349aa248b372f7bf2a777b001ea086ecd39478a7
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0002-Add-dwc_otg-driver.patch
1 From 344d6f31638c96846ac26f40a74ee1cc495f421e 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 002/196] 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                   |  172 +-
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          |  225 +
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, 56447 insertions(+), 49 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 diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
133 index c41feba..0b5c606 100644
134 --- a/drivers/usb/Makefile
135 +++ b/drivers/usb/Makefile
136 @@ -23,6 +23,7 @@ obj-$(CONFIG_USB_U132_HCD)    += host/
137  obj-$(CONFIG_USB_R8A66597_HCD) += host/
138  obj-$(CONFIG_USB_HWA_HCD)      += host/
139  obj-$(CONFIG_USB_ISP1760_HCD)  += host/
140 +obj-$(CONFIG_USB_DWCOTG)       += host/
141  obj-$(CONFIG_USB_IMX21_HCD)    += host/
142  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += host/
143  
144 diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
145 index acbfeb0..7d675c8 100644
146 --- a/drivers/usb/core/generic.c
147 +++ b/drivers/usb/core/generic.c
148 @@ -152,6 +152,7 @@ int usb_choose_configuration(struct usb_device *udev)
149                 dev_warn(&udev->dev,
150                         "no configuration chosen from %d choice%s\n",
151                         num_configs, plural(num_configs));
152 +               dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
153         }
154         return i;
155  }
156 diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
157 index 444d30e..3ff77fa 100644
158 --- a/drivers/usb/core/message.c
159 +++ b/drivers/usb/core/message.c
160 @@ -1875,6 +1875,85 @@ free_interfaces:
161         if (cp->string == NULL &&
162                         !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
163                 cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
164 +/* Uncomment this define to enable the HS Electrical Test support */
165 +#define DWC_HS_ELECT_TST 1
166 +#ifdef DWC_HS_ELECT_TST
167 +               /* Here we implement the HS Electrical Test support. The
168 +                * tester uses a vendor ID of 0x1A0A to indicate we should
169 +                * run a special test sequence. The product ID tells us
170 +                * which sequence to run. We invoke the test sequence by
171 +                * sending a non-standard SetFeature command to our root
172 +                * hub port. Our dwc_otg_hcd_hub_control() routine will
173 +                * recognize the command and perform the desired test
174 +                * sequence.
175 +                */
176 +               if (dev->descriptor.idVendor == 0x1A0A) {
177 +                       /* HSOTG Electrical Test */
178 +                       dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
179 +
180 +                       if (dev->bus && dev->bus->root_hub) {
181 +                               struct usb_device *hdev = dev->bus->root_hub;
182 +                               dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
183 +
184 +                               switch (dev->descriptor.idProduct) {
185 +                               case 0x0101:    /* TEST_SE0_NAK */
186 +                                       dev_warn(&dev->dev, "TEST_SE0_NAK\n");
187 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
188 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
189 +                                                       USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
190 +                                       break;
191 +
192 +                               case 0x0102:    /* TEST_J */
193 +                                       dev_warn(&dev->dev, "TEST_J\n");
194 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
195 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
196 +                                                       USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
197 +                                       break;
198 +
199 +                               case 0x0103:    /* TEST_K */
200 +                                       dev_warn(&dev->dev, "TEST_K\n");
201 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
202 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
203 +                                                       USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
204 +                                       break;
205 +
206 +                               case 0x0104:    /* TEST_PACKET */
207 +                                       dev_warn(&dev->dev, "TEST_PACKET\n");
208 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
209 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
210 +                                                       USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
211 +                                       break;
212 +
213 +                               case 0x0105:    /* TEST_FORCE_ENABLE */
214 +                                       dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
215 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
216 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
217 +                                                       USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
218 +                                       break;
219 +
220 +                               case 0x0106:    /* HS_HOST_PORT_SUSPEND_RESUME */
221 +                                       dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
222 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
223 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
224 +                                                       USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
225 +                                       break;
226 +
227 +                               case 0x0107:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
228 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
229 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
230 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
231 +                                                       USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
232 +                                       break;
233 +
234 +                               case 0x0108:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
235 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
236 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
237 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
238 +                                                       USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
239 +                               }
240 +                       }
241 +               }
242 +#endif /* DWC_HS_ELECT_TST */
243  
244         /* Now that the interfaces are installed, re-enable LPM. */
245         usb_unlocked_enable_lpm(dev);
246 diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
247 index e8cdce5..3a0da17 100644
248 --- a/drivers/usb/core/otg_whitelist.h
249 +++ b/drivers/usb/core/otg_whitelist.h
250 @@ -19,33 +19,82 @@
251  static struct usb_device_id whitelist_table [] = {
252  
253  /* hubs are optional in OTG, but very handy ... */
254 +#define CERT_WITHOUT_HUBS
255 +#if defined(CERT_WITHOUT_HUBS)
256 +{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
257 +#else
258  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
259  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
260 +{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
261 +#endif
262  
263  #ifdef CONFIG_USB_PRINTER              /* ignoring nonstatic linkage! */
264  /* FIXME actually, printers are NOT supposed to use device classes;
265   * they're supposed to use interface classes...
266   */
267 -{ USB_DEVICE_INFO(7, 1, 1) },
268 -{ USB_DEVICE_INFO(7, 1, 2) },
269 -{ USB_DEVICE_INFO(7, 1, 3) },
270 +//{ USB_DEVICE_INFO(7, 1, 1) },
271 +//{ USB_DEVICE_INFO(7, 1, 2) },
272 +//{ USB_DEVICE_INFO(7, 1, 3) },
273  #endif
274  
275  #ifdef CONFIG_USB_NET_CDCETHER
276  /* Linux-USB CDC Ethernet gadget */
277 -{ USB_DEVICE(0x0525, 0xa4a1), },
278 +//{ USB_DEVICE(0x0525, 0xa4a1), },
279  /* Linux-USB CDC Ethernet + RNDIS gadget */
280 -{ USB_DEVICE(0x0525, 0xa4a2), },
281 +//{ USB_DEVICE(0x0525, 0xa4a2), },
282  #endif
283  
284  #if    defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
285  /* gadget zero, for testing */
286 -{ USB_DEVICE(0x0525, 0xa4a0), },
287 +//{ USB_DEVICE(0x0525, 0xa4a0), },
288  #endif
289 +   
290 +/* OPT Tester */
291 +{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
292 +{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
293 +{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
294 +{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
295 +{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
296 +{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME  */
297 +{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
298 +{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
299 +
300 +/* Sony cameras */        
301 +{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
302 +   
303 +/* Memory Devices */
304 +//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
305 +//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
306 +//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
307 +//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD  */
308 +{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
309 +//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
310 +
311 +/* HP Printers */
312 +//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
313 +//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
314 +
315 +/* Speakers */
316 +//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
317 +//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
318  
319  { }    /* Terminating entry */
320  };
321  
322 +static inline void report_errors(struct usb_device *dev)
323 +{
324 +       /* OTG MESSAGE: report errors here, customize to match your product */
325 +       dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
326 +                le16_to_cpu(dev->descriptor.idVendor),
327 +                le16_to_cpu(dev->descriptor.idProduct));
328 +        if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
329 +                dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
330 +        } else {        
331 +                dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
332 +        }
333 +}
334 +
335 +
336  static int is_targeted(struct usb_device *dev)
337  {
338         struct usb_device_id    *id = whitelist_table;
339 @@ -55,58 +104,83 @@ static int is_targeted(struct usb_device *dev)
340                 return 1;
341  
342         /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
343 -       if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
344 -            le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
345 -               return 0;
346 -
347 -       /* NOTE: can't use usb_match_id() since interface caches
348 -        * aren't set up yet. this is cut/paste from that code.
349 -        */
350 -       for (id = whitelist_table; id->match_flags; id++) {
351 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
352 -                   id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
353 -                       continue;
354 -
355 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
356 -                   id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
357 -                       continue;
358 -
359 -               /* No need to test id->bcdDevice_lo != 0, since 0 is never
360 -                  greater than any unsigned number. */
361 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
362 -                   (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
363 -                       continue;
364 -
365 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
366 -                   (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
367 -                       continue;
368 -
369 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
370 -                   (id->bDeviceClass != dev->descriptor.bDeviceClass))
371 -                       continue;
372 -
373 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
374 -                   (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
375 -                       continue;
376 -
377 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
378 -                   (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
379 -                       continue;
380 +       if (dev->descriptor.idVendor == 0x1a0a && 
381 +            dev->descriptor.idProduct == 0xbadd) {
382 +                return 0;
383 +       } else if (!enable_whitelist) {
384 +               return 1;
385 +        } else {
386 +
387 +#ifdef DEBUG
388 +                dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
389 +                        dev->descriptor.idVendor,
390 +                        dev->descriptor.idProduct,
391 +                        dev->descriptor.bDeviceClass,
392 +                        dev->descriptor.bDeviceSubClass,
393 +                        dev->descriptor.bDeviceProtocol);
394 +#endif
395  
396                 return 1;
397 +               /* NOTE: can't use usb_match_id() since interface caches
398 +                * aren't set up yet. this is cut/paste from that code.
399 +                */
400 +               for (id = whitelist_table; id->match_flags; id++) {
401 +#ifdef DEBUG
402 +                       dev_dbg(&dev->dev, 
403 +                               "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
404 +                               id->idVendor,
405 +                               id->idProduct,
406 +                               id->bDeviceClass,
407 +                               id->bDeviceSubClass,
408 +                               id->bDeviceProtocol);
409 +#endif                       
410 +
411 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
412 +                           id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
413 +                               continue;
414 +
415 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
416 +                           id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
417 +                               continue;
418 +
419 +                       /* No need to test id->bcdDevice_lo != 0, since 0 is never
420 +                          greater than any unsigned number. */
421 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
422 +                           (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
423 +                               continue;
424 +
425 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
426 +                           (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
427 +                               continue;
428 +
429 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
430 +                           (id->bDeviceClass != dev->descriptor.bDeviceClass))
431 +                               continue;
432 +
433 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
434 +                           (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
435 +                               continue;
436 +
437 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
438 +                           (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
439 +                               continue;
440 +
441 +                       return 1;
442 +               }
443         }
444  
445         /* add other match criteria here ... */
446  
447 -
448 -       /* OTG MESSAGE: report errors here, customize to match your product */
449 -       dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
450 -               le16_to_cpu(dev->descriptor.idVendor),
451 -               le16_to_cpu(dev->descriptor.idProduct));
452  #ifdef CONFIG_USB_OTG_WHITELIST
453 +       report_errors(dev);
454         return 0;
455  #else
456 -       return 1;
457 +       if (enable_whitelist) {
458 +               report_errors(dev);
459 +               return 0;
460 +       } else {
461 +               return 1;
462 +       }
463  #endif
464  }
465  
466 diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
467 new file mode 100644
468 index 0000000..a896d73
469 --- /dev/null
470 +++ b/drivers/usb/gadget/file_storage.c
471 @@ -0,0 +1,3676 @@
472 +/*
473 + * file_storage.c -- File-backed USB Storage Gadget, for USB development
474 + *
475 + * Copyright (C) 2003-2008 Alan Stern
476 + * All rights reserved.
477 + *
478 + * Redistribution and use in source and binary forms, with or without
479 + * modification, are permitted provided that the following conditions
480 + * are met:
481 + * 1. Redistributions of source code must retain the above copyright
482 + *    notice, this list of conditions, and the following disclaimer,
483 + *    without modification.
484 + * 2. Redistributions in binary form must reproduce the above copyright
485 + *    notice, this list of conditions and the following disclaimer in the
486 + *    documentation and/or other materials provided with the distribution.
487 + * 3. The names of the above-listed copyright holders may not be used
488 + *    to endorse or promote products derived from this software without
489 + *    specific prior written permission.
490 + *
491 + * ALTERNATIVELY, this software may be distributed under the terms of the
492 + * GNU General Public License ("GPL") as published by the Free Software
493 + * Foundation, either version 2 of that License or (at your option) any
494 + * later version.
495 + *
496 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
497 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
498 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
499 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
500 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
501 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
502 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
503 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
504 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
505 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
506 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
507 + */
508 +
509 +
510 +/*
511 + * The File-backed Storage Gadget acts as a USB Mass Storage device,
512 + * appearing to the host as a disk drive or as a CD-ROM drive.  In addition
513 + * to providing an example of a genuinely useful gadget driver for a USB
514 + * device, it also illustrates a technique of double-buffering for increased
515 + * throughput.  Last but not least, it gives an easy way to probe the
516 + * behavior of the Mass Storage drivers in a USB host.
517 + *
518 + * Backing storage is provided by a regular file or a block device, specified
519 + * by the "file" module parameter.  Access can be limited to read-only by
520 + * setting the optional "ro" module parameter.  (For CD-ROM emulation,
521 + * access is always read-only.)  The gadget will indicate that it has
522 + * removable media if the optional "removable" module parameter is set.
523 + *
524 + * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
525 + * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
526 + * by the optional "transport" module parameter.  It also supports the
527 + * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
528 + * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
529 + * the optional "protocol" module parameter.  In addition, the default
530 + * Vendor ID, Product ID, release number and serial number can be overridden.
531 + *
532 + * There is support for multiple logical units (LUNs), each of which has
533 + * its own backing file.  The number of LUNs can be set using the optional
534 + * "luns" module parameter (anywhere from 1 to 8), and the corresponding
535 + * files are specified using comma-separated lists for "file" and "ro".
536 + * The default number of LUNs is taken from the number of "file" elements;
537 + * it is 1 if "file" is not given.  If "removable" is not set then a backing
538 + * file must be specified for each LUN.  If it is set, then an unspecified
539 + * or empty backing filename means the LUN's medium is not loaded.  Ideally
540 + * each LUN would be settable independently as a disk drive or a CD-ROM
541 + * drive, but currently all LUNs have to be the same type.  The CD-ROM
542 + * emulation includes a single data track and no audio tracks; hence there
543 + * need be only one backing file per LUN.
544 + *
545 + * Requirements are modest; only a bulk-in and a bulk-out endpoint are
546 + * needed (an interrupt-out endpoint is also needed for CBI).  The memory
547 + * requirement amounts to two 16K buffers, size configurable by a parameter.
548 + * Support is included for both full-speed and high-speed operation.
549 + *
550 + * Note that the driver is slightly non-portable in that it assumes a
551 + * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
552 + * interrupt-in endpoints.  With most device controllers this isn't an
553 + * issue, but there may be some with hardware restrictions that prevent
554 + * a buffer from being used by more than one endpoint.
555 + *
556 + * Module options:
557 + *
558 + *     file=filename[,filename...]
559 + *                             Required if "removable" is not set, names of
560 + *                                     the files or block devices used for
561 + *                                     backing storage
562 + *     serial=HHHH...          Required serial number (string of hex chars)
563 + *     ro=b[,b...]             Default false, booleans for read-only access
564 + *     removable               Default false, boolean for removable media
565 + *     luns=N                  Default N = number of filenames, number of
566 + *                                     LUNs to support
567 + *     nofua=b[,b...]          Default false, booleans for ignore FUA flag
568 + *                                     in SCSI WRITE(10,12) commands
569 + *     stall                   Default determined according to the type of
570 + *                                     USB device controller (usually true),
571 + *                                     boolean to permit the driver to halt
572 + *                                     bulk endpoints
573 + *     cdrom                   Default false, boolean for whether to emulate
574 + *                                     a CD-ROM drive
575 + *     transport=XXX           Default BBB, transport name (CB, CBI, or BBB)
576 + *     protocol=YYY            Default SCSI, protocol name (RBC, 8020 or
577 + *                                     ATAPI, QIC, UFI, 8070, or SCSI;
578 + *                                     also 1 - 6)
579 + *     vendor=0xVVVV           Default 0x0525 (NetChip), USB Vendor ID
580 + *     product=0xPPPP          Default 0xa4a5 (FSG), USB Product ID
581 + *     release=0xRRRR          Override the USB release number (bcdDevice)
582 + *     buflen=N                Default N=16384, buffer size used (will be
583 + *                                     rounded down to a multiple of
584 + *                                     PAGE_CACHE_SIZE)
585 + *
586 + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
587 + * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
588 + * default values are used for everything else.
589 + *
590 + * The pathnames of the backing files and the ro settings are available in
591 + * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
592 + * the gadget's sysfs directory.  If the "removable" option is set, writing to
593 + * these files will simulate ejecting/loading the medium (writing an empty
594 + * line means eject) and adjusting a write-enable tab.  Changes to the ro
595 + * setting are not allowed when the medium is loaded or if CD-ROM emulation
596 + * is being used.
597 + *
598 + * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
599 + * The driver's SCSI command interface was based on the "Information
600 + * technology - Small Computer System Interface - 2" document from
601 + * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
602 + * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception
603 + * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
604 + * "Universal Serial Bus Mass Storage Class UFI Command Specification"
605 + * document, Revision 1.0, December 14, 1998, available at
606 + * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
607 + */
608 +
609 +
610 +/*
611 + *                             Driver Design
612 + *
613 + * The FSG driver is fairly straightforward.  There is a main kernel
614 + * thread that handles most of the work.  Interrupt routines field
615 + * callbacks from the controller driver: bulk- and interrupt-request
616 + * completion notifications, endpoint-0 events, and disconnect events.
617 + * Completion events are passed to the main thread by wakeup calls.  Many
618 + * ep0 requests are handled at interrupt time, but SetInterface,
619 + * SetConfiguration, and device reset requests are forwarded to the
620 + * thread in the form of "exceptions" using SIGUSR1 signals (since they
621 + * should interrupt any ongoing file I/O operations).
622 + *
623 + * The thread's main routine implements the standard command/data/status
624 + * parts of a SCSI interaction.  It and its subroutines are full of tests
625 + * for pending signals/exceptions -- all this polling is necessary since
626 + * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
627 + * indication that the driver really wants to be running in userspace.)
628 + * An important point is that so long as the thread is alive it keeps an
629 + * open reference to the backing file.  This will prevent unmounting
630 + * the backing file's underlying filesystem and could cause problems
631 + * during system shutdown, for example.  To prevent such problems, the
632 + * thread catches INT, TERM, and KILL signals and converts them into
633 + * an EXIT exception.
634 + *
635 + * In normal operation the main thread is started during the gadget's
636 + * fsg_bind() callback and stopped during fsg_unbind().  But it can also
637 + * exit when it receives a signal, and there's no point leaving the
638 + * gadget running when the thread is dead.  So just before the thread
639 + * exits, it deregisters the gadget driver.  This makes things a little
640 + * tricky: The driver is deregistered at two places, and the exiting
641 + * thread can indirectly call fsg_unbind() which in turn can tell the
642 + * thread to exit.  The first problem is resolved through the use of the
643 + * REGISTERED atomic bitflag; the driver will only be deregistered once.
644 + * The second problem is resolved by having fsg_unbind() check
645 + * fsg->state; it won't try to stop the thread if the state is already
646 + * FSG_STATE_TERMINATED.
647 + *
648 + * To provide maximum throughput, the driver uses a circular pipeline of
649 + * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
650 + * arbitrarily long; in practice the benefits don't justify having more
651 + * than 2 stages (i.e., double buffering).  But it helps to think of the
652 + * pipeline as being a long one.  Each buffer head contains a bulk-in and
653 + * a bulk-out request pointer (since the buffer can be used for both
654 + * output and input -- directions always are given from the host's
655 + * point of view) as well as a pointer to the buffer and various state
656 + * variables.
657 + *
658 + * Use of the pipeline follows a simple protocol.  There is a variable
659 + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
660 + * At any time that buffer head may still be in use from an earlier
661 + * request, so each buffer head has a state variable indicating whether
662 + * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
663 + * buffer head to be EMPTY, filling the buffer either by file I/O or by
664 + * USB I/O (during which the buffer head is BUSY), and marking the buffer
665 + * head FULL when the I/O is complete.  Then the buffer will be emptied
666 + * (again possibly by USB I/O, during which it is marked BUSY) and
667 + * finally marked EMPTY again (possibly by a completion routine).
668 + *
669 + * A module parameter tells the driver to avoid stalling the bulk
670 + * endpoints wherever the transport specification allows.  This is
671 + * necessary for some UDCs like the SuperH, which cannot reliably clear a
672 + * halt on a bulk endpoint.  However, under certain circumstances the
673 + * Bulk-only specification requires a stall.  In such cases the driver
674 + * will halt the endpoint and set a flag indicating that it should clear
675 + * the halt in software during the next device reset.  Hopefully this
676 + * will permit everything to work correctly.  Furthermore, although the
677 + * specification allows the bulk-out endpoint to halt when the host sends
678 + * too much data, implementing this would cause an unavoidable race.
679 + * The driver will always use the "no-stall" approach for OUT transfers.
680 + *
681 + * One subtle point concerns sending status-stage responses for ep0
682 + * requests.  Some of these requests, such as device reset, can involve
683 + * interrupting an ongoing file I/O operation, which might take an
684 + * arbitrarily long time.  During that delay the host might give up on
685 + * the original ep0 request and issue a new one.  When that happens the
686 + * driver should not notify the host about completion of the original
687 + * request, as the host will no longer be waiting for it.  So the driver
688 + * assigns to each ep0 request a unique tag, and it keeps track of the
689 + * tag value of the request associated with a long-running exception
690 + * (device-reset, interface-change, or configuration-change).  When the
691 + * exception handler is finished, the status-stage response is submitted
692 + * only if the current ep0 request tag is equal to the exception request
693 + * tag.  Thus only the most recently received ep0 request will get a
694 + * status-stage response.
695 + *
696 + * Warning: This driver source file is too long.  It ought to be split up
697 + * into a header file plus about 3 separate .c files, to handle the details
698 + * of the Gadget, USB Mass Storage, and SCSI protocols.
699 + */
700 +
701 +
702 +/* #define VERBOSE_DEBUG */
703 +/* #define DUMP_MSGS */
704 +
705 +
706 +#include <linux/blkdev.h>
707 +#include <linux/completion.h>
708 +#include <linux/dcache.h>
709 +#include <linux/delay.h>
710 +#include <linux/device.h>
711 +#include <linux/fcntl.h>
712 +#include <linux/file.h>
713 +#include <linux/fs.h>
714 +#include <linux/kref.h>
715 +#include <linux/kthread.h>
716 +#include <linux/limits.h>
717 +#include <linux/module.h>
718 +#include <linux/rwsem.h>
719 +#include <linux/slab.h>
720 +#include <linux/spinlock.h>
721 +#include <linux/string.h>
722 +#include <linux/freezer.h>
723 +#include <linux/utsname.h>
724 +
725 +#include <linux/usb/ch9.h>
726 +#include <linux/usb/gadget.h>
727 +
728 +#include "gadget_chips.h"
729 +
730 +
731 +
732 +/*
733 + * Kbuild is not very cooperative with respect to linking separately
734 + * compiled library objects into one module.  So for now we won't use
735 + * separate compilation ... ensuring init/exit sections work to shrink
736 + * the runtime footprint, and giving us at least some parts of what
737 + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
738 + */
739 +#include "usbstring.c"
740 +#include "config.c"
741 +#include "epautoconf.c"
742 +
743 +/*-------------------------------------------------------------------------*/
744 +
745 +#define DRIVER_DESC            "File-backed Storage Gadget"
746 +#define DRIVER_NAME            "g_file_storage"
747 +#define DRIVER_VERSION         "1 September 2010"
748 +
749 +static       char fsg_string_manufacturer[64];
750 +static const char fsg_string_product[] = DRIVER_DESC;
751 +static const char fsg_string_config[] = "Self-powered";
752 +static const char fsg_string_interface[] = "Mass Storage";
753 +
754 +
755 +#include "storage_common.c"
756 +
757 +
758 +MODULE_DESCRIPTION(DRIVER_DESC);
759 +MODULE_AUTHOR("Alan Stern");
760 +MODULE_LICENSE("Dual BSD/GPL");
761 +
762 +/*
763 + * This driver assumes self-powered hardware and has no way for users to
764 + * trigger remote wakeup.  It uses autoconfiguration to select endpoints
765 + * and endpoint addresses.
766 + */
767 +
768 +
769 +/*-------------------------------------------------------------------------*/
770 +
771 +
772 +/* Encapsulate the module parameter settings */
773 +
774 +static struct {
775 +       char            *file[FSG_MAX_LUNS];
776 +       char            *serial;
777 +       bool            ro[FSG_MAX_LUNS];
778 +       bool            nofua[FSG_MAX_LUNS];
779 +       unsigned int    num_filenames;
780 +       unsigned int    num_ros;
781 +       unsigned int    num_nofuas;
782 +       unsigned int    nluns;
783 +
784 +       bool            removable;
785 +       bool            can_stall;
786 +       bool            cdrom;
787 +
788 +       char            *transport_parm;
789 +       char            *protocol_parm;
790 +       unsigned short  vendor;
791 +       unsigned short  product;
792 +       unsigned short  release;
793 +       unsigned int    buflen;
794 +
795 +       int             transport_type;
796 +       char            *transport_name;
797 +       int             protocol_type;
798 +       char            *protocol_name;
799 +
800 +} mod_data = {                                 // Default values
801 +       .transport_parm         = "BBB",
802 +       .protocol_parm          = "SCSI",
803 +       .removable              = 0,
804 +       .can_stall              = 1,
805 +       .cdrom                  = 0,
806 +       .vendor                 = FSG_VENDOR_ID,
807 +       .product                = FSG_PRODUCT_ID,
808 +       .release                = 0xffff,       // Use controller chip type
809 +       .buflen                 = 16384,
810 +       };
811 +
812 +
813 +module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
814 +               S_IRUGO);
815 +MODULE_PARM_DESC(file, "names of backing files or devices");
816 +
817 +module_param_named(serial, mod_data.serial, charp, S_IRUGO);
818 +MODULE_PARM_DESC(serial, "USB serial number");
819 +
820 +module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
821 +MODULE_PARM_DESC(ro, "true to force read-only");
822 +
823 +module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
824 +               S_IRUGO);
825 +MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
826 +
827 +module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
828 +MODULE_PARM_DESC(luns, "number of LUNs");
829 +
830 +module_param_named(removable, mod_data.removable, bool, S_IRUGO);
831 +MODULE_PARM_DESC(removable, "true to simulate removable media");
832 +
833 +module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
834 +MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
835 +
836 +module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
837 +MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
838 +
839 +/* In the non-TEST version, only the module parameters listed above
840 + * are available. */
841 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
842 +
843 +module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
844 +MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
845 +
846 +module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
847 +MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
848 +               "8070, or SCSI)");
849 +
850 +module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
851 +MODULE_PARM_DESC(vendor, "USB Vendor ID");
852 +
853 +module_param_named(product, mod_data.product, ushort, S_IRUGO);
854 +MODULE_PARM_DESC(product, "USB Product ID");
855 +
856 +module_param_named(release, mod_data.release, ushort, S_IRUGO);
857 +MODULE_PARM_DESC(release, "USB release number");
858 +
859 +module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
860 +MODULE_PARM_DESC(buflen, "I/O buffer size");
861 +
862 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
863 +
864 +
865 +/*
866 + * These definitions will permit the compiler to avoid generating code for
867 + * parts of the driver that aren't used in the non-TEST version.  Even gcc
868 + * can recognize when a test of a constant expression yields a dead code
869 + * path.
870 + */
871 +
872 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
873 +
874 +#define transport_is_bbb()     (mod_data.transport_type == USB_PR_BULK)
875 +#define transport_is_cbi()     (mod_data.transport_type == USB_PR_CBI)
876 +#define protocol_is_scsi()     (mod_data.protocol_type == USB_SC_SCSI)
877 +
878 +#else
879 +
880 +#define transport_is_bbb()     1
881 +#define transport_is_cbi()     0
882 +#define protocol_is_scsi()     1
883 +
884 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
885 +
886 +
887 +/*-------------------------------------------------------------------------*/
888 +
889 +
890 +struct fsg_dev {
891 +       /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
892 +       spinlock_t              lock;
893 +       struct usb_gadget       *gadget;
894 +
895 +       /* filesem protects: backing files in use */
896 +       struct rw_semaphore     filesem;
897 +
898 +       /* reference counting: wait until all LUNs are released */
899 +       struct kref             ref;
900 +
901 +       struct usb_ep           *ep0;           // Handy copy of gadget->ep0
902 +       struct usb_request      *ep0req;        // For control responses
903 +       unsigned int            ep0_req_tag;
904 +       const char              *ep0req_name;
905 +
906 +       struct usb_request      *intreq;        // For interrupt responses
907 +       int                     intreq_busy;
908 +       struct fsg_buffhd       *intr_buffhd;
909 +
910 +       unsigned int            bulk_out_maxpacket;
911 +       enum fsg_state          state;          // For exception handling
912 +       unsigned int            exception_req_tag;
913 +
914 +       u8                      config, new_config;
915 +
916 +       unsigned int            running : 1;
917 +       unsigned int            bulk_in_enabled : 1;
918 +       unsigned int            bulk_out_enabled : 1;
919 +       unsigned int            intr_in_enabled : 1;
920 +       unsigned int            phase_error : 1;
921 +       unsigned int            short_packet_received : 1;
922 +       unsigned int            bad_lun_okay : 1;
923 +
924 +       unsigned long           atomic_bitflags;
925 +#define REGISTERED             0
926 +#define IGNORE_BULK_OUT                1
927 +#define SUSPENDED              2
928 +
929 +       struct usb_ep           *bulk_in;
930 +       struct usb_ep           *bulk_out;
931 +       struct usb_ep           *intr_in;
932 +
933 +       struct fsg_buffhd       *next_buffhd_to_fill;
934 +       struct fsg_buffhd       *next_buffhd_to_drain;
935 +
936 +       int                     thread_wakeup_needed;
937 +       struct completion       thread_notifier;
938 +       struct task_struct      *thread_task;
939 +
940 +       int                     cmnd_size;
941 +       u8                      cmnd[MAX_COMMAND_SIZE];
942 +       enum data_direction     data_dir;
943 +       u32                     data_size;
944 +       u32                     data_size_from_cmnd;
945 +       u32                     tag;
946 +       unsigned int            lun;
947 +       u32                     residue;
948 +       u32                     usb_amount_left;
949 +
950 +       /* The CB protocol offers no way for a host to know when a command
951 +        * has completed.  As a result the next command may arrive early,
952 +        * and we will still have to handle it.  For that reason we need
953 +        * a buffer to store new commands when using CB (or CBI, which
954 +        * does not oblige a host to wait for command completion either). */
955 +       int                     cbbuf_cmnd_size;
956 +       u8                      cbbuf_cmnd[MAX_COMMAND_SIZE];
957 +
958 +       unsigned int            nluns;
959 +       struct fsg_lun          *luns;
960 +       struct fsg_lun          *curlun;
961 +       /* Must be the last entry */
962 +       struct fsg_buffhd       buffhds[];
963 +};
964 +
965 +typedef void (*fsg_routine_t)(struct fsg_dev *);
966 +
967 +static int exception_in_progress(struct fsg_dev *fsg)
968 +{
969 +       return (fsg->state > FSG_STATE_IDLE);
970 +}
971 +
972 +/* Make bulk-out requests be divisible by the maxpacket size */
973 +static void set_bulk_out_req_length(struct fsg_dev *fsg,
974 +               struct fsg_buffhd *bh, unsigned int length)
975 +{
976 +       unsigned int    rem;
977 +
978 +       bh->bulk_out_intended_length = length;
979 +       rem = length % fsg->bulk_out_maxpacket;
980 +       if (rem > 0)
981 +               length += fsg->bulk_out_maxpacket - rem;
982 +       bh->outreq->length = length;
983 +}
984 +
985 +static struct fsg_dev                  *the_fsg;
986 +static struct usb_gadget_driver                fsg_driver;
987 +
988 +
989 +/*-------------------------------------------------------------------------*/
990 +
991 +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
992 +{
993 +       const char      *name;
994 +
995 +       if (ep == fsg->bulk_in)
996 +               name = "bulk-in";
997 +       else if (ep == fsg->bulk_out)
998 +               name = "bulk-out";
999 +       else
1000 +               name = ep->name;
1001 +       DBG(fsg, "%s set halt\n", name);
1002 +       return usb_ep_set_halt(ep);
1003 +}
1004 +
1005 +
1006 +/*-------------------------------------------------------------------------*/
1007 +
1008 +/*
1009 + * DESCRIPTORS ... most are static, but strings and (full) configuration
1010 + * descriptors are built on demand.  Also the (static) config and interface
1011 + * descriptors are adjusted during fsg_bind().
1012 + */
1013 +
1014 +/* There is only one configuration. */
1015 +#define        CONFIG_VALUE            1
1016 +
1017 +static struct usb_device_descriptor
1018 +device_desc = {
1019 +       .bLength =              sizeof device_desc,
1020 +       .bDescriptorType =      USB_DT_DEVICE,
1021 +
1022 +       .bcdUSB =               cpu_to_le16(0x0200),
1023 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
1024 +
1025 +       /* The next three values can be overridden by module parameters */
1026 +       .idVendor =             cpu_to_le16(FSG_VENDOR_ID),
1027 +       .idProduct =            cpu_to_le16(FSG_PRODUCT_ID),
1028 +       .bcdDevice =            cpu_to_le16(0xffff),
1029 +
1030 +       .iManufacturer =        FSG_STRING_MANUFACTURER,
1031 +       .iProduct =             FSG_STRING_PRODUCT,
1032 +       .iSerialNumber =        FSG_STRING_SERIAL,
1033 +       .bNumConfigurations =   1,
1034 +};
1035 +
1036 +static struct usb_config_descriptor
1037 +config_desc = {
1038 +       .bLength =              sizeof config_desc,
1039 +       .bDescriptorType =      USB_DT_CONFIG,
1040 +
1041 +       /* wTotalLength computed by usb_gadget_config_buf() */
1042 +       .bNumInterfaces =       1,
1043 +       .bConfigurationValue =  CONFIG_VALUE,
1044 +       .iConfiguration =       FSG_STRING_CONFIG,
1045 +       .bmAttributes =         USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
1046 +       .bMaxPower =            CONFIG_USB_GADGET_VBUS_DRAW / 2,
1047 +};
1048 +
1049 +
1050 +static struct usb_qualifier_descriptor
1051 +dev_qualifier = {
1052 +       .bLength =              sizeof dev_qualifier,
1053 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
1054 +
1055 +       .bcdUSB =               cpu_to_le16(0x0200),
1056 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
1057 +
1058 +       .bNumConfigurations =   1,
1059 +};
1060 +
1061 +static int populate_bos(struct fsg_dev *fsg, u8 *buf)
1062 +{
1063 +       memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
1064 +       buf += USB_DT_BOS_SIZE;
1065 +
1066 +       memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
1067 +       buf += USB_DT_USB_EXT_CAP_SIZE;
1068 +
1069 +       memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
1070 +
1071 +       return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
1072 +               + USB_DT_USB_EXT_CAP_SIZE;
1073 +}
1074 +
1075 +/*
1076 + * Config descriptors must agree with the code that sets configurations
1077 + * and with code managing interfaces and their altsettings.  They must
1078 + * also handle different speeds and other-speed requests.
1079 + */
1080 +static int populate_config_buf(struct usb_gadget *gadget,
1081 +               u8 *buf, u8 type, unsigned index)
1082 +{
1083 +       enum usb_device_speed                   speed = gadget->speed;
1084 +       int                                     len;
1085 +       const struct usb_descriptor_header      **function;
1086 +
1087 +       if (index > 0)
1088 +               return -EINVAL;
1089 +
1090 +       if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
1091 +               speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
1092 +       function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
1093 +               ? (const struct usb_descriptor_header **)fsg_hs_function
1094 +               : (const struct usb_descriptor_header **)fsg_fs_function;
1095 +
1096 +       /* for now, don't advertise srp-only devices */
1097 +       if (!gadget_is_otg(gadget))
1098 +               function++;
1099 +
1100 +       len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
1101 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
1102 +       return len;
1103 +}
1104 +
1105 +
1106 +/*-------------------------------------------------------------------------*/
1107 +
1108 +/* These routines may be called in process context or in_irq */
1109 +
1110 +/* Caller must hold fsg->lock */
1111 +static void wakeup_thread(struct fsg_dev *fsg)
1112 +{
1113 +       /* Tell the main thread that something has happened */
1114 +       fsg->thread_wakeup_needed = 1;
1115 +       if (fsg->thread_task)
1116 +               wake_up_process(fsg->thread_task);
1117 +}
1118 +
1119 +
1120 +static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
1121 +{
1122 +       unsigned long           flags;
1123 +
1124 +       /* Do nothing if a higher-priority exception is already in progress.
1125 +        * If a lower-or-equal priority exception is in progress, preempt it
1126 +        * and notify the main thread by sending it a signal. */
1127 +       spin_lock_irqsave(&fsg->lock, flags);
1128 +       if (fsg->state <= new_state) {
1129 +               fsg->exception_req_tag = fsg->ep0_req_tag;
1130 +               fsg->state = new_state;
1131 +               if (fsg->thread_task)
1132 +                       send_sig_info(SIGUSR1, SEND_SIG_FORCED,
1133 +                                       fsg->thread_task);
1134 +       }
1135 +       spin_unlock_irqrestore(&fsg->lock, flags);
1136 +}
1137 +
1138 +
1139 +/*-------------------------------------------------------------------------*/
1140 +
1141 +/* The disconnect callback and ep0 routines.  These always run in_irq,
1142 + * except that ep0_queue() is called in the main thread to acknowledge
1143 + * completion of various requests: set config, set interface, and
1144 + * Bulk-only device reset. */
1145 +
1146 +static void fsg_disconnect(struct usb_gadget *gadget)
1147 +{
1148 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
1149 +
1150 +       DBG(fsg, "disconnect or port reset\n");
1151 +       raise_exception(fsg, FSG_STATE_DISCONNECT);
1152 +}
1153 +
1154 +
1155 +static int ep0_queue(struct fsg_dev *fsg)
1156 +{
1157 +       int     rc;
1158 +
1159 +       rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
1160 +       if (rc != 0 && rc != -ESHUTDOWN) {
1161 +
1162 +               /* We can't do much more than wait for a reset */
1163 +               WARNING(fsg, "error in submission: %s --> %d\n",
1164 +                               fsg->ep0->name, rc);
1165 +       }
1166 +       return rc;
1167 +}
1168 +
1169 +static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
1170 +{
1171 +       struct fsg_dev          *fsg = ep->driver_data;
1172 +
1173 +       if (req->actual > 0)
1174 +               dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
1175 +       if (req->status || req->actual != req->length)
1176 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1177 +                               req->status, req->actual, req->length);
1178 +       if (req->status == -ECONNRESET)         // Request was cancelled
1179 +               usb_ep_fifo_flush(ep);
1180 +
1181 +       if (req->status == 0 && req->context)
1182 +               ((fsg_routine_t) (req->context))(fsg);
1183 +}
1184 +
1185 +
1186 +/*-------------------------------------------------------------------------*/
1187 +
1188 +/* Bulk and interrupt endpoint completion handlers.
1189 + * These always run in_irq. */
1190 +
1191 +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
1192 +{
1193 +       struct fsg_dev          *fsg = ep->driver_data;
1194 +       struct fsg_buffhd       *bh = req->context;
1195 +
1196 +       if (req->status || req->actual != req->length)
1197 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1198 +                               req->status, req->actual, req->length);
1199 +       if (req->status == -ECONNRESET)         // Request was cancelled
1200 +               usb_ep_fifo_flush(ep);
1201 +
1202 +       /* Hold the lock while we update the request and buffer states */
1203 +       smp_wmb();
1204 +       spin_lock(&fsg->lock);
1205 +       bh->inreq_busy = 0;
1206 +       bh->state = BUF_STATE_EMPTY;
1207 +       wakeup_thread(fsg);
1208 +       spin_unlock(&fsg->lock);
1209 +}
1210 +
1211 +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
1212 +{
1213 +       struct fsg_dev          *fsg = ep->driver_data;
1214 +       struct fsg_buffhd       *bh = req->context;
1215 +
1216 +       dump_msg(fsg, "bulk-out", req->buf, req->actual);
1217 +       if (req->status || req->actual != bh->bulk_out_intended_length)
1218 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1219 +                               req->status, req->actual,
1220 +                               bh->bulk_out_intended_length);
1221 +       if (req->status == -ECONNRESET)         // Request was cancelled
1222 +               usb_ep_fifo_flush(ep);
1223 +
1224 +       /* Hold the lock while we update the request and buffer states */
1225 +       smp_wmb();
1226 +       spin_lock(&fsg->lock);
1227 +       bh->outreq_busy = 0;
1228 +       bh->state = BUF_STATE_FULL;
1229 +       wakeup_thread(fsg);
1230 +       spin_unlock(&fsg->lock);
1231 +}
1232 +
1233 +
1234 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1235 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1236 +{
1237 +       struct fsg_dev          *fsg = ep->driver_data;
1238 +       struct fsg_buffhd       *bh = req->context;
1239 +
1240 +       if (req->status || req->actual != req->length)
1241 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1242 +                               req->status, req->actual, req->length);
1243 +       if (req->status == -ECONNRESET)         // Request was cancelled
1244 +               usb_ep_fifo_flush(ep);
1245 +
1246 +       /* Hold the lock while we update the request and buffer states */
1247 +       smp_wmb();
1248 +       spin_lock(&fsg->lock);
1249 +       fsg->intreq_busy = 0;
1250 +       bh->state = BUF_STATE_EMPTY;
1251 +       wakeup_thread(fsg);
1252 +       spin_unlock(&fsg->lock);
1253 +}
1254 +
1255 +#else
1256 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1257 +{}
1258 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1259 +
1260 +
1261 +/*-------------------------------------------------------------------------*/
1262 +
1263 +/* Ep0 class-specific handlers.  These always run in_irq. */
1264 +
1265 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1266 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1267 +{
1268 +       struct usb_request      *req = fsg->ep0req;
1269 +       static u8               cbi_reset_cmnd[6] = {
1270 +                       SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
1271 +
1272 +       /* Error in command transfer? */
1273 +       if (req->status || req->length != req->actual ||
1274 +                       req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
1275 +
1276 +               /* Not all controllers allow a protocol stall after
1277 +                * receiving control-out data, but we'll try anyway. */
1278 +               fsg_set_halt(fsg, fsg->ep0);
1279 +               return;                 // Wait for reset
1280 +       }
1281 +
1282 +       /* Is it the special reset command? */
1283 +       if (req->actual >= sizeof cbi_reset_cmnd &&
1284 +                       memcmp(req->buf, cbi_reset_cmnd,
1285 +                               sizeof cbi_reset_cmnd) == 0) {
1286 +
1287 +               /* Raise an exception to stop the current operation
1288 +                * and reinitialize our state. */
1289 +               DBG(fsg, "cbi reset request\n");
1290 +               raise_exception(fsg, FSG_STATE_RESET);
1291 +               return;
1292 +       }
1293 +
1294 +       VDBG(fsg, "CB[I] accept device-specific command\n");
1295 +       spin_lock(&fsg->lock);
1296 +
1297 +       /* Save the command for later */
1298 +       if (fsg->cbbuf_cmnd_size)
1299 +               WARNING(fsg, "CB[I] overwriting previous command\n");
1300 +       fsg->cbbuf_cmnd_size = req->actual;
1301 +       memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
1302 +
1303 +       wakeup_thread(fsg);
1304 +       spin_unlock(&fsg->lock);
1305 +}
1306 +
1307 +#else
1308 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1309 +{}
1310 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1311 +
1312 +
1313 +static int class_setup_req(struct fsg_dev *fsg,
1314 +               const struct usb_ctrlrequest *ctrl)
1315 +{
1316 +       struct usb_request      *req = fsg->ep0req;
1317 +       int                     value = -EOPNOTSUPP;
1318 +       u16                     w_index = le16_to_cpu(ctrl->wIndex);
1319 +       u16                     w_value = le16_to_cpu(ctrl->wValue);
1320 +       u16                     w_length = le16_to_cpu(ctrl->wLength);
1321 +
1322 +       if (!fsg->config)
1323 +               return value;
1324 +
1325 +       /* Handle Bulk-only class-specific requests */
1326 +       if (transport_is_bbb()) {
1327 +               switch (ctrl->bRequest) {
1328 +
1329 +               case US_BULK_RESET_REQUEST:
1330 +                       if (ctrl->bRequestType != (USB_DIR_OUT |
1331 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1332 +                               break;
1333 +                       if (w_index != 0 || w_value != 0 || w_length != 0) {
1334 +                               value = -EDOM;
1335 +                               break;
1336 +                       }
1337 +
1338 +                       /* Raise an exception to stop the current operation
1339 +                        * and reinitialize our state. */
1340 +                       DBG(fsg, "bulk reset request\n");
1341 +                       raise_exception(fsg, FSG_STATE_RESET);
1342 +                       value = DELAYED_STATUS;
1343 +                       break;
1344 +
1345 +               case US_BULK_GET_MAX_LUN:
1346 +                       if (ctrl->bRequestType != (USB_DIR_IN |
1347 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1348 +                               break;
1349 +                       if (w_index != 0 || w_value != 0 || w_length != 1) {
1350 +                               value = -EDOM;
1351 +                               break;
1352 +                       }
1353 +                       VDBG(fsg, "get max LUN\n");
1354 +                       *(u8 *) req->buf = fsg->nluns - 1;
1355 +                       value = 1;
1356 +                       break;
1357 +               }
1358 +       }
1359 +
1360 +       /* Handle CBI class-specific requests */
1361 +       else {
1362 +               switch (ctrl->bRequest) {
1363 +
1364 +               case USB_CBI_ADSC_REQUEST:
1365 +                       if (ctrl->bRequestType != (USB_DIR_OUT |
1366 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1367 +                               break;
1368 +                       if (w_index != 0 || w_value != 0) {
1369 +                               value = -EDOM;
1370 +                               break;
1371 +                       }
1372 +                       if (w_length > MAX_COMMAND_SIZE) {
1373 +                               value = -EOVERFLOW;
1374 +                               break;
1375 +                       }
1376 +                       value = w_length;
1377 +                       fsg->ep0req->context = received_cbi_adsc;
1378 +                       break;
1379 +               }
1380 +       }
1381 +
1382 +       if (value == -EOPNOTSUPP)
1383 +               VDBG(fsg,
1384 +                       "unknown class-specific control req "
1385 +                       "%02x.%02x v%04x i%04x l%u\n",
1386 +                       ctrl->bRequestType, ctrl->bRequest,
1387 +                       le16_to_cpu(ctrl->wValue), w_index, w_length);
1388 +       return value;
1389 +}
1390 +
1391 +
1392 +/*-------------------------------------------------------------------------*/
1393 +
1394 +/* Ep0 standard request handlers.  These always run in_irq. */
1395 +
1396 +static int standard_setup_req(struct fsg_dev *fsg,
1397 +               const struct usb_ctrlrequest *ctrl)
1398 +{
1399 +       struct usb_request      *req = fsg->ep0req;
1400 +       int                     value = -EOPNOTSUPP;
1401 +       u16                     w_index = le16_to_cpu(ctrl->wIndex);
1402 +       u16                     w_value = le16_to_cpu(ctrl->wValue);
1403 +
1404 +       /* Usually this just stores reply data in the pre-allocated ep0 buffer,
1405 +        * but config change events will also reconfigure hardware. */
1406 +       switch (ctrl->bRequest) {
1407 +
1408 +       case USB_REQ_GET_DESCRIPTOR:
1409 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1410 +                               USB_RECIP_DEVICE))
1411 +                       break;
1412 +               switch (w_value >> 8) {
1413 +
1414 +               case USB_DT_DEVICE:
1415 +                       VDBG(fsg, "get device descriptor\n");
1416 +                       device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
1417 +                       value = sizeof device_desc;
1418 +                       memcpy(req->buf, &device_desc, value);
1419 +                       break;
1420 +               case USB_DT_DEVICE_QUALIFIER:
1421 +                       VDBG(fsg, "get device qualifier\n");
1422 +                       if (!gadget_is_dualspeed(fsg->gadget) ||
1423 +                                       fsg->gadget->speed == USB_SPEED_SUPER)
1424 +                               break;
1425 +                       /*
1426 +                        * Assume ep0 uses the same maxpacket value for both
1427 +                        * speeds
1428 +                        */
1429 +                       dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
1430 +                       value = sizeof dev_qualifier;
1431 +                       memcpy(req->buf, &dev_qualifier, value);
1432 +                       break;
1433 +
1434 +               case USB_DT_OTHER_SPEED_CONFIG:
1435 +                       VDBG(fsg, "get other-speed config descriptor\n");
1436 +                       if (!gadget_is_dualspeed(fsg->gadget) ||
1437 +                                       fsg->gadget->speed == USB_SPEED_SUPER)
1438 +                               break;
1439 +                       goto get_config;
1440 +               case USB_DT_CONFIG:
1441 +                       VDBG(fsg, "get configuration descriptor\n");
1442 +get_config:
1443 +                       value = populate_config_buf(fsg->gadget,
1444 +                                       req->buf,
1445 +                                       w_value >> 8,
1446 +                                       w_value & 0xff);
1447 +                       break;
1448 +
1449 +               case USB_DT_STRING:
1450 +                       VDBG(fsg, "get string descriptor\n");
1451 +
1452 +                       /* wIndex == language code */
1453 +                       value = usb_gadget_get_string(&fsg_stringtab,
1454 +                                       w_value & 0xff, req->buf);
1455 +                       break;
1456 +
1457 +               case USB_DT_BOS:
1458 +                       VDBG(fsg, "get bos descriptor\n");
1459 +
1460 +                       if (gadget_is_superspeed(fsg->gadget))
1461 +                               value = populate_bos(fsg, req->buf);
1462 +                       break;
1463 +               }
1464 +
1465 +               break;
1466 +
1467 +       /* One config, two speeds */
1468 +       case USB_REQ_SET_CONFIGURATION:
1469 +               if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
1470 +                               USB_RECIP_DEVICE))
1471 +                       break;
1472 +               VDBG(fsg, "set configuration\n");
1473 +               if (w_value == CONFIG_VALUE || w_value == 0) {
1474 +                       fsg->new_config = w_value;
1475 +
1476 +                       /* Raise an exception to wipe out previous transaction
1477 +                        * state (queued bufs, etc) and set the new config. */
1478 +                       raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
1479 +                       value = DELAYED_STATUS;
1480 +               }
1481 +               break;
1482 +       case USB_REQ_GET_CONFIGURATION:
1483 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1484 +                               USB_RECIP_DEVICE))
1485 +                       break;
1486 +               VDBG(fsg, "get configuration\n");
1487 +               *(u8 *) req->buf = fsg->config;
1488 +               value = 1;
1489 +               break;
1490 +
1491 +       case USB_REQ_SET_INTERFACE:
1492 +               if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
1493 +                               USB_RECIP_INTERFACE))
1494 +                       break;
1495 +               if (fsg->config && w_index == 0) {
1496 +
1497 +                       /* Raise an exception to wipe out previous transaction
1498 +                        * state (queued bufs, etc) and install the new
1499 +                        * interface altsetting. */
1500 +                       raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
1501 +                       value = DELAYED_STATUS;
1502 +               }
1503 +               break;
1504 +       case USB_REQ_GET_INTERFACE:
1505 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1506 +                               USB_RECIP_INTERFACE))
1507 +                       break;
1508 +               if (!fsg->config)
1509 +                       break;
1510 +               if (w_index != 0) {
1511 +                       value = -EDOM;
1512 +                       break;
1513 +               }
1514 +               VDBG(fsg, "get interface\n");
1515 +               *(u8 *) req->buf = 0;
1516 +               value = 1;
1517 +               break;
1518 +
1519 +       default:
1520 +               VDBG(fsg,
1521 +                       "unknown control req %02x.%02x v%04x i%04x l%u\n",
1522 +                       ctrl->bRequestType, ctrl->bRequest,
1523 +                       w_value, w_index, le16_to_cpu(ctrl->wLength));
1524 +       }
1525 +
1526 +       return value;
1527 +}
1528 +
1529 +
1530 +static int fsg_setup(struct usb_gadget *gadget,
1531 +               const struct usb_ctrlrequest *ctrl)
1532 +{
1533 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
1534 +       int                     rc;
1535 +       int                     w_length = le16_to_cpu(ctrl->wLength);
1536 +
1537 +       ++fsg->ep0_req_tag;             // Record arrival of a new request
1538 +       fsg->ep0req->context = NULL;
1539 +       fsg->ep0req->length = 0;
1540 +       dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
1541 +
1542 +       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
1543 +               rc = class_setup_req(fsg, ctrl);
1544 +       else
1545 +               rc = standard_setup_req(fsg, ctrl);
1546 +
1547 +       /* Respond with data/status or defer until later? */
1548 +       if (rc >= 0 && rc != DELAYED_STATUS) {
1549 +               rc = min(rc, w_length);
1550 +               fsg->ep0req->length = rc;
1551 +               fsg->ep0req->zero = rc < w_length;
1552 +               fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
1553 +                               "ep0-in" : "ep0-out");
1554 +               rc = ep0_queue(fsg);
1555 +       }
1556 +
1557 +       /* Device either stalls (rc < 0) or reports success */
1558 +       return rc;
1559 +}
1560 +
1561 +
1562 +/*-------------------------------------------------------------------------*/
1563 +
1564 +/* All the following routines run in process context */
1565 +
1566 +
1567 +/* Use this for bulk or interrupt transfers, not ep0 */
1568 +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
1569 +               struct usb_request *req, int *pbusy,
1570 +               enum fsg_buffer_state *state)
1571 +{
1572 +       int     rc;
1573 +
1574 +       if (ep == fsg->bulk_in)
1575 +               dump_msg(fsg, "bulk-in", req->buf, req->length);
1576 +       else if (ep == fsg->intr_in)
1577 +               dump_msg(fsg, "intr-in", req->buf, req->length);
1578 +
1579 +       spin_lock_irq(&fsg->lock);
1580 +       *pbusy = 1;
1581 +       *state = BUF_STATE_BUSY;
1582 +       spin_unlock_irq(&fsg->lock);
1583 +       rc = usb_ep_queue(ep, req, GFP_KERNEL);
1584 +       if (rc != 0) {
1585 +               *pbusy = 0;
1586 +               *state = BUF_STATE_EMPTY;
1587 +
1588 +               /* We can't do much more than wait for a reset */
1589 +
1590 +               /* Note: currently the net2280 driver fails zero-length
1591 +                * submissions if DMA is enabled. */
1592 +               if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
1593 +                                               req->length == 0))
1594 +                       WARNING(fsg, "error in submission: %s --> %d\n",
1595 +                                       ep->name, rc);
1596 +       }
1597 +}
1598 +
1599 +
1600 +static int sleep_thread(struct fsg_dev *fsg)
1601 +{
1602 +       int     rc = 0;
1603 +
1604 +       /* Wait until a signal arrives or we are woken up */
1605 +       for (;;) {
1606 +               try_to_freeze();
1607 +               set_current_state(TASK_INTERRUPTIBLE);
1608 +               if (signal_pending(current)) {
1609 +                       rc = -EINTR;
1610 +                       break;
1611 +               }
1612 +               if (fsg->thread_wakeup_needed)
1613 +                       break;
1614 +               schedule();
1615 +       }
1616 +       __set_current_state(TASK_RUNNING);
1617 +       fsg->thread_wakeup_needed = 0;
1618 +       return rc;
1619 +}
1620 +
1621 +
1622 +/*-------------------------------------------------------------------------*/
1623 +
1624 +static int do_read(struct fsg_dev *fsg)
1625 +{
1626 +       struct fsg_lun          *curlun = fsg->curlun;
1627 +       u32                     lba;
1628 +       struct fsg_buffhd       *bh;
1629 +       int                     rc;
1630 +       u32                     amount_left;
1631 +       loff_t                  file_offset, file_offset_tmp;
1632 +       unsigned int            amount;
1633 +       ssize_t                 nread;
1634 +
1635 +       /* Get the starting Logical Block Address and check that it's
1636 +        * not too big */
1637 +       if (fsg->cmnd[0] == READ_6)
1638 +               lba = get_unaligned_be24(&fsg->cmnd[1]);
1639 +       else {
1640 +               lba = get_unaligned_be32(&fsg->cmnd[2]);
1641 +
1642 +               /* We allow DPO (Disable Page Out = don't save data in the
1643 +                * cache) and FUA (Force Unit Access = don't read from the
1644 +                * cache), but we don't implement them. */
1645 +               if ((fsg->cmnd[1] & ~0x18) != 0) {
1646 +                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1647 +                       return -EINVAL;
1648 +               }
1649 +       }
1650 +       if (lba >= curlun->num_sectors) {
1651 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1652 +               return -EINVAL;
1653 +       }
1654 +       file_offset = ((loff_t) lba) << curlun->blkbits;
1655 +
1656 +       /* Carry out the file reads */
1657 +       amount_left = fsg->data_size_from_cmnd;
1658 +       if (unlikely(amount_left == 0))
1659 +               return -EIO;            // No default reply
1660 +
1661 +       for (;;) {
1662 +
1663 +               /* Figure out how much we need to read:
1664 +                * Try to read the remaining amount.
1665 +                * But don't read more than the buffer size.
1666 +                * And don't try to read past the end of the file.
1667 +                */
1668 +               amount = min((unsigned int) amount_left, mod_data.buflen);
1669 +               amount = min((loff_t) amount,
1670 +                               curlun->file_length - file_offset);
1671 +
1672 +               /* Wait for the next buffer to become available */
1673 +               bh = fsg->next_buffhd_to_fill;
1674 +               while (bh->state != BUF_STATE_EMPTY) {
1675 +                       rc = sleep_thread(fsg);
1676 +                       if (rc)
1677 +                               return rc;
1678 +               }
1679 +
1680 +               /* If we were asked to read past the end of file,
1681 +                * end with an empty buffer. */
1682 +               if (amount == 0) {
1683 +                       curlun->sense_data =
1684 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1685 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1686 +                       curlun->info_valid = 1;
1687 +                       bh->inreq->length = 0;
1688 +                       bh->state = BUF_STATE_FULL;
1689 +                       break;
1690 +               }
1691 +
1692 +               /* Perform the read */
1693 +               file_offset_tmp = file_offset;
1694 +               nread = vfs_read(curlun->filp,
1695 +                               (char __user *) bh->buf,
1696 +                               amount, &file_offset_tmp);
1697 +               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
1698 +                               (unsigned long long) file_offset,
1699 +                               (int) nread);
1700 +               if (signal_pending(current))
1701 +                       return -EINTR;
1702 +
1703 +               if (nread < 0) {
1704 +                       LDBG(curlun, "error in file read: %d\n",
1705 +                                       (int) nread);
1706 +                       nread = 0;
1707 +               } else if (nread < amount) {
1708 +                       LDBG(curlun, "partial file read: %d/%u\n",
1709 +                                       (int) nread, amount);
1710 +                       nread = round_down(nread, curlun->blksize);
1711 +               }
1712 +               file_offset  += nread;
1713 +               amount_left  -= nread;
1714 +               fsg->residue -= nread;
1715 +
1716 +               /* Except at the end of the transfer, nread will be
1717 +                * equal to the buffer size, which is divisible by the
1718 +                * bulk-in maxpacket size.
1719 +                */
1720 +               bh->inreq->length = nread;
1721 +               bh->state = BUF_STATE_FULL;
1722 +
1723 +               /* If an error occurred, report it and its position */
1724 +               if (nread < amount) {
1725 +                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1726 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1727 +                       curlun->info_valid = 1;
1728 +                       break;
1729 +               }
1730 +
1731 +               if (amount_left == 0)
1732 +                       break;          // No more left to read
1733 +
1734 +               /* Send this buffer and go read some more */
1735 +               bh->inreq->zero = 0;
1736 +               start_transfer(fsg, fsg->bulk_in, bh->inreq,
1737 +                               &bh->inreq_busy, &bh->state);
1738 +               fsg->next_buffhd_to_fill = bh->next;
1739 +       }
1740 +
1741 +       return -EIO;            // No default reply
1742 +}
1743 +
1744 +
1745 +/*-------------------------------------------------------------------------*/
1746 +
1747 +static int do_write(struct fsg_dev *fsg)
1748 +{
1749 +       struct fsg_lun          *curlun = fsg->curlun;
1750 +       u32                     lba;
1751 +       struct fsg_buffhd       *bh;
1752 +       int                     get_some_more;
1753 +       u32                     amount_left_to_req, amount_left_to_write;
1754 +       loff_t                  usb_offset, file_offset, file_offset_tmp;
1755 +       unsigned int            amount;
1756 +       ssize_t                 nwritten;
1757 +       int                     rc;
1758 +
1759 +       if (curlun->ro) {
1760 +               curlun->sense_data = SS_WRITE_PROTECTED;
1761 +               return -EINVAL;
1762 +       }
1763 +       spin_lock(&curlun->filp->f_lock);
1764 +       curlun->filp->f_flags &= ~O_SYNC;       // Default is not to wait
1765 +       spin_unlock(&curlun->filp->f_lock);
1766 +
1767 +       /* Get the starting Logical Block Address and check that it's
1768 +        * not too big */
1769 +       if (fsg->cmnd[0] == WRITE_6)
1770 +               lba = get_unaligned_be24(&fsg->cmnd[1]);
1771 +       else {
1772 +               lba = get_unaligned_be32(&fsg->cmnd[2]);
1773 +
1774 +               /* We allow DPO (Disable Page Out = don't save data in the
1775 +                * cache) and FUA (Force Unit Access = write directly to the
1776 +                * medium).  We don't implement DPO; we implement FUA by
1777 +                * performing synchronous output. */
1778 +               if ((fsg->cmnd[1] & ~0x18) != 0) {
1779 +                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1780 +                       return -EINVAL;
1781 +               }
1782 +               /* FUA */
1783 +               if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
1784 +                       spin_lock(&curlun->filp->f_lock);
1785 +                       curlun->filp->f_flags |= O_DSYNC;
1786 +                       spin_unlock(&curlun->filp->f_lock);
1787 +               }
1788 +       }
1789 +       if (lba >= curlun->num_sectors) {
1790 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1791 +               return -EINVAL;
1792 +       }
1793 +
1794 +       /* Carry out the file writes */
1795 +       get_some_more = 1;
1796 +       file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
1797 +       amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
1798 +
1799 +       while (amount_left_to_write > 0) {
1800 +
1801 +               /* Queue a request for more data from the host */
1802 +               bh = fsg->next_buffhd_to_fill;
1803 +               if (bh->state == BUF_STATE_EMPTY && get_some_more) {
1804 +
1805 +                       /* Figure out how much we want to get:
1806 +                        * Try to get the remaining amount,
1807 +                        * but not more than the buffer size.
1808 +                        */
1809 +                       amount = min(amount_left_to_req, mod_data.buflen);
1810 +
1811 +                       /* Beyond the end of the backing file? */
1812 +                       if (usb_offset >= curlun->file_length) {
1813 +                               get_some_more = 0;
1814 +                               curlun->sense_data =
1815 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1816 +                               curlun->sense_data_info = usb_offset >> curlun->blkbits;
1817 +                               curlun->info_valid = 1;
1818 +                               continue;
1819 +                       }
1820 +
1821 +                       /* Get the next buffer */
1822 +                       usb_offset += amount;
1823 +                       fsg->usb_amount_left -= amount;
1824 +                       amount_left_to_req -= amount;
1825 +                       if (amount_left_to_req == 0)
1826 +                               get_some_more = 0;
1827 +
1828 +                       /* Except at the end of the transfer, amount will be
1829 +                        * equal to the buffer size, which is divisible by
1830 +                        * the bulk-out maxpacket size.
1831 +                        */
1832 +                       set_bulk_out_req_length(fsg, bh, amount);
1833 +                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
1834 +                                       &bh->outreq_busy, &bh->state);
1835 +                       fsg->next_buffhd_to_fill = bh->next;
1836 +                       continue;
1837 +               }
1838 +
1839 +               /* Write the received data to the backing file */
1840 +               bh = fsg->next_buffhd_to_drain;
1841 +               if (bh->state == BUF_STATE_EMPTY && !get_some_more)
1842 +                       break;                  // We stopped early
1843 +               if (bh->state == BUF_STATE_FULL) {
1844 +                       smp_rmb();
1845 +                       fsg->next_buffhd_to_drain = bh->next;
1846 +                       bh->state = BUF_STATE_EMPTY;
1847 +
1848 +                       /* Did something go wrong with the transfer? */
1849 +                       if (bh->outreq->status != 0) {
1850 +                               curlun->sense_data = SS_COMMUNICATION_FAILURE;
1851 +                               curlun->sense_data_info = file_offset >> curlun->blkbits;
1852 +                               curlun->info_valid = 1;
1853 +                               break;
1854 +                       }
1855 +
1856 +                       amount = bh->outreq->actual;
1857 +                       if (curlun->file_length - file_offset < amount) {
1858 +                               LERROR(curlun,
1859 +       "write %u @ %llu beyond end %llu\n",
1860 +       amount, (unsigned long long) file_offset,
1861 +       (unsigned long long) curlun->file_length);
1862 +                               amount = curlun->file_length - file_offset;
1863 +                       }
1864 +
1865 +                       /* Don't accept excess data.  The spec doesn't say
1866 +                        * what to do in this case.  We'll ignore the error.
1867 +                        */
1868 +                       amount = min(amount, bh->bulk_out_intended_length);
1869 +
1870 +                       /* Don't write a partial block */
1871 +                       amount = round_down(amount, curlun->blksize);
1872 +                       if (amount == 0)
1873 +                               goto empty_write;
1874 +
1875 +                       /* Perform the write */
1876 +                       file_offset_tmp = file_offset;
1877 +                       nwritten = vfs_write(curlun->filp,
1878 +                                       (char __user *) bh->buf,
1879 +                                       amount, &file_offset_tmp);
1880 +                       VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
1881 +                                       (unsigned long long) file_offset,
1882 +                                       (int) nwritten);
1883 +                       if (signal_pending(current))
1884 +                               return -EINTR;          // Interrupted!
1885 +
1886 +                       if (nwritten < 0) {
1887 +                               LDBG(curlun, "error in file write: %d\n",
1888 +                                               (int) nwritten);
1889 +                               nwritten = 0;
1890 +                       } else if (nwritten < amount) {
1891 +                               LDBG(curlun, "partial file write: %d/%u\n",
1892 +                                               (int) nwritten, amount);
1893 +                               nwritten = round_down(nwritten, curlun->blksize);
1894 +                       }
1895 +                       file_offset += nwritten;
1896 +                       amount_left_to_write -= nwritten;
1897 +                       fsg->residue -= nwritten;
1898 +
1899 +                       /* If an error occurred, report it and its position */
1900 +                       if (nwritten < amount) {
1901 +                               curlun->sense_data = SS_WRITE_ERROR;
1902 +                               curlun->sense_data_info = file_offset >> curlun->blkbits;
1903 +                               curlun->info_valid = 1;
1904 +                               break;
1905 +                       }
1906 +
1907 + empty_write:
1908 +                       /* Did the host decide to stop early? */
1909 +                       if (bh->outreq->actual < bh->bulk_out_intended_length) {
1910 +                               fsg->short_packet_received = 1;
1911 +                               break;
1912 +                       }
1913 +                       continue;
1914 +               }
1915 +
1916 +               /* Wait for something to happen */
1917 +               rc = sleep_thread(fsg);
1918 +               if (rc)
1919 +                       return rc;
1920 +       }
1921 +
1922 +       return -EIO;            // No default reply
1923 +}
1924 +
1925 +
1926 +/*-------------------------------------------------------------------------*/
1927 +
1928 +static int do_synchronize_cache(struct fsg_dev *fsg)
1929 +{
1930 +       struct fsg_lun  *curlun = fsg->curlun;
1931 +       int             rc;
1932 +
1933 +       /* We ignore the requested LBA and write out all file's
1934 +        * dirty data buffers. */
1935 +       rc = fsg_lun_fsync_sub(curlun);
1936 +       if (rc)
1937 +               curlun->sense_data = SS_WRITE_ERROR;
1938 +       return 0;
1939 +}
1940 +
1941 +
1942 +/*-------------------------------------------------------------------------*/
1943 +
1944 +static void invalidate_sub(struct fsg_lun *curlun)
1945 +{
1946 +       struct file     *filp = curlun->filp;
1947 +       struct inode    *inode = filp->f_path.dentry->d_inode;
1948 +       unsigned long   rc;
1949 +
1950 +       rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
1951 +       VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
1952 +}
1953 +
1954 +static int do_verify(struct fsg_dev *fsg)
1955 +{
1956 +       struct fsg_lun          *curlun = fsg->curlun;
1957 +       u32                     lba;
1958 +       u32                     verification_length;
1959 +       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
1960 +       loff_t                  file_offset, file_offset_tmp;
1961 +       u32                     amount_left;
1962 +       unsigned int            amount;
1963 +       ssize_t                 nread;
1964 +
1965 +       /* Get the starting Logical Block Address and check that it's
1966 +        * not too big */
1967 +       lba = get_unaligned_be32(&fsg->cmnd[2]);
1968 +       if (lba >= curlun->num_sectors) {
1969 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1970 +               return -EINVAL;
1971 +       }
1972 +
1973 +       /* We allow DPO (Disable Page Out = don't save data in the
1974 +        * cache) but we don't implement it. */
1975 +       if ((fsg->cmnd[1] & ~0x10) != 0) {
1976 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1977 +               return -EINVAL;
1978 +       }
1979 +
1980 +       verification_length = get_unaligned_be16(&fsg->cmnd[7]);
1981 +       if (unlikely(verification_length == 0))
1982 +               return -EIO;            // No default reply
1983 +
1984 +       /* Prepare to carry out the file verify */
1985 +       amount_left = verification_length << curlun->blkbits;
1986 +       file_offset = ((loff_t) lba) << curlun->blkbits;
1987 +
1988 +       /* Write out all the dirty buffers before invalidating them */
1989 +       fsg_lun_fsync_sub(curlun);
1990 +       if (signal_pending(current))
1991 +               return -EINTR;
1992 +
1993 +       invalidate_sub(curlun);
1994 +       if (signal_pending(current))
1995 +               return -EINTR;
1996 +
1997 +       /* Just try to read the requested blocks */
1998 +       while (amount_left > 0) {
1999 +
2000 +               /* Figure out how much we need to read:
2001 +                * Try to read the remaining amount, but not more than
2002 +                * the buffer size.
2003 +                * And don't try to read past the end of the file.
2004 +                */
2005 +               amount = min((unsigned int) amount_left, mod_data.buflen);
2006 +               amount = min((loff_t) amount,
2007 +                               curlun->file_length - file_offset);
2008 +               if (amount == 0) {
2009 +                       curlun->sense_data =
2010 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
2011 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
2012 +                       curlun->info_valid = 1;
2013 +                       break;
2014 +               }
2015 +
2016 +               /* Perform the read */
2017 +               file_offset_tmp = file_offset;
2018 +               nread = vfs_read(curlun->filp,
2019 +                               (char __user *) bh->buf,
2020 +                               amount, &file_offset_tmp);
2021 +               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
2022 +                               (unsigned long long) file_offset,
2023 +                               (int) nread);
2024 +               if (signal_pending(current))
2025 +                       return -EINTR;
2026 +
2027 +               if (nread < 0) {
2028 +                       LDBG(curlun, "error in file verify: %d\n",
2029 +                                       (int) nread);
2030 +                       nread = 0;
2031 +               } else if (nread < amount) {
2032 +                       LDBG(curlun, "partial file verify: %d/%u\n",
2033 +                                       (int) nread, amount);
2034 +                       nread = round_down(nread, curlun->blksize);
2035 +               }
2036 +               if (nread == 0) {
2037 +                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
2038 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
2039 +                       curlun->info_valid = 1;
2040 +                       break;
2041 +               }
2042 +               file_offset += nread;
2043 +               amount_left -= nread;
2044 +       }
2045 +       return 0;
2046 +}
2047 +
2048 +
2049 +/*-------------------------------------------------------------------------*/
2050 +
2051 +static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2052 +{
2053 +       u8      *buf = (u8 *) bh->buf;
2054 +
2055 +       static char vendor_id[] = "Linux   ";
2056 +       static char product_disk_id[] = "File-Stor Gadget";
2057 +       static char product_cdrom_id[] = "File-CD Gadget  ";
2058 +
2059 +       if (!fsg->curlun) {             // Unsupported LUNs are okay
2060 +               fsg->bad_lun_okay = 1;
2061 +               memset(buf, 0, 36);
2062 +               buf[0] = 0x7f;          // Unsupported, no device-type
2063 +               buf[4] = 31;            // Additional length
2064 +               return 36;
2065 +       }
2066 +
2067 +       memset(buf, 0, 8);
2068 +       buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
2069 +       if (mod_data.removable)
2070 +               buf[1] = 0x80;
2071 +       buf[2] = 2;             // ANSI SCSI level 2
2072 +       buf[3] = 2;             // SCSI-2 INQUIRY data format
2073 +       buf[4] = 31;            // Additional length
2074 +                               // No special options
2075 +       sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
2076 +                       (mod_data.cdrom ? product_cdrom_id :
2077 +                               product_disk_id),
2078 +                       mod_data.release);
2079 +       return 36;
2080 +}
2081 +
2082 +
2083 +static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2084 +{
2085 +       struct fsg_lun  *curlun = fsg->curlun;
2086 +       u8              *buf = (u8 *) bh->buf;
2087 +       u32             sd, sdinfo;
2088 +       int             valid;
2089 +
2090 +       /*
2091 +        * From the SCSI-2 spec., section 7.9 (Unit attention condition):
2092 +        *
2093 +        * If a REQUEST SENSE command is received from an initiator
2094 +        * with a pending unit attention condition (before the target
2095 +        * generates the contingent allegiance condition), then the
2096 +        * target shall either:
2097 +        *   a) report any pending sense data and preserve the unit
2098 +        *      attention condition on the logical unit, or,
2099 +        *   b) report the unit attention condition, may discard any
2100 +        *      pending sense data, and clear the unit attention
2101 +        *      condition on the logical unit for that initiator.
2102 +        *
2103 +        * FSG normally uses option a); enable this code to use option b).
2104 +        */
2105 +#if 0
2106 +       if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
2107 +               curlun->sense_data = curlun->unit_attention_data;
2108 +               curlun->unit_attention_data = SS_NO_SENSE;
2109 +       }
2110 +#endif
2111 +
2112 +       if (!curlun) {          // Unsupported LUNs are okay
2113 +               fsg->bad_lun_okay = 1;
2114 +               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2115 +               sdinfo = 0;
2116 +               valid = 0;
2117 +       } else {
2118 +               sd = curlun->sense_data;
2119 +               sdinfo = curlun->sense_data_info;
2120 +               valid = curlun->info_valid << 7;
2121 +               curlun->sense_data = SS_NO_SENSE;
2122 +               curlun->sense_data_info = 0;
2123 +               curlun->info_valid = 0;
2124 +       }
2125 +
2126 +       memset(buf, 0, 18);
2127 +       buf[0] = valid | 0x70;                  // Valid, current error
2128 +       buf[2] = SK(sd);
2129 +       put_unaligned_be32(sdinfo, &buf[3]);    /* Sense information */
2130 +       buf[7] = 18 - 8;                        // Additional sense length
2131 +       buf[12] = ASC(sd);
2132 +       buf[13] = ASCQ(sd);
2133 +       return 18;
2134 +}
2135 +
2136 +
2137 +static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2138 +{
2139 +       struct fsg_lun  *curlun = fsg->curlun;
2140 +       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
2141 +       int             pmi = fsg->cmnd[8];
2142 +       u8              *buf = (u8 *) bh->buf;
2143 +
2144 +       /* Check the PMI and LBA fields */
2145 +       if (pmi > 1 || (pmi == 0 && lba != 0)) {
2146 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2147 +               return -EINVAL;
2148 +       }
2149 +
2150 +       put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
2151 +                                               /* Max logical block */
2152 +       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
2153 +       return 8;
2154 +}
2155 +
2156 +
2157 +static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2158 +{
2159 +       struct fsg_lun  *curlun = fsg->curlun;
2160 +       int             msf = fsg->cmnd[1] & 0x02;
2161 +       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
2162 +       u8              *buf = (u8 *) bh->buf;
2163 +
2164 +       if ((fsg->cmnd[1] & ~0x02) != 0) {              /* Mask away MSF */
2165 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2166 +               return -EINVAL;
2167 +       }
2168 +       if (lba >= curlun->num_sectors) {
2169 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
2170 +               return -EINVAL;
2171 +       }
2172 +
2173 +       memset(buf, 0, 8);
2174 +       buf[0] = 0x01;          /* 2048 bytes of user data, rest is EC */
2175 +       store_cdrom_address(&buf[4], msf, lba);
2176 +       return 8;
2177 +}
2178 +
2179 +
2180 +static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2181 +{
2182 +       struct fsg_lun  *curlun = fsg->curlun;
2183 +       int             msf = fsg->cmnd[1] & 0x02;
2184 +       int             start_track = fsg->cmnd[6];
2185 +       u8              *buf = (u8 *) bh->buf;
2186 +
2187 +       if ((fsg->cmnd[1] & ~0x02) != 0 ||              /* Mask away MSF */
2188 +                       start_track > 1) {
2189 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2190 +               return -EINVAL;
2191 +       }
2192 +
2193 +       memset(buf, 0, 20);
2194 +       buf[1] = (20-2);                /* TOC data length */
2195 +       buf[2] = 1;                     /* First track number */
2196 +       buf[3] = 1;                     /* Last track number */
2197 +       buf[5] = 0x16;                  /* Data track, copying allowed */
2198 +       buf[6] = 0x01;                  /* Only track is number 1 */
2199 +       store_cdrom_address(&buf[8], msf, 0);
2200 +
2201 +       buf[13] = 0x16;                 /* Lead-out track is data */
2202 +       buf[14] = 0xAA;                 /* Lead-out track number */
2203 +       store_cdrom_address(&buf[16], msf, curlun->num_sectors);
2204 +       return 20;
2205 +}
2206 +
2207 +
2208 +static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2209 +{
2210 +       struct fsg_lun  *curlun = fsg->curlun;
2211 +       int             mscmnd = fsg->cmnd[0];
2212 +       u8              *buf = (u8 *) bh->buf;
2213 +       u8              *buf0 = buf;
2214 +       int             pc, page_code;
2215 +       int             changeable_values, all_pages;
2216 +       int             valid_page = 0;
2217 +       int             len, limit;
2218 +
2219 +       if ((fsg->cmnd[1] & ~0x08) != 0) {              // Mask away DBD
2220 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2221 +               return -EINVAL;
2222 +       }
2223 +       pc = fsg->cmnd[2] >> 6;
2224 +       page_code = fsg->cmnd[2] & 0x3f;
2225 +       if (pc == 3) {
2226 +               curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
2227 +               return -EINVAL;
2228 +       }
2229 +       changeable_values = (pc == 1);
2230 +       all_pages = (page_code == 0x3f);
2231 +
2232 +       /* Write the mode parameter header.  Fixed values are: default
2233 +        * medium type, no cache control (DPOFUA), and no block descriptors.
2234 +        * The only variable value is the WriteProtect bit.  We will fill in
2235 +        * the mode data length later. */
2236 +       memset(buf, 0, 8);
2237 +       if (mscmnd == MODE_SENSE) {
2238 +               buf[2] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
2239 +               buf += 4;
2240 +               limit = 255;
2241 +       } else {                        // MODE_SENSE_10
2242 +               buf[3] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
2243 +               buf += 8;
2244 +               limit = 65535;          // Should really be mod_data.buflen
2245 +       }
2246 +
2247 +       /* No block descriptors */
2248 +
2249 +       /* The mode pages, in numerical order.  The only page we support
2250 +        * is the Caching page. */
2251 +       if (page_code == 0x08 || all_pages) {
2252 +               valid_page = 1;
2253 +               buf[0] = 0x08;          // Page code
2254 +               buf[1] = 10;            // Page length
2255 +               memset(buf+2, 0, 10);   // None of the fields are changeable
2256 +
2257 +               if (!changeable_values) {
2258 +                       buf[2] = 0x04;  // Write cache enable,
2259 +                                       // Read cache not disabled
2260 +                                       // No cache retention priorities
2261 +                       put_unaligned_be16(0xffff, &buf[4]);
2262 +                                       /* Don't disable prefetch */
2263 +                                       /* Minimum prefetch = 0 */
2264 +                       put_unaligned_be16(0xffff, &buf[8]);
2265 +                                       /* Maximum prefetch */
2266 +                       put_unaligned_be16(0xffff, &buf[10]);
2267 +                                       /* Maximum prefetch ceiling */
2268 +               }
2269 +               buf += 12;
2270 +       }
2271 +
2272 +       /* Check that a valid page was requested and the mode data length
2273 +        * isn't too long. */
2274 +       len = buf - buf0;
2275 +       if (!valid_page || len > limit) {
2276 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2277 +               return -EINVAL;
2278 +       }
2279 +
2280 +       /*  Store the mode data length */
2281 +       if (mscmnd == MODE_SENSE)
2282 +               buf0[0] = len - 1;
2283 +       else
2284 +               put_unaligned_be16(len - 2, buf0);
2285 +       return len;
2286 +}
2287 +
2288 +
2289 +static int do_start_stop(struct fsg_dev *fsg)
2290 +{
2291 +       struct fsg_lun  *curlun = fsg->curlun;
2292 +       int             loej, start;
2293 +
2294 +       if (!mod_data.removable) {
2295 +               curlun->sense_data = SS_INVALID_COMMAND;
2296 +               return -EINVAL;
2297 +       }
2298 +
2299 +       // int immed = fsg->cmnd[1] & 0x01;
2300 +       loej = fsg->cmnd[4] & 0x02;
2301 +       start = fsg->cmnd[4] & 0x01;
2302 +
2303 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
2304 +       if ((fsg->cmnd[1] & ~0x01) != 0 ||              // Mask away Immed
2305 +                       (fsg->cmnd[4] & ~0x03) != 0) {  // Mask LoEj, Start
2306 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2307 +               return -EINVAL;
2308 +       }
2309 +
2310 +       if (!start) {
2311 +
2312 +               /* Are we allowed to unload the media? */
2313 +               if (curlun->prevent_medium_removal) {
2314 +                       LDBG(curlun, "unload attempt prevented\n");
2315 +                       curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
2316 +                       return -EINVAL;
2317 +               }
2318 +               if (loej) {             // Simulate an unload/eject
2319 +                       up_read(&fsg->filesem);
2320 +                       down_write(&fsg->filesem);
2321 +                       fsg_lun_close(curlun);
2322 +                       up_write(&fsg->filesem);
2323 +                       down_read(&fsg->filesem);
2324 +               }
2325 +       } else {
2326 +
2327 +               /* Our emulation doesn't support mounting; the medium is
2328 +                * available for use as soon as it is loaded. */
2329 +               if (!fsg_lun_is_open(curlun)) {
2330 +                       curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2331 +                       return -EINVAL;
2332 +               }
2333 +       }
2334 +#endif
2335 +       return 0;
2336 +}
2337 +
2338 +
2339 +static int do_prevent_allow(struct fsg_dev *fsg)
2340 +{
2341 +       struct fsg_lun  *curlun = fsg->curlun;
2342 +       int             prevent;
2343 +
2344 +       if (!mod_data.removable) {
2345 +               curlun->sense_data = SS_INVALID_COMMAND;
2346 +               return -EINVAL;
2347 +       }
2348 +
2349 +       prevent = fsg->cmnd[4] & 0x01;
2350 +       if ((fsg->cmnd[4] & ~0x01) != 0) {              // Mask away Prevent
2351 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2352 +               return -EINVAL;
2353 +       }
2354 +
2355 +       if (curlun->prevent_medium_removal && !prevent)
2356 +               fsg_lun_fsync_sub(curlun);
2357 +       curlun->prevent_medium_removal = prevent;
2358 +       return 0;
2359 +}
2360 +
2361 +
2362 +static int do_read_format_capacities(struct fsg_dev *fsg,
2363 +                       struct fsg_buffhd *bh)
2364 +{
2365 +       struct fsg_lun  *curlun = fsg->curlun;
2366 +       u8              *buf = (u8 *) bh->buf;
2367 +
2368 +       buf[0] = buf[1] = buf[2] = 0;
2369 +       buf[3] = 8;             // Only the Current/Maximum Capacity Descriptor
2370 +       buf += 4;
2371 +
2372 +       put_unaligned_be32(curlun->num_sectors, &buf[0]);
2373 +                                               /* Number of blocks */
2374 +       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
2375 +       buf[4] = 0x02;                          /* Current capacity */
2376 +       return 12;
2377 +}
2378 +
2379 +
2380 +static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2381 +{
2382 +       struct fsg_lun  *curlun = fsg->curlun;
2383 +
2384 +       /* We don't support MODE SELECT */
2385 +       curlun->sense_data = SS_INVALID_COMMAND;
2386 +       return -EINVAL;
2387 +}
2388 +
2389 +
2390 +/*-------------------------------------------------------------------------*/
2391 +
2392 +static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
2393 +{
2394 +       int     rc;
2395 +
2396 +       rc = fsg_set_halt(fsg, fsg->bulk_in);
2397 +       if (rc == -EAGAIN)
2398 +               VDBG(fsg, "delayed bulk-in endpoint halt\n");
2399 +       while (rc != 0) {
2400 +               if (rc != -EAGAIN) {
2401 +                       WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
2402 +                       rc = 0;
2403 +                       break;
2404 +               }
2405 +
2406 +               /* Wait for a short time and then try again */
2407 +               if (msleep_interruptible(100) != 0)
2408 +                       return -EINTR;
2409 +               rc = usb_ep_set_halt(fsg->bulk_in);
2410 +       }
2411 +       return rc;
2412 +}
2413 +
2414 +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
2415 +{
2416 +       int     rc;
2417 +
2418 +       DBG(fsg, "bulk-in set wedge\n");
2419 +       rc = usb_ep_set_wedge(fsg->bulk_in);
2420 +       if (rc == -EAGAIN)
2421 +               VDBG(fsg, "delayed bulk-in endpoint wedge\n");
2422 +       while (rc != 0) {
2423 +               if (rc != -EAGAIN) {
2424 +                       WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
2425 +                       rc = 0;
2426 +                       break;
2427 +               }
2428 +
2429 +               /* Wait for a short time and then try again */
2430 +               if (msleep_interruptible(100) != 0)
2431 +                       return -EINTR;
2432 +               rc = usb_ep_set_wedge(fsg->bulk_in);
2433 +       }
2434 +       return rc;
2435 +}
2436 +
2437 +static int throw_away_data(struct fsg_dev *fsg)
2438 +{
2439 +       struct fsg_buffhd       *bh;
2440 +       u32                     amount;
2441 +       int                     rc;
2442 +
2443 +       while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
2444 +                       fsg->usb_amount_left > 0) {
2445 +
2446 +               /* Throw away the data in a filled buffer */
2447 +               if (bh->state == BUF_STATE_FULL) {
2448 +                       smp_rmb();
2449 +                       bh->state = BUF_STATE_EMPTY;
2450 +                       fsg->next_buffhd_to_drain = bh->next;
2451 +
2452 +                       /* A short packet or an error ends everything */
2453 +                       if (bh->outreq->actual < bh->bulk_out_intended_length ||
2454 +                                       bh->outreq->status != 0) {
2455 +                               raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2456 +                               return -EINTR;
2457 +                       }
2458 +                       continue;
2459 +               }
2460 +
2461 +               /* Try to submit another request if we need one */
2462 +               bh = fsg->next_buffhd_to_fill;
2463 +               if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
2464 +                       amount = min(fsg->usb_amount_left,
2465 +                                       (u32) mod_data.buflen);
2466 +
2467 +                       /* Except at the end of the transfer, amount will be
2468 +                        * equal to the buffer size, which is divisible by
2469 +                        * the bulk-out maxpacket size.
2470 +                        */
2471 +                       set_bulk_out_req_length(fsg, bh, amount);
2472 +                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
2473 +                                       &bh->outreq_busy, &bh->state);
2474 +                       fsg->next_buffhd_to_fill = bh->next;
2475 +                       fsg->usb_amount_left -= amount;
2476 +                       continue;
2477 +               }
2478 +
2479 +               /* Otherwise wait for something to happen */
2480 +               rc = sleep_thread(fsg);
2481 +               if (rc)
2482 +                       return rc;
2483 +       }
2484 +       return 0;
2485 +}
2486 +
2487 +
2488 +static int finish_reply(struct fsg_dev *fsg)
2489 +{
2490 +       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
2491 +       int                     rc = 0;
2492 +
2493 +       switch (fsg->data_dir) {
2494 +       case DATA_DIR_NONE:
2495 +               break;                  // Nothing to send
2496 +
2497 +       /* If we don't know whether the host wants to read or write,
2498 +        * this must be CB or CBI with an unknown command.  We mustn't
2499 +        * try to send or receive any data.  So stall both bulk pipes
2500 +        * if we can and wait for a reset. */
2501 +       case DATA_DIR_UNKNOWN:
2502 +               if (mod_data.can_stall) {
2503 +                       fsg_set_halt(fsg, fsg->bulk_out);
2504 +                       rc = halt_bulk_in_endpoint(fsg);
2505 +               }
2506 +               break;
2507 +
2508 +       /* All but the last buffer of data must have already been sent */
2509 +       case DATA_DIR_TO_HOST:
2510 +               if (fsg->data_size == 0)
2511 +                       ;               // Nothing to send
2512 +
2513 +               /* If there's no residue, simply send the last buffer */
2514 +               else if (fsg->residue == 0) {
2515 +                       bh->inreq->zero = 0;
2516 +                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
2517 +                                       &bh->inreq_busy, &bh->state);
2518 +                       fsg->next_buffhd_to_fill = bh->next;
2519 +               }
2520 +
2521 +               /* There is a residue.  For CB and CBI, simply mark the end
2522 +                * of the data with a short packet.  However, if we are
2523 +                * allowed to stall, there was no data at all (residue ==
2524 +                * data_size), and the command failed (invalid LUN or
2525 +                * sense data is set), then halt the bulk-in endpoint
2526 +                * instead. */
2527 +               else if (!transport_is_bbb()) {
2528 +                       if (mod_data.can_stall &&
2529 +                                       fsg->residue == fsg->data_size &&
2530 +       (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
2531 +                               bh->state = BUF_STATE_EMPTY;
2532 +                               rc = halt_bulk_in_endpoint(fsg);
2533 +                       } else {
2534 +                               bh->inreq->zero = 1;
2535 +                               start_transfer(fsg, fsg->bulk_in, bh->inreq,
2536 +                                               &bh->inreq_busy, &bh->state);
2537 +                               fsg->next_buffhd_to_fill = bh->next;
2538 +                       }
2539 +               }
2540 +
2541 +               /*
2542 +                * For Bulk-only, mark the end of the data with a short
2543 +                * packet.  If we are allowed to stall, halt the bulk-in
2544 +                * endpoint.  (Note: This violates the Bulk-Only Transport
2545 +                * specification, which requires us to pad the data if we
2546 +                * don't halt the endpoint.  Presumably nobody will mind.)
2547 +                */
2548 +               else {
2549 +                       bh->inreq->zero = 1;
2550 +                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
2551 +                                       &bh->inreq_busy, &bh->state);
2552 +                       fsg->next_buffhd_to_fill = bh->next;
2553 +                       if (mod_data.can_stall)
2554 +                               rc = halt_bulk_in_endpoint(fsg);
2555 +               }
2556 +               break;
2557 +
2558 +       /* We have processed all we want from the data the host has sent.
2559 +        * There may still be outstanding bulk-out requests. */
2560 +       case DATA_DIR_FROM_HOST:
2561 +               if (fsg->residue == 0)
2562 +                       ;               // Nothing to receive
2563 +
2564 +               /* Did the host stop sending unexpectedly early? */
2565 +               else if (fsg->short_packet_received) {
2566 +                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2567 +                       rc = -EINTR;
2568 +               }
2569 +
2570 +               /* We haven't processed all the incoming data.  Even though
2571 +                * we may be allowed to stall, doing so would cause a race.
2572 +                * The controller may already have ACK'ed all the remaining
2573 +                * bulk-out packets, in which case the host wouldn't see a
2574 +                * STALL.  Not realizing the endpoint was halted, it wouldn't
2575 +                * clear the halt -- leading to problems later on. */
2576 +#if 0
2577 +               else if (mod_data.can_stall) {
2578 +                       fsg_set_halt(fsg, fsg->bulk_out);
2579 +                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2580 +                       rc = -EINTR;
2581 +               }
2582 +#endif
2583 +
2584 +               /* We can't stall.  Read in the excess data and throw it
2585 +                * all away. */
2586 +               else
2587 +                       rc = throw_away_data(fsg);
2588 +               break;
2589 +       }
2590 +       return rc;
2591 +}
2592 +
2593 +
2594 +static int send_status(struct fsg_dev *fsg)
2595 +{
2596 +       struct fsg_lun          *curlun = fsg->curlun;
2597 +       struct fsg_buffhd       *bh;
2598 +       int                     rc;
2599 +       u8                      status = US_BULK_STAT_OK;
2600 +       u32                     sd, sdinfo = 0;
2601 +
2602 +       /* Wait for the next buffer to become available */
2603 +       bh = fsg->next_buffhd_to_fill;
2604 +       while (bh->state != BUF_STATE_EMPTY) {
2605 +               rc = sleep_thread(fsg);
2606 +               if (rc)
2607 +                       return rc;
2608 +       }
2609 +
2610 +       if (curlun) {
2611 +               sd = curlun->sense_data;
2612 +               sdinfo = curlun->sense_data_info;
2613 +       } else if (fsg->bad_lun_okay)
2614 +               sd = SS_NO_SENSE;
2615 +       else
2616 +               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2617 +
2618 +       if (fsg->phase_error) {
2619 +               DBG(fsg, "sending phase-error status\n");
2620 +               status = US_BULK_STAT_PHASE;
2621 +               sd = SS_INVALID_COMMAND;
2622 +       } else if (sd != SS_NO_SENSE) {
2623 +               DBG(fsg, "sending command-failure status\n");
2624 +               status = US_BULK_STAT_FAIL;
2625 +               VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
2626 +                               "  info x%x\n",
2627 +                               SK(sd), ASC(sd), ASCQ(sd), sdinfo);
2628 +       }
2629 +
2630 +       if (transport_is_bbb()) {
2631 +               struct bulk_cs_wrap     *csw = bh->buf;
2632 +
2633 +               /* Store and send the Bulk-only CSW */
2634 +               csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
2635 +               csw->Tag = fsg->tag;
2636 +               csw->Residue = cpu_to_le32(fsg->residue);
2637 +               csw->Status = status;
2638 +
2639 +               bh->inreq->length = US_BULK_CS_WRAP_LEN;
2640 +               bh->inreq->zero = 0;
2641 +               start_transfer(fsg, fsg->bulk_in, bh->inreq,
2642 +                               &bh->inreq_busy, &bh->state);
2643 +
2644 +       } else if (mod_data.transport_type == USB_PR_CB) {
2645 +
2646 +               /* Control-Bulk transport has no status phase! */
2647 +               return 0;
2648 +
2649 +       } else {                        // USB_PR_CBI
2650 +               struct interrupt_data   *buf = bh->buf;
2651 +
2652 +               /* Store and send the Interrupt data.  UFI sends the ASC
2653 +                * and ASCQ bytes.  Everything else sends a Type (which
2654 +                * is always 0) and the status Value. */
2655 +               if (mod_data.protocol_type == USB_SC_UFI) {
2656 +                       buf->bType = ASC(sd);
2657 +                       buf->bValue = ASCQ(sd);
2658 +               } else {
2659 +                       buf->bType = 0;
2660 +                       buf->bValue = status;
2661 +               }
2662 +               fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
2663 +
2664 +               fsg->intr_buffhd = bh;          // Point to the right buffhd
2665 +               fsg->intreq->buf = bh->inreq->buf;
2666 +               fsg->intreq->context = bh;
2667 +               start_transfer(fsg, fsg->intr_in, fsg->intreq,
2668 +                               &fsg->intreq_busy, &bh->state);
2669 +       }
2670 +
2671 +       fsg->next_buffhd_to_fill = bh->next;
2672 +       return 0;
2673 +}
2674 +
2675 +
2676 +/*-------------------------------------------------------------------------*/
2677 +
2678 +/* Check whether the command is properly formed and whether its data size
2679 + * and direction agree with the values we already have. */
2680 +static int check_command(struct fsg_dev *fsg, int cmnd_size,
2681 +               enum data_direction data_dir, unsigned int mask,
2682 +               int needs_medium, const char *name)
2683 +{
2684 +       int                     i;
2685 +       int                     lun = fsg->cmnd[1] >> 5;
2686 +       static const char       dirletter[4] = {'u', 'o', 'i', 'n'};
2687 +       char                    hdlen[20];
2688 +       struct fsg_lun          *curlun;
2689 +
2690 +       /* Adjust the expected cmnd_size for protocol encapsulation padding.
2691 +        * Transparent SCSI doesn't pad. */
2692 +       if (protocol_is_scsi())
2693 +               ;
2694 +
2695 +       /* There's some disagreement as to whether RBC pads commands or not.
2696 +        * We'll play it safe and accept either form. */
2697 +       else if (mod_data.protocol_type == USB_SC_RBC) {
2698 +               if (fsg->cmnd_size == 12)
2699 +                       cmnd_size = 12;
2700 +
2701 +       /* All the other protocols pad to 12 bytes */
2702 +       } else
2703 +               cmnd_size = 12;
2704 +
2705 +       hdlen[0] = 0;
2706 +       if (fsg->data_dir != DATA_DIR_UNKNOWN)
2707 +               sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
2708 +                               fsg->data_size);
2709 +       VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
2710 +                       name, cmnd_size, dirletter[(int) data_dir],
2711 +                       fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
2712 +
2713 +       /* We can't reply at all until we know the correct data direction
2714 +        * and size. */
2715 +       if (fsg->data_size_from_cmnd == 0)
2716 +               data_dir = DATA_DIR_NONE;
2717 +       if (fsg->data_dir == DATA_DIR_UNKNOWN) {        // CB or CBI
2718 +               fsg->data_dir = data_dir;
2719 +               fsg->data_size = fsg->data_size_from_cmnd;
2720 +
2721 +       } else {                                        // Bulk-only
2722 +               if (fsg->data_size < fsg->data_size_from_cmnd) {
2723 +
2724 +                       /* Host data size < Device data size is a phase error.
2725 +                        * Carry out the command, but only transfer as much
2726 +                        * as we are allowed. */
2727 +                       fsg->data_size_from_cmnd = fsg->data_size;
2728 +                       fsg->phase_error = 1;
2729 +               }
2730 +       }
2731 +       fsg->residue = fsg->usb_amount_left = fsg->data_size;
2732 +
2733 +       /* Conflicting data directions is a phase error */
2734 +       if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
2735 +               fsg->phase_error = 1;
2736 +               return -EINVAL;
2737 +       }
2738 +
2739 +       /* Verify the length of the command itself */
2740 +       if (cmnd_size != fsg->cmnd_size) {
2741 +
2742 +               /* Special case workaround: There are plenty of buggy SCSI
2743 +                * implementations. Many have issues with cbw->Length
2744 +                * field passing a wrong command size. For those cases we
2745 +                * always try to work around the problem by using the length
2746 +                * sent by the host side provided it is at least as large
2747 +                * as the correct command length.
2748 +                * Examples of such cases would be MS-Windows, which issues
2749 +                * REQUEST SENSE with cbw->Length == 12 where it should
2750 +                * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
2751 +                * REQUEST SENSE with cbw->Length == 10 where it should
2752 +                * be 6 as well.
2753 +                */
2754 +               if (cmnd_size <= fsg->cmnd_size) {
2755 +                       DBG(fsg, "%s is buggy! Expected length %d "
2756 +                                       "but we got %d\n", name,
2757 +                                       cmnd_size, fsg->cmnd_size);
2758 +                       cmnd_size = fsg->cmnd_size;
2759 +               } else {
2760 +                       fsg->phase_error = 1;
2761 +                       return -EINVAL;
2762 +               }
2763 +       }
2764 +
2765 +       /* Check that the LUN values are consistent */
2766 +       if (transport_is_bbb()) {
2767 +               if (fsg->lun != lun)
2768 +                       DBG(fsg, "using LUN %d from CBW, "
2769 +                                       "not LUN %d from CDB\n",
2770 +                                       fsg->lun, lun);
2771 +       }
2772 +
2773 +       /* Check the LUN */
2774 +       curlun = fsg->curlun;
2775 +       if (curlun) {
2776 +               if (fsg->cmnd[0] != REQUEST_SENSE) {
2777 +                       curlun->sense_data = SS_NO_SENSE;
2778 +                       curlun->sense_data_info = 0;
2779 +                       curlun->info_valid = 0;
2780 +               }
2781 +       } else {
2782 +               fsg->bad_lun_okay = 0;
2783 +
2784 +               /* INQUIRY and REQUEST SENSE commands are explicitly allowed
2785 +                * to use unsupported LUNs; all others may not. */
2786 +               if (fsg->cmnd[0] != INQUIRY &&
2787 +                               fsg->cmnd[0] != REQUEST_SENSE) {
2788 +                       DBG(fsg, "unsupported LUN %d\n", fsg->lun);
2789 +                       return -EINVAL;
2790 +               }
2791 +       }
2792 +
2793 +       /* If a unit attention condition exists, only INQUIRY and
2794 +        * REQUEST SENSE commands are allowed; anything else must fail. */
2795 +       if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
2796 +                       fsg->cmnd[0] != INQUIRY &&
2797 +                       fsg->cmnd[0] != REQUEST_SENSE) {
2798 +               curlun->sense_data = curlun->unit_attention_data;
2799 +               curlun->unit_attention_data = SS_NO_SENSE;
2800 +               return -EINVAL;
2801 +       }
2802 +
2803 +       /* Check that only command bytes listed in the mask are non-zero */
2804 +       fsg->cmnd[1] &= 0x1f;                   // Mask away the LUN
2805 +       for (i = 1; i < cmnd_size; ++i) {
2806 +               if (fsg->cmnd[i] && !(mask & (1 << i))) {
2807 +                       if (curlun)
2808 +                               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2809 +                       return -EINVAL;
2810 +               }
2811 +       }
2812 +
2813 +       /* If the medium isn't mounted and the command needs to access
2814 +        * it, return an error. */
2815 +       if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
2816 +               curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2817 +               return -EINVAL;
2818 +       }
2819 +
2820 +       return 0;
2821 +}
2822 +
2823 +/* wrapper of check_command for data size in blocks handling */
2824 +static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
2825 +               enum data_direction data_dir, unsigned int mask,
2826 +               int needs_medium, const char *name)
2827 +{
2828 +       if (fsg->curlun)
2829 +               fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
2830 +       return check_command(fsg, cmnd_size, data_dir,
2831 +                       mask, needs_medium, name);
2832 +}
2833 +
2834 +static int do_scsi_command(struct fsg_dev *fsg)
2835 +{
2836 +       struct fsg_buffhd       *bh;
2837 +       int                     rc;
2838 +       int                     reply = -EINVAL;
2839 +       int                     i;
2840 +       static char             unknown[16];
2841 +
2842 +       dump_cdb(fsg);
2843 +
2844 +       /* Wait for the next buffer to become available for data or status */
2845 +       bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
2846 +       while (bh->state != BUF_STATE_EMPTY) {
2847 +               rc = sleep_thread(fsg);
2848 +               if (rc)
2849 +                       return rc;
2850 +       }
2851 +       fsg->phase_error = 0;
2852 +       fsg->short_packet_received = 0;
2853 +
2854 +       down_read(&fsg->filesem);       // We're using the backing file
2855 +       switch (fsg->cmnd[0]) {
2856 +
2857 +       case INQUIRY:
2858 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2859 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2860 +                               (1<<4), 0,
2861 +                               "INQUIRY")) == 0)
2862 +                       reply = do_inquiry(fsg, bh);
2863 +               break;
2864 +
2865 +       case MODE_SELECT:
2866 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2867 +               if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
2868 +                               (1<<1) | (1<<4), 0,
2869 +                               "MODE SELECT(6)")) == 0)
2870 +                       reply = do_mode_select(fsg, bh);
2871 +               break;
2872 +
2873 +       case MODE_SELECT_10:
2874 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2875 +               if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
2876 +                               (1<<1) | (3<<7), 0,
2877 +                               "MODE SELECT(10)")) == 0)
2878 +                       reply = do_mode_select(fsg, bh);
2879 +               break;
2880 +
2881 +       case MODE_SENSE:
2882 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2883 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2884 +                               (1<<1) | (1<<2) | (1<<4), 0,
2885 +                               "MODE SENSE(6)")) == 0)
2886 +                       reply = do_mode_sense(fsg, bh);
2887 +               break;
2888 +
2889 +       case MODE_SENSE_10:
2890 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2891 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2892 +                               (1<<1) | (1<<2) | (3<<7), 0,
2893 +                               "MODE SENSE(10)")) == 0)
2894 +                       reply = do_mode_sense(fsg, bh);
2895 +               break;
2896 +
2897 +       case ALLOW_MEDIUM_REMOVAL:
2898 +               fsg->data_size_from_cmnd = 0;
2899 +               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2900 +                               (1<<4), 0,
2901 +                               "PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
2902 +                       reply = do_prevent_allow(fsg);
2903 +               break;
2904 +
2905 +       case READ_6:
2906 +               i = fsg->cmnd[4];
2907 +               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
2908 +               if ((reply = check_command_size_in_blocks(fsg, 6,
2909 +                               DATA_DIR_TO_HOST,
2910 +                               (7<<1) | (1<<4), 1,
2911 +                               "READ(6)")) == 0)
2912 +                       reply = do_read(fsg);
2913 +               break;
2914 +
2915 +       case READ_10:
2916 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2917 +               if ((reply = check_command_size_in_blocks(fsg, 10,
2918 +                               DATA_DIR_TO_HOST,
2919 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2920 +                               "READ(10)")) == 0)
2921 +                       reply = do_read(fsg);
2922 +               break;
2923 +
2924 +       case READ_12:
2925 +               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
2926 +               if ((reply = check_command_size_in_blocks(fsg, 12,
2927 +                               DATA_DIR_TO_HOST,
2928 +                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
2929 +                               "READ(12)")) == 0)
2930 +                       reply = do_read(fsg);
2931 +               break;
2932 +
2933 +       case READ_CAPACITY:
2934 +               fsg->data_size_from_cmnd = 8;
2935 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2936 +                               (0xf<<2) | (1<<8), 1,
2937 +                               "READ CAPACITY")) == 0)
2938 +                       reply = do_read_capacity(fsg, bh);
2939 +               break;
2940 +
2941 +       case READ_HEADER:
2942 +               if (!mod_data.cdrom)
2943 +                       goto unknown_cmnd;
2944 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2945 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2946 +                               (3<<7) | (0x1f<<1), 1,
2947 +                               "READ HEADER")) == 0)
2948 +                       reply = do_read_header(fsg, bh);
2949 +               break;
2950 +
2951 +       case READ_TOC:
2952 +               if (!mod_data.cdrom)
2953 +                       goto unknown_cmnd;
2954 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2955 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2956 +                               (7<<6) | (1<<1), 1,
2957 +                               "READ TOC")) == 0)
2958 +                       reply = do_read_toc(fsg, bh);
2959 +               break;
2960 +
2961 +       case READ_FORMAT_CAPACITIES:
2962 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2963 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2964 +                               (3<<7), 1,
2965 +                               "READ FORMAT CAPACITIES")) == 0)
2966 +                       reply = do_read_format_capacities(fsg, bh);
2967 +               break;
2968 +
2969 +       case REQUEST_SENSE:
2970 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2971 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2972 +                               (1<<4), 0,
2973 +                               "REQUEST SENSE")) == 0)
2974 +                       reply = do_request_sense(fsg, bh);
2975 +               break;
2976 +
2977 +       case START_STOP:
2978 +               fsg->data_size_from_cmnd = 0;
2979 +               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2980 +                               (1<<1) | (1<<4), 0,
2981 +                               "START-STOP UNIT")) == 0)
2982 +                       reply = do_start_stop(fsg);
2983 +               break;
2984 +
2985 +       case SYNCHRONIZE_CACHE:
2986 +               fsg->data_size_from_cmnd = 0;
2987 +               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2988 +                               (0xf<<2) | (3<<7), 1,
2989 +                               "SYNCHRONIZE CACHE")) == 0)
2990 +                       reply = do_synchronize_cache(fsg);
2991 +               break;
2992 +
2993 +       case TEST_UNIT_READY:
2994 +               fsg->data_size_from_cmnd = 0;
2995 +               reply = check_command(fsg, 6, DATA_DIR_NONE,
2996 +                               0, 1,
2997 +                               "TEST UNIT READY");
2998 +               break;
2999 +
3000 +       /* Although optional, this command is used by MS-Windows.  We
3001 +        * support a minimal version: BytChk must be 0. */
3002 +       case VERIFY:
3003 +               fsg->data_size_from_cmnd = 0;
3004 +               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
3005 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
3006 +                               "VERIFY")) == 0)
3007 +                       reply = do_verify(fsg);
3008 +               break;
3009 +
3010 +       case WRITE_6:
3011 +               i = fsg->cmnd[4];
3012 +               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
3013 +               if ((reply = check_command_size_in_blocks(fsg, 6,
3014 +                               DATA_DIR_FROM_HOST,
3015 +                               (7<<1) | (1<<4), 1,
3016 +                               "WRITE(6)")) == 0)
3017 +                       reply = do_write(fsg);
3018 +               break;
3019 +
3020 +       case WRITE_10:
3021 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
3022 +               if ((reply = check_command_size_in_blocks(fsg, 10,
3023 +                               DATA_DIR_FROM_HOST,
3024 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
3025 +                               "WRITE(10)")) == 0)
3026 +                       reply = do_write(fsg);
3027 +               break;
3028 +
3029 +       case WRITE_12:
3030 +               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
3031 +               if ((reply = check_command_size_in_blocks(fsg, 12,
3032 +                               DATA_DIR_FROM_HOST,
3033 +                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
3034 +                               "WRITE(12)")) == 0)
3035 +                       reply = do_write(fsg);
3036 +               break;
3037 +
3038 +       /* Some mandatory commands that we recognize but don't implement.
3039 +        * They don't mean much in this setting.  It's left as an exercise
3040 +        * for anyone interested to implement RESERVE and RELEASE in terms
3041 +        * of Posix locks. */
3042 +       case FORMAT_UNIT:
3043 +       case RELEASE:
3044 +       case RESERVE:
3045 +       case SEND_DIAGNOSTIC:
3046 +               // Fall through
3047 +
3048 +       default:
3049 + unknown_cmnd:
3050 +               fsg->data_size_from_cmnd = 0;
3051 +               sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
3052 +               if ((reply = check_command(fsg, fsg->cmnd_size,
3053 +                               DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
3054 +                       fsg->curlun->sense_data = SS_INVALID_COMMAND;
3055 +                       reply = -EINVAL;
3056 +               }
3057 +               break;
3058 +       }
3059 +       up_read(&fsg->filesem);
3060 +
3061 +       if (reply == -EINTR || signal_pending(current))
3062 +               return -EINTR;
3063 +
3064 +       /* Set up the single reply buffer for finish_reply() */
3065 +       if (reply == -EINVAL)
3066 +               reply = 0;              // Error reply length
3067 +       if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
3068 +               reply = min((u32) reply, fsg->data_size_from_cmnd);
3069 +               bh->inreq->length = reply;
3070 +               bh->state = BUF_STATE_FULL;
3071 +               fsg->residue -= reply;
3072 +       }                               // Otherwise it's already set
3073 +
3074 +       return 0;
3075 +}
3076 +
3077 +
3078 +/*-------------------------------------------------------------------------*/
3079 +
3080 +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
3081 +{
3082 +       struct usb_request              *req = bh->outreq;
3083 +       struct bulk_cb_wrap     *cbw = req->buf;
3084 +
3085 +       /* Was this a real packet?  Should it be ignored? */
3086 +       if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3087 +               return -EINVAL;
3088 +
3089 +       /* Is the CBW valid? */
3090 +       if (req->actual != US_BULK_CB_WRAP_LEN ||
3091 +                       cbw->Signature != cpu_to_le32(
3092 +                               US_BULK_CB_SIGN)) {
3093 +               DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
3094 +                               req->actual,
3095 +                               le32_to_cpu(cbw->Signature));
3096 +
3097 +               /* The Bulk-only spec says we MUST stall the IN endpoint
3098 +                * (6.6.1), so it's unavoidable.  It also says we must
3099 +                * retain this state until the next reset, but there's
3100 +                * no way to tell the controller driver it should ignore
3101 +                * Clear-Feature(HALT) requests.
3102 +                *
3103 +                * We aren't required to halt the OUT endpoint; instead
3104 +                * we can simply accept and discard any data received
3105 +                * until the next reset. */
3106 +               wedge_bulk_in_endpoint(fsg);
3107 +               set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3108 +               return -EINVAL;
3109 +       }
3110 +
3111 +       /* Is the CBW meaningful? */
3112 +       if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
3113 +                       cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
3114 +               DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
3115 +                               "cmdlen %u\n",
3116 +                               cbw->Lun, cbw->Flags, cbw->Length);
3117 +
3118 +               /* We can do anything we want here, so let's stall the
3119 +                * bulk pipes if we are allowed to. */
3120 +               if (mod_data.can_stall) {
3121 +                       fsg_set_halt(fsg, fsg->bulk_out);
3122 +                       halt_bulk_in_endpoint(fsg);
3123 +               }
3124 +               return -EINVAL;
3125 +       }
3126 +
3127 +       /* Save the command for later */
3128 +       fsg->cmnd_size = cbw->Length;
3129 +       memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
3130 +       if (cbw->Flags & US_BULK_FLAG_IN)
3131 +               fsg->data_dir = DATA_DIR_TO_HOST;
3132 +       else
3133 +               fsg->data_dir = DATA_DIR_FROM_HOST;
3134 +       fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
3135 +       if (fsg->data_size == 0)
3136 +               fsg->data_dir = DATA_DIR_NONE;
3137 +       fsg->lun = cbw->Lun;
3138 +       fsg->tag = cbw->Tag;
3139 +       return 0;
3140 +}
3141 +
3142 +
3143 +static int get_next_command(struct fsg_dev *fsg)
3144 +{
3145 +       struct fsg_buffhd       *bh;
3146 +       int                     rc = 0;
3147 +
3148 +       if (transport_is_bbb()) {
3149 +
3150 +               /* Wait for the next buffer to become available */
3151 +               bh = fsg->next_buffhd_to_fill;
3152 +               while (bh->state != BUF_STATE_EMPTY) {
3153 +                       rc = sleep_thread(fsg);
3154 +                       if (rc)
3155 +                               return rc;
3156 +               }
3157 +
3158 +               /* Queue a request to read a Bulk-only CBW */
3159 +               set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
3160 +               start_transfer(fsg, fsg->bulk_out, bh->outreq,
3161 +                               &bh->outreq_busy, &bh->state);
3162 +
3163 +               /* We will drain the buffer in software, which means we
3164 +                * can reuse it for the next filling.  No need to advance
3165 +                * next_buffhd_to_fill. */
3166 +
3167 +               /* Wait for the CBW to arrive */
3168 +               while (bh->state != BUF_STATE_FULL) {
3169 +                       rc = sleep_thread(fsg);
3170 +                       if (rc)
3171 +                               return rc;
3172 +               }
3173 +               smp_rmb();
3174 +               rc = received_cbw(fsg, bh);
3175 +               bh->state = BUF_STATE_EMPTY;
3176 +
3177 +       } else {                // USB_PR_CB or USB_PR_CBI
3178 +
3179 +               /* Wait for the next command to arrive */
3180 +               while (fsg->cbbuf_cmnd_size == 0) {
3181 +                       rc = sleep_thread(fsg);
3182 +                       if (rc)
3183 +                               return rc;
3184 +               }
3185 +
3186 +               /* Is the previous status interrupt request still busy?
3187 +                * The host is allowed to skip reading the status,
3188 +                * so we must cancel it. */
3189 +               if (fsg->intreq_busy)
3190 +                       usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3191 +
3192 +               /* Copy the command and mark the buffer empty */
3193 +               fsg->data_dir = DATA_DIR_UNKNOWN;
3194 +               spin_lock_irq(&fsg->lock);
3195 +               fsg->cmnd_size = fsg->cbbuf_cmnd_size;
3196 +               memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
3197 +               fsg->cbbuf_cmnd_size = 0;
3198 +               spin_unlock_irq(&fsg->lock);
3199 +
3200 +               /* Use LUN from the command */
3201 +               fsg->lun = fsg->cmnd[1] >> 5;
3202 +       }
3203 +
3204 +       /* Update current lun */
3205 +       if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
3206 +               fsg->curlun = &fsg->luns[fsg->lun];
3207 +       else
3208 +               fsg->curlun = NULL;
3209 +
3210 +       return rc;
3211 +}
3212 +
3213 +
3214 +/*-------------------------------------------------------------------------*/
3215 +
3216 +static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
3217 +               const struct usb_endpoint_descriptor *d)
3218 +{
3219 +       int     rc;
3220 +
3221 +       ep->driver_data = fsg;
3222 +       ep->desc = d;
3223 +       rc = usb_ep_enable(ep);
3224 +       if (rc)
3225 +               ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
3226 +       return rc;
3227 +}
3228 +
3229 +static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
3230 +               struct usb_request **preq)
3231 +{
3232 +       *preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
3233 +       if (*preq)
3234 +               return 0;
3235 +       ERROR(fsg, "can't allocate request for %s\n", ep->name);
3236 +       return -ENOMEM;
3237 +}
3238 +
3239 +/*
3240 + * Reset interface setting and re-init endpoint state (toggle etc).
3241 + * Call with altsetting < 0 to disable the interface.  The only other
3242 + * available altsetting is 0, which enables the interface.
3243 + */
3244 +static int do_set_interface(struct fsg_dev *fsg, int altsetting)
3245 +{
3246 +       int     rc = 0;
3247 +       int     i;
3248 +       const struct usb_endpoint_descriptor    *d;
3249 +
3250 +       if (fsg->running)
3251 +               DBG(fsg, "reset interface\n");
3252 +
3253 +reset:
3254 +       /* Deallocate the requests */
3255 +       for (i = 0; i < fsg_num_buffers; ++i) {
3256 +               struct fsg_buffhd *bh = &fsg->buffhds[i];
3257 +
3258 +               if (bh->inreq) {
3259 +                       usb_ep_free_request(fsg->bulk_in, bh->inreq);
3260 +                       bh->inreq = NULL;
3261 +               }
3262 +               if (bh->outreq) {
3263 +                       usb_ep_free_request(fsg->bulk_out, bh->outreq);
3264 +                       bh->outreq = NULL;
3265 +               }
3266 +       }
3267 +       if (fsg->intreq) {
3268 +               usb_ep_free_request(fsg->intr_in, fsg->intreq);
3269 +               fsg->intreq = NULL;
3270 +       }
3271 +
3272 +       /* Disable the endpoints */
3273 +       if (fsg->bulk_in_enabled) {
3274 +               usb_ep_disable(fsg->bulk_in);
3275 +               fsg->bulk_in_enabled = 0;
3276 +       }
3277 +       if (fsg->bulk_out_enabled) {
3278 +               usb_ep_disable(fsg->bulk_out);
3279 +               fsg->bulk_out_enabled = 0;
3280 +       }
3281 +       if (fsg->intr_in_enabled) {
3282 +               usb_ep_disable(fsg->intr_in);
3283 +               fsg->intr_in_enabled = 0;
3284 +       }
3285 +
3286 +       fsg->running = 0;
3287 +       if (altsetting < 0 || rc != 0)
3288 +               return rc;
3289 +
3290 +       DBG(fsg, "set interface %d\n", altsetting);
3291 +
3292 +       /* Enable the endpoints */
3293 +       d = fsg_ep_desc(fsg->gadget,
3294 +                       &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
3295 +                       &fsg_ss_bulk_in_desc);
3296 +       if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
3297 +               goto reset;
3298 +       fsg->bulk_in_enabled = 1;
3299 +
3300 +       d = fsg_ep_desc(fsg->gadget,
3301 +                       &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
3302 +                       &fsg_ss_bulk_out_desc);
3303 +       if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
3304 +               goto reset;
3305 +       fsg->bulk_out_enabled = 1;
3306 +       fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
3307 +       clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3308 +
3309 +       if (transport_is_cbi()) {
3310 +               d = fsg_ep_desc(fsg->gadget,
3311 +                               &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
3312 +                               &fsg_ss_intr_in_desc);
3313 +               if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
3314 +                       goto reset;
3315 +               fsg->intr_in_enabled = 1;
3316 +       }
3317 +
3318 +       /* Allocate the requests */
3319 +       for (i = 0; i < fsg_num_buffers; ++i) {
3320 +               struct fsg_buffhd       *bh = &fsg->buffhds[i];
3321 +
3322 +               if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
3323 +                       goto reset;
3324 +               if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
3325 +                       goto reset;
3326 +               bh->inreq->buf = bh->outreq->buf = bh->buf;
3327 +               bh->inreq->context = bh->outreq->context = bh;
3328 +               bh->inreq->complete = bulk_in_complete;
3329 +               bh->outreq->complete = bulk_out_complete;
3330 +       }
3331 +       if (transport_is_cbi()) {
3332 +               if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
3333 +                       goto reset;
3334 +               fsg->intreq->complete = intr_in_complete;
3335 +       }
3336 +
3337 +       fsg->running = 1;
3338 +       for (i = 0; i < fsg->nluns; ++i)
3339 +               fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3340 +       return rc;
3341 +}
3342 +
3343 +
3344 +/*
3345 + * Change our operational configuration.  This code must agree with the code
3346 + * that returns config descriptors, and with interface altsetting code.
3347 + *
3348 + * It's also responsible for power management interactions.  Some
3349 + * configurations might not work with our current power sources.
3350 + * For now we just assume the gadget is always self-powered.
3351 + */
3352 +static int do_set_config(struct fsg_dev *fsg, u8 new_config)
3353 +{
3354 +       int     rc = 0;
3355 +
3356 +       /* Disable the single interface */
3357 +       if (fsg->config != 0) {
3358 +               DBG(fsg, "reset config\n");
3359 +               fsg->config = 0;
3360 +               rc = do_set_interface(fsg, -1);
3361 +       }
3362 +
3363 +       /* Enable the interface */
3364 +       if (new_config != 0) {
3365 +               fsg->config = new_config;
3366 +               if ((rc = do_set_interface(fsg, 0)) != 0)
3367 +                       fsg->config = 0;        // Reset on errors
3368 +               else
3369 +                       INFO(fsg, "%s config #%d\n",
3370 +                            usb_speed_string(fsg->gadget->speed),
3371 +                            fsg->config);
3372 +       }
3373 +       return rc;
3374 +}
3375 +
3376 +
3377 +/*-------------------------------------------------------------------------*/
3378 +
3379 +static void handle_exception(struct fsg_dev *fsg)
3380 +{
3381 +       siginfo_t               info;
3382 +       int                     sig;
3383 +       int                     i;
3384 +       int                     num_active;
3385 +       struct fsg_buffhd       *bh;
3386 +       enum fsg_state          old_state;
3387 +       u8                      new_config;
3388 +       struct fsg_lun          *curlun;
3389 +       unsigned int            exception_req_tag;
3390 +       int                     rc;
3391 +
3392 +       /* Clear the existing signals.  Anything but SIGUSR1 is converted
3393 +        * into a high-priority EXIT exception. */
3394 +       for (;;) {
3395 +               sig = dequeue_signal_lock(current, &current->blocked, &info);
3396 +               if (!sig)
3397 +                       break;
3398 +               if (sig != SIGUSR1) {
3399 +                       if (fsg->state < FSG_STATE_EXIT)
3400 +                               DBG(fsg, "Main thread exiting on signal\n");
3401 +                       raise_exception(fsg, FSG_STATE_EXIT);
3402 +               }
3403 +       }
3404 +
3405 +       /* Cancel all the pending transfers */
3406 +       if (fsg->intreq_busy)
3407 +               usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3408 +       for (i = 0; i < fsg_num_buffers; ++i) {
3409 +               bh = &fsg->buffhds[i];
3410 +               if (bh->inreq_busy)
3411 +                       usb_ep_dequeue(fsg->bulk_in, bh->inreq);
3412 +               if (bh->outreq_busy)
3413 +                       usb_ep_dequeue(fsg->bulk_out, bh->outreq);
3414 +       }
3415 +
3416 +       /* Wait until everything is idle */
3417 +       for (;;) {
3418 +               num_active = fsg->intreq_busy;
3419 +               for (i = 0; i < fsg_num_buffers; ++i) {
3420 +                       bh = &fsg->buffhds[i];
3421 +                       num_active += bh->inreq_busy + bh->outreq_busy;
3422 +               }
3423 +               if (num_active == 0)
3424 +                       break;
3425 +               if (sleep_thread(fsg))
3426 +                       return;
3427 +       }
3428 +
3429 +       /* Clear out the controller's fifos */
3430 +       if (fsg->bulk_in_enabled)
3431 +               usb_ep_fifo_flush(fsg->bulk_in);
3432 +       if (fsg->bulk_out_enabled)
3433 +               usb_ep_fifo_flush(fsg->bulk_out);
3434 +       if (fsg->intr_in_enabled)
3435 +               usb_ep_fifo_flush(fsg->intr_in);
3436 +
3437 +       /* Reset the I/O buffer states and pointers, the SCSI
3438 +        * state, and the exception.  Then invoke the handler. */
3439 +       spin_lock_irq(&fsg->lock);
3440 +
3441 +       for (i = 0; i < fsg_num_buffers; ++i) {
3442 +               bh = &fsg->buffhds[i];
3443 +               bh->state = BUF_STATE_EMPTY;
3444 +       }
3445 +       fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
3446 +                       &fsg->buffhds[0];
3447 +
3448 +       exception_req_tag = fsg->exception_req_tag;
3449 +       new_config = fsg->new_config;
3450 +       old_state = fsg->state;
3451 +
3452 +       if (old_state == FSG_STATE_ABORT_BULK_OUT)
3453 +               fsg->state = FSG_STATE_STATUS_PHASE;
3454 +       else {
3455 +               for (i = 0; i < fsg->nluns; ++i) {
3456 +                       curlun = &fsg->luns[i];
3457 +                       curlun->prevent_medium_removal = 0;
3458 +                       curlun->sense_data = curlun->unit_attention_data =
3459 +                                       SS_NO_SENSE;
3460 +                       curlun->sense_data_info = 0;
3461 +                       curlun->info_valid = 0;
3462 +               }
3463 +               fsg->state = FSG_STATE_IDLE;
3464 +       }
3465 +       spin_unlock_irq(&fsg->lock);
3466 +
3467 +       /* Carry out any extra actions required for the exception */
3468 +       switch (old_state) {
3469 +       default:
3470 +               break;
3471 +
3472 +       case FSG_STATE_ABORT_BULK_OUT:
3473 +               send_status(fsg);
3474 +               spin_lock_irq(&fsg->lock);
3475 +               if (fsg->state == FSG_STATE_STATUS_PHASE)
3476 +                       fsg->state = FSG_STATE_IDLE;
3477 +               spin_unlock_irq(&fsg->lock);
3478 +               break;
3479 +
3480 +       case FSG_STATE_RESET:
3481 +               /* In case we were forced against our will to halt a
3482 +                * bulk endpoint, clear the halt now.  (The SuperH UDC
3483 +                * requires this.) */
3484 +               if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3485 +                       usb_ep_clear_halt(fsg->bulk_in);
3486 +
3487 +               if (transport_is_bbb()) {
3488 +                       if (fsg->ep0_req_tag == exception_req_tag)
3489 +                               ep0_queue(fsg); // Complete the status stage
3490 +
3491 +               } else if (transport_is_cbi())
3492 +                       send_status(fsg);       // Status by interrupt pipe
3493 +
3494 +               /* Technically this should go here, but it would only be
3495 +                * a waste of time.  Ditto for the INTERFACE_CHANGE and
3496 +                * CONFIG_CHANGE cases. */
3497 +               // for (i = 0; i < fsg->nluns; ++i)
3498 +               //      fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3499 +               break;
3500 +
3501 +       case FSG_STATE_INTERFACE_CHANGE:
3502 +               rc = do_set_interface(fsg, 0);
3503 +               if (fsg->ep0_req_tag != exception_req_tag)
3504 +                       break;
3505 +               if (rc != 0)                    // STALL on errors
3506 +                       fsg_set_halt(fsg, fsg->ep0);
3507 +               else                            // Complete the status stage
3508 +                       ep0_queue(fsg);
3509 +               break;
3510 +
3511 +       case FSG_STATE_CONFIG_CHANGE:
3512 +               rc = do_set_config(fsg, new_config);
3513 +               if (fsg->ep0_req_tag != exception_req_tag)
3514 +                       break;
3515 +               if (rc != 0)                    // STALL on errors
3516 +                       fsg_set_halt(fsg, fsg->ep0);
3517 +               else                            // Complete the status stage
3518 +                       ep0_queue(fsg);
3519 +               break;
3520 +
3521 +       case FSG_STATE_DISCONNECT:
3522 +               for (i = 0; i < fsg->nluns; ++i)
3523 +                       fsg_lun_fsync_sub(fsg->luns + i);
3524 +               do_set_config(fsg, 0);          // Unconfigured state
3525 +               break;
3526 +
3527 +       case FSG_STATE_EXIT:
3528 +       case FSG_STATE_TERMINATED:
3529 +               do_set_config(fsg, 0);                  // Free resources
3530 +               spin_lock_irq(&fsg->lock);
3531 +               fsg->state = FSG_STATE_TERMINATED;      // Stop the thread
3532 +               spin_unlock_irq(&fsg->lock);
3533 +               break;
3534 +       }
3535 +}
3536 +
3537 +
3538 +/*-------------------------------------------------------------------------*/
3539 +
3540 +static int fsg_main_thread(void *fsg_)
3541 +{
3542 +       struct fsg_dev          *fsg = fsg_;
3543 +
3544 +       /* Allow the thread to be killed by a signal, but set the signal mask
3545 +        * to block everything but INT, TERM, KILL, and USR1. */
3546 +       allow_signal(SIGINT);
3547 +       allow_signal(SIGTERM);
3548 +       allow_signal(SIGKILL);
3549 +       allow_signal(SIGUSR1);
3550 +
3551 +       /* Allow the thread to be frozen */
3552 +       set_freezable();
3553 +
3554 +       /* Arrange for userspace references to be interpreted as kernel
3555 +        * pointers.  That way we can pass a kernel pointer to a routine
3556 +        * that expects a __user pointer and it will work okay. */
3557 +       set_fs(get_ds());
3558 +
3559 +       /* The main loop */
3560 +       while (fsg->state != FSG_STATE_TERMINATED) {
3561 +               if (exception_in_progress(fsg) || signal_pending(current)) {
3562 +                       handle_exception(fsg);
3563 +                       continue;
3564 +               }
3565 +
3566 +               if (!fsg->running) {
3567 +                       sleep_thread(fsg);
3568 +                       continue;
3569 +               }
3570 +
3571 +               if (get_next_command(fsg))
3572 +                       continue;
3573 +
3574 +               spin_lock_irq(&fsg->lock);
3575 +               if (!exception_in_progress(fsg))
3576 +                       fsg->state = FSG_STATE_DATA_PHASE;
3577 +               spin_unlock_irq(&fsg->lock);
3578 +
3579 +               if (do_scsi_command(fsg) || finish_reply(fsg))
3580 +                       continue;
3581 +
3582 +               spin_lock_irq(&fsg->lock);
3583 +               if (!exception_in_progress(fsg))
3584 +                       fsg->state = FSG_STATE_STATUS_PHASE;
3585 +               spin_unlock_irq(&fsg->lock);
3586 +
3587 +               if (send_status(fsg))
3588 +                       continue;
3589 +
3590 +               spin_lock_irq(&fsg->lock);
3591 +               if (!exception_in_progress(fsg))
3592 +                       fsg->state = FSG_STATE_IDLE;
3593 +               spin_unlock_irq(&fsg->lock);
3594 +               }
3595 +
3596 +       spin_lock_irq(&fsg->lock);
3597 +       fsg->thread_task = NULL;
3598 +       spin_unlock_irq(&fsg->lock);
3599 +
3600 +       /* If we are exiting because of a signal, unregister the
3601 +        * gadget driver. */
3602 +       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
3603 +               usb_gadget_unregister_driver(&fsg_driver);
3604 +
3605 +       /* Let the unbind and cleanup routines know the thread has exited */
3606 +       complete_and_exit(&fsg->thread_notifier, 0);
3607 +}
3608 +
3609 +
3610 +/*-------------------------------------------------------------------------*/
3611 +
3612 +
3613 +/* The write permissions and store_xxx pointers are set in fsg_bind() */
3614 +static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
3615 +static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
3616 +static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
3617 +
3618 +
3619 +/*-------------------------------------------------------------------------*/
3620 +
3621 +static void fsg_release(struct kref *ref)
3622 +{
3623 +       struct fsg_dev  *fsg = container_of(ref, struct fsg_dev, ref);
3624 +
3625 +       kfree(fsg->luns);
3626 +       kfree(fsg);
3627 +}
3628 +
3629 +static void lun_release(struct device *dev)
3630 +{
3631 +       struct rw_semaphore     *filesem = dev_get_drvdata(dev);
3632 +       struct fsg_dev          *fsg =
3633 +               container_of(filesem, struct fsg_dev, filesem);
3634 +
3635 +       kref_put(&fsg->ref, fsg_release);
3636 +}
3637 +
3638 +static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
3639 +{
3640 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
3641 +       int                     i;
3642 +       struct fsg_lun          *curlun;
3643 +       struct usb_request      *req = fsg->ep0req;
3644 +
3645 +       DBG(fsg, "unbind\n");
3646 +       clear_bit(REGISTERED, &fsg->atomic_bitflags);
3647 +
3648 +       /* If the thread isn't already dead, tell it to exit now */
3649 +       if (fsg->state != FSG_STATE_TERMINATED) {
3650 +               raise_exception(fsg, FSG_STATE_EXIT);
3651 +               wait_for_completion(&fsg->thread_notifier);
3652 +
3653 +               /* The cleanup routine waits for this completion also */
3654 +               complete(&fsg->thread_notifier);
3655 +       }
3656 +
3657 +       /* Unregister the sysfs attribute files and the LUNs */
3658 +       for (i = 0; i < fsg->nluns; ++i) {
3659 +               curlun = &fsg->luns[i];
3660 +               if (curlun->registered) {
3661 +                       device_remove_file(&curlun->dev, &dev_attr_nofua);
3662 +                       device_remove_file(&curlun->dev, &dev_attr_ro);
3663 +                       device_remove_file(&curlun->dev, &dev_attr_file);
3664 +                       fsg_lun_close(curlun);
3665 +                       device_unregister(&curlun->dev);
3666 +                       curlun->registered = 0;
3667 +               }
3668 +       }
3669 +
3670 +       /* Free the data buffers */
3671 +       for (i = 0; i < fsg_num_buffers; ++i)
3672 +               kfree(fsg->buffhds[i].buf);
3673 +
3674 +       /* Free the request and buffer for endpoint 0 */
3675 +       if (req) {
3676 +               kfree(req->buf);
3677 +               usb_ep_free_request(fsg->ep0, req);
3678 +       }
3679 +
3680 +       set_gadget_data(gadget, NULL);
3681 +}
3682 +
3683 +
3684 +static int __init check_parameters(struct fsg_dev *fsg)
3685 +{
3686 +       int     prot;
3687 +       int     gcnum;
3688 +
3689 +       /* Store the default values */
3690 +       mod_data.transport_type = USB_PR_BULK;
3691 +       mod_data.transport_name = "Bulk-only";
3692 +       mod_data.protocol_type = USB_SC_SCSI;
3693 +       mod_data.protocol_name = "Transparent SCSI";
3694 +
3695 +       /* Some peripheral controllers are known not to be able to
3696 +        * halt bulk endpoints correctly.  If one of them is present,
3697 +        * disable stalls.
3698 +        */
3699 +       if (gadget_is_at91(fsg->gadget))
3700 +               mod_data.can_stall = 0;
3701 +
3702 +       if (mod_data.release == 0xffff) {       // Parameter wasn't set
3703 +               gcnum = usb_gadget_controller_number(fsg->gadget);
3704 +               if (gcnum >= 0)
3705 +                       mod_data.release = 0x0300 + gcnum;
3706 +               else {
3707 +                       WARNING(fsg, "controller '%s' not recognized\n",
3708 +                               fsg->gadget->name);
3709 +                       mod_data.release = 0x0399;
3710 +               }
3711 +       }
3712 +
3713 +       prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
3714 +
3715 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
3716 +       if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
3717 +               ;               // Use default setting
3718 +       } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
3719 +               mod_data.transport_type = USB_PR_CB;
3720 +               mod_data.transport_name = "Control-Bulk";
3721 +       } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
3722 +               mod_data.transport_type = USB_PR_CBI;
3723 +               mod_data.transport_name = "Control-Bulk-Interrupt";
3724 +       } else {
3725 +               ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
3726 +               return -EINVAL;
3727 +       }
3728 +
3729 +       if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
3730 +                       prot == USB_SC_SCSI) {
3731 +               ;               // Use default setting
3732 +       } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
3733 +                       prot == USB_SC_RBC) {
3734 +               mod_data.protocol_type = USB_SC_RBC;
3735 +               mod_data.protocol_name = "RBC";
3736 +       } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
3737 +                       strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
3738 +                       prot == USB_SC_8020) {
3739 +               mod_data.protocol_type = USB_SC_8020;
3740 +               mod_data.protocol_name = "8020i (ATAPI)";
3741 +       } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
3742 +                       prot == USB_SC_QIC) {
3743 +               mod_data.protocol_type = USB_SC_QIC;
3744 +               mod_data.protocol_name = "QIC-157";
3745 +       } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
3746 +                       prot == USB_SC_UFI) {
3747 +               mod_data.protocol_type = USB_SC_UFI;
3748 +               mod_data.protocol_name = "UFI";
3749 +       } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
3750 +                       prot == USB_SC_8070) {
3751 +               mod_data.protocol_type = USB_SC_8070;
3752 +               mod_data.protocol_name = "8070i";
3753 +       } else {
3754 +               ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
3755 +               return -EINVAL;
3756 +       }
3757 +
3758 +       mod_data.buflen &= PAGE_CACHE_MASK;
3759 +       if (mod_data.buflen <= 0) {
3760 +               ERROR(fsg, "invalid buflen\n");
3761 +               return -ETOOSMALL;
3762 +       }
3763 +
3764 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
3765 +
3766 +       /* Serial string handling.
3767 +        * On a real device, the serial string would be loaded
3768 +        * from permanent storage. */
3769 +       if (mod_data.serial) {
3770 +               const char *ch;
3771 +               unsigned len = 0;
3772 +
3773 +               /* Sanity check :
3774 +                * The CB[I] specification limits the serial string to
3775 +                * 12 uppercase hexadecimal characters.
3776 +                * BBB need at least 12 uppercase hexadecimal characters,
3777 +                * with a maximum of 126. */
3778 +               for (ch = mod_data.serial; *ch; ++ch) {
3779 +                       ++len;
3780 +                       if ((*ch < '0' || *ch > '9') &&
3781 +                           (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
3782 +                               WARNING(fsg,
3783 +                                       "Invalid serial string character: %c\n",
3784 +                                       *ch);
3785 +                               goto no_serial;
3786 +                       }
3787 +               }
3788 +               if (len > 126 ||
3789 +                   (mod_data.transport_type == USB_PR_BULK && len < 12) ||
3790 +                   (mod_data.transport_type != USB_PR_BULK && len > 12)) {
3791 +                       WARNING(fsg, "Invalid serial string length!\n");
3792 +                       goto no_serial;
3793 +               }
3794 +               fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
3795 +       } else {
3796 +               WARNING(fsg, "No serial-number string provided!\n");
3797 + no_serial:
3798 +               device_desc.iSerialNumber = 0;
3799 +       }
3800 +
3801 +       return 0;
3802 +}
3803 +
3804 +
3805 +static int __init fsg_bind(struct usb_gadget *gadget)
3806 +{
3807 +       struct fsg_dev          *fsg = the_fsg;
3808 +       int                     rc;
3809 +       int                     i;
3810 +       struct fsg_lun          *curlun;
3811 +       struct usb_ep           *ep;
3812 +       struct usb_request      *req;
3813 +       char                    *pathbuf, *p;
3814 +
3815 +       fsg->gadget = gadget;
3816 +       set_gadget_data(gadget, fsg);
3817 +       fsg->ep0 = gadget->ep0;
3818 +       fsg->ep0->driver_data = fsg;
3819 +
3820 +       if ((rc = check_parameters(fsg)) != 0)
3821 +               goto out;
3822 +
3823 +       if (mod_data.removable) {       // Enable the store_xxx attributes
3824 +               dev_attr_file.attr.mode = 0644;
3825 +               dev_attr_file.store = fsg_store_file;
3826 +               if (!mod_data.cdrom) {
3827 +                       dev_attr_ro.attr.mode = 0644;
3828 +                       dev_attr_ro.store = fsg_store_ro;
3829 +               }
3830 +       }
3831 +
3832 +       /* Only for removable media? */
3833 +       dev_attr_nofua.attr.mode = 0644;
3834 +       dev_attr_nofua.store = fsg_store_nofua;
3835 +
3836 +       /* Find out how many LUNs there should be */
3837 +       i = mod_data.nluns;
3838 +       if (i == 0)
3839 +               i = max(mod_data.num_filenames, 1u);
3840 +       if (i > FSG_MAX_LUNS) {
3841 +               ERROR(fsg, "invalid number of LUNs: %d\n", i);
3842 +               rc = -EINVAL;
3843 +               goto out;
3844 +       }
3845 +
3846 +       /* Create the LUNs, open their backing files, and register the
3847 +        * LUN devices in sysfs. */
3848 +       fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
3849 +       if (!fsg->luns) {
3850 +               rc = -ENOMEM;
3851 +               goto out;
3852 +       }
3853 +       fsg->nluns = i;
3854 +
3855 +       for (i = 0; i < fsg->nluns; ++i) {
3856 +               curlun = &fsg->luns[i];
3857 +               curlun->cdrom = !!mod_data.cdrom;
3858 +               curlun->ro = mod_data.cdrom || mod_data.ro[i];
3859 +               curlun->initially_ro = curlun->ro;
3860 +               curlun->removable = mod_data.removable;
3861 +               curlun->nofua = mod_data.nofua[i];
3862 +               curlun->dev.release = lun_release;
3863 +               curlun->dev.parent = &gadget->dev;
3864 +               curlun->dev.driver = &fsg_driver.driver;
3865 +               dev_set_drvdata(&curlun->dev, &fsg->filesem);
3866 +               dev_set_name(&curlun->dev,"%s-lun%d",
3867 +                            dev_name(&gadget->dev), i);
3868 +
3869 +               kref_get(&fsg->ref);
3870 +               rc = device_register(&curlun->dev);
3871 +               if (rc) {
3872 +                       INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
3873 +                       put_device(&curlun->dev);
3874 +                       goto out;
3875 +               }
3876 +               curlun->registered = 1;
3877 +
3878 +               rc = device_create_file(&curlun->dev, &dev_attr_ro);
3879 +               if (rc)
3880 +                       goto out;
3881 +               rc = device_create_file(&curlun->dev, &dev_attr_nofua);
3882 +               if (rc)
3883 +                       goto out;
3884 +               rc = device_create_file(&curlun->dev, &dev_attr_file);
3885 +               if (rc)
3886 +                       goto out;
3887 +
3888 +               if (mod_data.file[i] && *mod_data.file[i]) {
3889 +                       rc = fsg_lun_open(curlun, mod_data.file[i]);
3890 +                       if (rc)
3891 +                               goto out;
3892 +               } else if (!mod_data.removable) {
3893 +                       ERROR(fsg, "no file given for LUN%d\n", i);
3894 +                       rc = -EINVAL;
3895 +                       goto out;
3896 +               }
3897 +       }
3898 +
3899 +       /* Find all the endpoints we will use */
3900 +       usb_ep_autoconfig_reset(gadget);
3901 +       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
3902 +       if (!ep)
3903 +               goto autoconf_fail;
3904 +       ep->driver_data = fsg;          // claim the endpoint
3905 +       fsg->bulk_in = ep;
3906 +
3907 +       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
3908 +       if (!ep)
3909 +               goto autoconf_fail;
3910 +       ep->driver_data = fsg;          // claim the endpoint
3911 +       fsg->bulk_out = ep;
3912 +
3913 +       if (transport_is_cbi()) {
3914 +               ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
3915 +               if (!ep)
3916 +                       goto autoconf_fail;
3917 +               ep->driver_data = fsg;          // claim the endpoint
3918 +               fsg->intr_in = ep;
3919 +       }
3920 +
3921 +       /* Fix up the descriptors */
3922 +       device_desc.idVendor = cpu_to_le16(mod_data.vendor);
3923 +       device_desc.idProduct = cpu_to_le16(mod_data.product);
3924 +       device_desc.bcdDevice = cpu_to_le16(mod_data.release);
3925 +
3926 +       i = (transport_is_cbi() ? 3 : 2);       // Number of endpoints
3927 +       fsg_intf_desc.bNumEndpoints = i;
3928 +       fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
3929 +       fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
3930 +       fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3931 +
3932 +       if (gadget_is_dualspeed(gadget)) {
3933 +               fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3934 +
3935 +               /* Assume endpoint addresses are the same for both speeds */
3936 +               fsg_hs_bulk_in_desc.bEndpointAddress =
3937 +                       fsg_fs_bulk_in_desc.bEndpointAddress;
3938 +               fsg_hs_bulk_out_desc.bEndpointAddress =
3939 +                       fsg_fs_bulk_out_desc.bEndpointAddress;
3940 +               fsg_hs_intr_in_desc.bEndpointAddress =
3941 +                       fsg_fs_intr_in_desc.bEndpointAddress;
3942 +       }
3943 +
3944 +       if (gadget_is_superspeed(gadget)) {
3945 +               unsigned                max_burst;
3946 +
3947 +               fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3948 +
3949 +               /* Calculate bMaxBurst, we know packet size is 1024 */
3950 +               max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
3951 +
3952 +               /* Assume endpoint addresses are the same for both speeds */
3953 +               fsg_ss_bulk_in_desc.bEndpointAddress =
3954 +                       fsg_fs_bulk_in_desc.bEndpointAddress;
3955 +               fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
3956 +
3957 +               fsg_ss_bulk_out_desc.bEndpointAddress =
3958 +                       fsg_fs_bulk_out_desc.bEndpointAddress;
3959 +               fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
3960 +       }
3961 +
3962 +       if (gadget_is_otg(gadget))
3963 +               fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
3964 +
3965 +       rc = -ENOMEM;
3966 +
3967 +       /* Allocate the request and buffer for endpoint 0 */
3968 +       fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
3969 +       if (!req)
3970 +               goto out;
3971 +       req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
3972 +       if (!req->buf)
3973 +               goto out;
3974 +       req->complete = ep0_complete;
3975 +
3976 +       /* Allocate the data buffers */
3977 +       for (i = 0; i < fsg_num_buffers; ++i) {
3978 +               struct fsg_buffhd       *bh = &fsg->buffhds[i];
3979 +
3980 +               /* Allocate for the bulk-in endpoint.  We assume that
3981 +                * the buffer will also work with the bulk-out (and
3982 +                * interrupt-in) endpoint. */
3983 +               bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
3984 +               if (!bh->buf)
3985 +                       goto out;
3986 +               bh->next = bh + 1;
3987 +       }
3988 +       fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
3989 +
3990 +       /* This should reflect the actual gadget power source */
3991 +       usb_gadget_set_selfpowered(gadget);
3992 +
3993 +       snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
3994 +                       "%s %s with %s",
3995 +                       init_utsname()->sysname, init_utsname()->release,
3996 +                       gadget->name);
3997 +
3998 +       fsg->thread_task = kthread_create(fsg_main_thread, fsg,
3999 +                       "file-storage-gadget");
4000 +       if (IS_ERR(fsg->thread_task)) {
4001 +               rc = PTR_ERR(fsg->thread_task);
4002 +               goto out;
4003 +       }
4004 +
4005 +       INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
4006 +       INFO(fsg, "NOTE: This driver is deprecated.  "
4007 +                       "Consider using g_mass_storage instead.\n");
4008 +       INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
4009 +
4010 +       pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
4011 +       for (i = 0; i < fsg->nluns; ++i) {
4012 +               curlun = &fsg->luns[i];
4013 +               if (fsg_lun_is_open(curlun)) {
4014 +                       p = NULL;
4015 +                       if (pathbuf) {
4016 +                               p = d_path(&curlun->filp->f_path,
4017 +                                          pathbuf, PATH_MAX);
4018 +                               if (IS_ERR(p))
4019 +                                       p = NULL;
4020 +                       }
4021 +                       LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
4022 +                             curlun->ro, curlun->nofua, (p ? p : "(error)"));
4023 +               }
4024 +       }
4025 +       kfree(pathbuf);
4026 +
4027 +       DBG(fsg, "transport=%s (x%02x)\n",
4028 +                       mod_data.transport_name, mod_data.transport_type);
4029 +       DBG(fsg, "protocol=%s (x%02x)\n",
4030 +                       mod_data.protocol_name, mod_data.protocol_type);
4031 +       DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
4032 +                       mod_data.vendor, mod_data.product, mod_data.release);
4033 +       DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
4034 +                       mod_data.removable, mod_data.can_stall,
4035 +                       mod_data.cdrom, mod_data.buflen);
4036 +       DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
4037 +
4038 +       set_bit(REGISTERED, &fsg->atomic_bitflags);
4039 +
4040 +       /* Tell the thread to start working */
4041 +       wake_up_process(fsg->thread_task);
4042 +       return 0;
4043 +
4044 +autoconf_fail:
4045 +       ERROR(fsg, "unable to autoconfigure all endpoints\n");
4046 +       rc = -ENOTSUPP;
4047 +
4048 +out:
4049 +       fsg->state = FSG_STATE_TERMINATED;      // The thread is dead
4050 +       fsg_unbind(gadget);
4051 +       complete(&fsg->thread_notifier);
4052 +       return rc;
4053 +}
4054 +
4055 +
4056 +/*-------------------------------------------------------------------------*/
4057 +
4058 +static void fsg_suspend(struct usb_gadget *gadget)
4059 +{
4060 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
4061 +
4062 +       DBG(fsg, "suspend\n");
4063 +       set_bit(SUSPENDED, &fsg->atomic_bitflags);
4064 +}
4065 +
4066 +static void fsg_resume(struct usb_gadget *gadget)
4067 +{
4068 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
4069 +
4070 +       DBG(fsg, "resume\n");
4071 +       clear_bit(SUSPENDED, &fsg->atomic_bitflags);
4072 +}
4073 +
4074 +
4075 +/*-------------------------------------------------------------------------*/
4076 +
4077 +static struct usb_gadget_driver                fsg_driver = {
4078 +       .max_speed      = USB_SPEED_SUPER,
4079 +       .function       = (char *) fsg_string_product,
4080 +       .unbind         = fsg_unbind,
4081 +       .disconnect     = fsg_disconnect,
4082 +       .setup          = fsg_setup,
4083 +       .suspend        = fsg_suspend,
4084 +       .resume         = fsg_resume,
4085 +
4086 +       .driver         = {
4087 +               .name           = DRIVER_NAME,
4088 +               .owner          = THIS_MODULE,
4089 +               // .release = ...
4090 +               // .suspend = ...
4091 +               // .resume = ...
4092 +       },
4093 +};
4094 +
4095 +
4096 +static int __init fsg_alloc(void)
4097 +{
4098 +       struct fsg_dev          *fsg;
4099 +
4100 +       fsg = kzalloc(sizeof *fsg +
4101 +                     fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
4102 +
4103 +       if (!fsg)
4104 +               return -ENOMEM;
4105 +       spin_lock_init(&fsg->lock);
4106 +       init_rwsem(&fsg->filesem);
4107 +       kref_init(&fsg->ref);
4108 +       init_completion(&fsg->thread_notifier);
4109 +
4110 +       the_fsg = fsg;
4111 +       return 0;
4112 +}
4113 +
4114 +
4115 +static int __init fsg_init(void)
4116 +{
4117 +       int             rc;
4118 +       struct fsg_dev  *fsg;
4119 +
4120 +       rc = fsg_num_buffers_validate();
4121 +       if (rc != 0)
4122 +               return rc;
4123 +
4124 +       if ((rc = fsg_alloc()) != 0)
4125 +               return rc;
4126 +       fsg = the_fsg;
4127 +       if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
4128 +               kref_put(&fsg->ref, fsg_release);
4129 +       return rc;
4130 +}
4131 +module_init(fsg_init);
4132 +
4133 +
4134 +static void __exit fsg_cleanup(void)
4135 +{
4136 +       struct fsg_dev  *fsg = the_fsg;
4137 +
4138 +       /* Unregister the driver iff the thread hasn't already done so */
4139 +       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
4140 +               usb_gadget_unregister_driver(&fsg_driver);
4141 +
4142 +       /* Wait for the thread to finish up */
4143 +       wait_for_completion(&fsg->thread_notifier);
4144 +
4145 +       kref_put(&fsg->ref, fsg_release);
4146 +}
4147 +module_exit(fsg_cleanup);
4148 diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
4149 index 344d5e2..0937bde 100644
4150 --- a/drivers/usb/host/Kconfig
4151 +++ b/drivers/usb/host/Kconfig
4152 @@ -663,6 +663,19 @@ config USB_HWA_HCD
4153           To compile this driver a module, choose M here: the module
4154           will be called "hwa-hc".
4155  
4156 +config USB_DWCOTG
4157 +       tristate "Synopsis DWC host support"
4158 +       depends on USB
4159 +       help
4160 +         The Synopsis DWC controller is a dual-role
4161 +         host/peripheral/OTG ("On The Go") USB controllers.
4162 +
4163 +         Enable this option to support this IP in host controller mode.
4164 +         If unsure, say N.
4165 +
4166 +         To compile this driver as a module, choose M here: the
4167 +         modules built will be called dwc_otg and dwc_common_port.
4168 +
4169  config USB_IMX21_HCD
4170         tristate "i.MX21 HCD support"
4171         depends on ARM && ARCH_MXC
4172 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
4173 index 4fb73c1..76d97de 100644
4174 --- a/drivers/usb/host/Makefile
4175 +++ b/drivers/usb/host/Makefile
4176 @@ -47,6 +47,8 @@ obj-$(CONFIG_USB_U132_HCD)    += u132-hcd.o
4177  obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
4178  obj-$(CONFIG_USB_ISP1760_HCD)  += isp1760.o
4179  obj-$(CONFIG_USB_HWA_HCD)      += hwa-hc.o
4180 +
4181 +obj-$(CONFIG_USB_DWCOTG)        += dwc_otg/ dwc_common_port/
4182  obj-$(CONFIG_USB_IMX21_HCD)    += imx21-hcd.o
4183  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += fsl-mph-dr-of.o
4184  obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
4185 diff --git a/drivers/usb/host/dwc_common_port/Makefile b/drivers/usb/host/dwc_common_port/Makefile
4186 new file mode 100644
4187 index 0000000..63e3485
4188 --- /dev/null
4189 +++ b/drivers/usb/host/dwc_common_port/Makefile
4190 @@ -0,0 +1,58 @@
4191 +#
4192 +# Makefile for DWC_common library
4193 +#
4194 +
4195 +ifneq ($(KERNELRELEASE),)
4196 +
4197 +EXTRA_CFLAGS   += -DDWC_LINUX
4198 +#EXTRA_CFLAGS  += -DDEBUG
4199 +#EXTRA_CFLAGS  += -DDWC_DEBUG_REGS
4200 +#EXTRA_CFLAGS  += -DDWC_DEBUG_MEMORY
4201 +
4202 +EXTRA_CFLAGS   += -DDWC_LIBMODULE
4203 +EXTRA_CFLAGS   += -DDWC_CCLIB
4204 +#EXTRA_CFLAGS  += -DDWC_CRYPTOLIB
4205 +EXTRA_CFLAGS   += -DDWC_NOTIFYLIB
4206 +EXTRA_CFLAGS   += -DDWC_UTFLIB
4207 +
4208 +obj-$(CONFIG_USB_DWCOTG)       += dwc_common_port_lib.o
4209 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
4210 +                           dwc_crypto.o dwc_notifier.o \
4211 +                           dwc_common_linux.o dwc_mem.o
4212 +
4213 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
4214 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
4215 +                           
4216 +ifneq ($(kernrel3),2.6.20)
4217 +# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually
4218 +EXTRA_CFLAGS += $(CPPFLAGS)
4219 +endif
4220 +
4221 +else
4222 +
4223 +#ifeq ($(KDIR),)
4224 +#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
4225 +#endif
4226 +
4227 +ifeq ($(ARCH),)
4228 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
4229 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
4230 +endif
4231 +
4232 +ifeq ($(DOXYGEN),)
4233 +DOXYGEN                := doxygen
4234 +endif
4235 +
4236 +default:
4237 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
4238 +
4239 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
4240 +       $(DOXYGEN) doc/doxygen.cfg
4241 +
4242 +tags:  $(wildcard *.[hc])
4243 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
4244 +
4245 +endif
4246 +
4247 +clean:
4248 +       rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
4249 diff --git a/drivers/usb/host/dwc_common_port/Makefile.fbsd b/drivers/usb/host/dwc_common_port/Makefile.fbsd
4250 new file mode 100644
4251 index 0000000..45db991
4252 --- /dev/null
4253 +++ b/drivers/usb/host/dwc_common_port/Makefile.fbsd
4254 @@ -0,0 +1,17 @@
4255 +CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include
4256 +CFLAGS += -DDWC_FREEBSD
4257 +CFLAGS += -DDEBUG
4258 +#CFLAGS        += -DDWC_DEBUG_REGS
4259 +#CFLAGS        += -DDWC_DEBUG_MEMORY
4260 +
4261 +#CFLAGS        += -DDWC_LIBMODULE
4262 +#CFLAGS        += -DDWC_CCLIB
4263 +#CFLAGS        += -DDWC_CRYPTOLIB
4264 +#CFLAGS        += -DDWC_NOTIFYLIB
4265 +#CFLAGS        += -DDWC_UTFLIB
4266 +
4267 +KMOD = dwc_common_port_lib
4268 +SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \
4269 +       dwc_common_fbsd.c dwc_mem.c
4270 +
4271 +.include <bsd.kmod.mk>
4272 diff --git a/drivers/usb/host/dwc_common_port/Makefile.linux b/drivers/usb/host/dwc_common_port/Makefile.linux
4273 new file mode 100644
4274 index 0000000..961df3f
4275 --- /dev/null
4276 +++ b/drivers/usb/host/dwc_common_port/Makefile.linux
4277 @@ -0,0 +1,49 @@
4278 +#
4279 +# Makefile for DWC_common library
4280 +#
4281 +ifneq ($(KERNELRELEASE),)
4282 +
4283 +EXTRA_CFLAGS   += -DDWC_LINUX
4284 +#EXTRA_CFLAGS  += -DDEBUG
4285 +#EXTRA_CFLAGS  += -DDWC_DEBUG_REGS
4286 +#EXTRA_CFLAGS  += -DDWC_DEBUG_MEMORY
4287 +
4288 +EXTRA_CFLAGS   += -DDWC_LIBMODULE
4289 +EXTRA_CFLAGS   += -DDWC_CCLIB
4290 +EXTRA_CFLAGS   += -DDWC_CRYPTOLIB
4291 +EXTRA_CFLAGS   += -DDWC_NOTIFYLIB
4292 +EXTRA_CFLAGS   += -DDWC_UTFLIB
4293 +
4294 +obj-m                   := dwc_common_port_lib.o
4295 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
4296 +                           dwc_crypto.o dwc_notifier.o \
4297 +                           dwc_common_linux.o dwc_mem.o
4298 +
4299 +else
4300 +
4301 +ifeq ($(KDIR),)
4302 +$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
4303 +endif
4304 +
4305 +ifeq ($(ARCH),)
4306 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
4307 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
4308 +endif
4309 +
4310 +ifeq ($(DOXYGEN),)
4311 +DOXYGEN                := doxygen
4312 +endif
4313 +
4314 +default:
4315 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
4316 +
4317 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
4318 +       $(DOXYGEN) doc/doxygen.cfg
4319 +
4320 +tags:  $(wildcard *.[hc])
4321 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
4322 +
4323 +endif
4324 +
4325 +clean:
4326 +       rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
4327 diff --git a/drivers/usb/host/dwc_common_port/changes.txt b/drivers/usb/host/dwc_common_port/changes.txt
4328 new file mode 100644
4329 index 0000000..f6839f9
4330 --- /dev/null
4331 +++ b/drivers/usb/host/dwc_common_port/changes.txt
4332 @@ -0,0 +1,174 @@
4333 +
4334 +dwc_read_reg32() and friends now take an additional parameter, a pointer to an
4335 +IO context struct. The IO context struct should live in an os-dependent struct
4336 +in your driver. As an example, the dwc_usb3 driver has an os-dependent struct
4337 +named 'os_dep' embedded in the main device struct. So there these calls look
4338 +like this:
4339 +
4340 +       dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg);
4341 +
4342 +       dwc_write_reg32(&usb3_dev->os_dep.ioctx,
4343 +                       &pcd->dev_global_regs->dcfg, 0);
4344 +
4345 +Note that for the existing Linux driver ports, it is not necessary to actually
4346 +define the 'ioctx' member in the os-dependent struct. Since Linux does not
4347 +require an IO context, its macros for dwc_read_reg32() and friends do not
4348 +use the context pointer, so it is optimized away by the compiler. But it is
4349 +necessary to add the pointer parameter to all of the call sites, to be ready
4350 +for any future ports (such as FreeBSD) which do require an IO context.
4351 +
4352 +
4353 +Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now
4354 +take an additional parameter, a pointer to a memory context. Examples:
4355 +
4356 +       addr = dwc_alloc(&usb3_dev->os_dep.memctx, size);
4357 +
4358 +       dwc_free(&usb3_dev->os_dep.memctx, addr);
4359 +
4360 +Again, for the Linux ports, it is not necessary to actually define the memctx
4361 +member, but it is necessary to add the pointer parameter to all of the call
4362 +sites.
4363 +
4364 +
4365 +Same for dwc_dma_alloc() and dwc_dma_free(). Examples:
4366 +
4367 +       virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr);
4368 +
4369 +       dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr);
4370 +
4371 +
4372 +Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples:
4373 +
4374 +       mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx);
4375 +
4376 +       dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex);
4377 +
4378 +
4379 +Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples:
4380 +
4381 +       lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx);
4382 +
4383 +       dwc_spinlock_free(&usb3_dev->osdep.splctx, lock);
4384 +
4385 +
4386 +Same for dwc_timer_alloc(). Example:
4387 +
4388 +       timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1",
4389 +                               cb_func, cb_data);
4390 +
4391 +
4392 +Same for dwc_waitq_alloc(). Example:
4393 +
4394 +       waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx);
4395 +
4396 +
4397 +Same for dwc_thread_run(). Example:
4398 +
4399 +       thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func,
4400 +                               "dwc_usb3_thd1", data);
4401 +
4402 +
4403 +Same for dwc_workq_alloc(). Example:
4404 +
4405 +       workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1");
4406 +
4407 +
4408 +Same for dwc_task_alloc(). Example:
4409 +
4410 +       task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1",
4411 +                             cb_func, cb_data);
4412 +
4413 +
4414 +In addition to the context pointer additions, a few core functions have had
4415 +other changes made to their parameters:
4416 +
4417 +The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore()
4418 +has been changed from a uint64_t to a dwc_irqflags_t.
4419 +
4420 +dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the
4421 +FreeBSD equivalent of that function requires it.
4422 +
4423 +And, in addition to the context pointer, dwc_task_alloc() also adds a
4424 +'char *name' parameter, to be consistent with dwc_thread_run() and
4425 +dwc_workq_alloc(), and because the FreeBSD equivalent of that function
4426 +requires a unique name.
4427 +
4428 +
4429 +Here is a complete list of the core functions that now take a pointer to a
4430 +context as their first parameter:
4431 +
4432 +       dwc_read_reg32
4433 +       dwc_read_reg64
4434 +       dwc_write_reg32
4435 +       dwc_write_reg64
4436 +       dwc_modify_reg32
4437 +       dwc_modify_reg64
4438 +       dwc_alloc
4439 +       dwc_alloc_atomic
4440 +       dwc_strdup
4441 +       dwc_free
4442 +       dwc_dma_alloc
4443 +       dwc_dma_free
4444 +       dwc_mutex_alloc
4445 +       dwc_mutex_free
4446 +       dwc_spinlock_alloc
4447 +       dwc_spinlock_free
4448 +       dwc_timer_alloc
4449 +       dwc_waitq_alloc
4450 +       dwc_thread_run
4451 +       dwc_workq_alloc
4452 +       dwc_task_alloc     Also adds a 'char *name' as its 2nd parameter
4453 +
4454 +And here are the core functions that have other changes to their parameters:
4455 +
4456 +       dwc_spinlock_irqsave      'flags' param is now a 'dwc_irqflags_t *'
4457 +       dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t'
4458 +       dwc_thread_should_stop    Adds a 'dwc_thread_t *' parameter
4459 +
4460 +
4461 +
4462 +The changes to the core functions also require some of the other library
4463 +functions to change:
4464 +
4465 +       dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx'
4466 +       (for memory allocation) as the 1st param and a 'void *mtxctx'
4467 +       (for mutex allocation) as the 2nd param.
4468 +
4469 +       dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(),
4470 +       dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a
4471 +       'void *memctx' as the 1st param.
4472 +
4473 +       dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a
4474 +       'void *memctx' as the 1st param.
4475 +
4476 +       dwc_modpow() now takes a 'void *memctx' as the 1st param.
4477 +
4478 +       dwc_alloc_notification_manager() now takes a 'void *memctx' as the
4479 +       1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd
4480 +       param, and also now returns an integer value that is non-zero if
4481 +       allocation of its data structures or work queue fails.
4482 +
4483 +       dwc_register_notifier() now takes a 'void *memctx' as the 1st param.
4484 +
4485 +       dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first
4486 +       param, and also now returns an integer value that is non-zero if
4487 +       allocation of its data structures fails.
4488 +
4489 +
4490 +
4491 +Other miscellaneous changes:
4492 +
4493 +The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to
4494 +DWC_DEBUG_MEMORY and DWC_DEBUG_REGS.
4495 +
4496 +The following #define's have been added to allow selectively compiling library
4497 +features:
4498 +
4499 +       DWC_CCLIB
4500 +       DWC_CRYPTOLIB
4501 +       DWC_NOTIFYLIB
4502 +       DWC_UTFLIB
4503 +
4504 +A DWC_LIBMODULE #define has also been added. If this is not defined, then the
4505 +module code in dwc_common_linux.c is not compiled in. This allows linking the
4506 +library code directly into a driver module, instead of as a standalone module.
4507 diff --git a/drivers/usb/host/dwc_common_port/doc/doxygen.cfg b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
4508 new file mode 100644
4509 index 0000000..605b9dab
4510 --- /dev/null
4511 +++ b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
4512 @@ -0,0 +1,270 @@
4513 +# Doxyfile 1.4.5
4514 +
4515 +#---------------------------------------------------------------------------
4516 +# Project related configuration options
4517 +#---------------------------------------------------------------------------
4518 +PROJECT_NAME           = "Synopsys DWC Portability and Common Library for UWB"
4519 +PROJECT_NUMBER         = 
4520 +OUTPUT_DIRECTORY       = doc
4521 +CREATE_SUBDIRS         = NO
4522 +OUTPUT_LANGUAGE        = English
4523 +BRIEF_MEMBER_DESC      = YES
4524 +REPEAT_BRIEF           = YES
4525 +ABBREVIATE_BRIEF       = "The $name class" \
4526 +                         "The $name widget" \
4527 +                         "The $name file" \
4528 +                         is \
4529 +                         provides \
4530 +                         specifies \
4531 +                         contains \
4532 +                         represents \
4533 +                         a \
4534 +                         an \
4535 +                         the
4536 +ALWAYS_DETAILED_SEC    = YES
4537 +INLINE_INHERITED_MEMB  = NO
4538 +FULL_PATH_NAMES        = NO
4539 +STRIP_FROM_PATH        = ..
4540 +STRIP_FROM_INC_PATH    = 
4541 +SHORT_NAMES            = NO
4542 +JAVADOC_AUTOBRIEF      = YES
4543 +MULTILINE_CPP_IS_BRIEF = NO
4544 +DETAILS_AT_TOP         = YES
4545 +INHERIT_DOCS           = YES
4546 +SEPARATE_MEMBER_PAGES  = NO
4547 +TAB_SIZE               = 8
4548 +ALIASES                = 
4549 +OPTIMIZE_OUTPUT_FOR_C  = YES
4550 +OPTIMIZE_OUTPUT_JAVA   = NO
4551 +BUILTIN_STL_SUPPORT    = NO
4552 +DISTRIBUTE_GROUP_DOC   = NO
4553 +SUBGROUPING            = NO
4554 +#---------------------------------------------------------------------------
4555 +# Build related configuration options
4556 +#---------------------------------------------------------------------------
4557 +EXTRACT_ALL            = NO
4558 +EXTRACT_PRIVATE        = NO
4559 +EXTRACT_STATIC         = YES
4560 +EXTRACT_LOCAL_CLASSES  = NO
4561 +EXTRACT_LOCAL_METHODS  = NO
4562 +HIDE_UNDOC_MEMBERS     = NO
4563 +HIDE_UNDOC_CLASSES     = NO
4564 +HIDE_FRIEND_COMPOUNDS  = NO
4565 +HIDE_IN_BODY_DOCS      = NO
4566 +INTERNAL_DOCS          = NO
4567 +CASE_SENSE_NAMES       = YES
4568 +HIDE_SCOPE_NAMES       = NO
4569 +SHOW_INCLUDE_FILES     = NO
4570 +INLINE_INFO            = YES
4571 +SORT_MEMBER_DOCS       = NO
4572 +SORT_BRIEF_DOCS        = NO
4573 +SORT_BY_SCOPE_NAME     = NO
4574 +GENERATE_TODOLIST      = YES
4575 +GENERATE_TESTLIST      = YES
4576 +GENERATE_BUGLIST       = YES
4577 +GENERATE_DEPRECATEDLIST= YES
4578 +ENABLED_SECTIONS       = 
4579 +MAX_INITIALIZER_LINES  = 30
4580 +SHOW_USED_FILES        = YES
4581 +SHOW_DIRECTORIES       = YES
4582 +FILE_VERSION_FILTER    = 
4583 +#---------------------------------------------------------------------------
4584 +# configuration options related to warning and progress messages
4585 +#---------------------------------------------------------------------------
4586 +QUIET                  = YES
4587 +WARNINGS               = YES
4588 +WARN_IF_UNDOCUMENTED   = NO
4589 +WARN_IF_DOC_ERROR      = YES
4590 +WARN_NO_PARAMDOC       = YES
4591 +WARN_FORMAT            = "$file:$line: $text"
4592 +WARN_LOGFILE           = 
4593 +#---------------------------------------------------------------------------
4594 +# configuration options related to the input files
4595 +#---------------------------------------------------------------------------
4596 +INPUT                  = .
4597 +FILE_PATTERNS          = *.c \
4598 +                         *.cc \
4599 +                         *.cxx \
4600 +                         *.cpp \
4601 +                         *.c++ \
4602 +                         *.d \
4603 +                         *.java \
4604 +                         *.ii \
4605 +                         *.ixx \
4606 +                         *.ipp \
4607 +                         *.i++ \
4608 +                         *.inl \
4609 +                         *.h \
4610 +                         *.hh \
4611 +                         *.hxx \
4612 +                         *.hpp \
4613 +                         *.h++ \
4614 +                         *.idl \
4615 +                         *.odl \
4616 +                         *.cs \
4617 +                         *.php \
4618 +                         *.php3 \
4619 +                         *.inc \
4620 +                         *.m \
4621 +                         *.mm \
4622 +                         *.dox \
4623 +                         *.py \
4624 +                         *.C \
4625 +                         *.CC \
4626 +                         *.C++ \
4627 +                         *.II \
4628 +                         *.I++ \
4629 +                         *.H \
4630 +                         *.HH \
4631 +                         *.H++ \
4632 +                         *.CS \
4633 +                         *.PHP \
4634 +                         *.PHP3 \
4635 +                         *.M \
4636 +                         *.MM \
4637 +                         *.PY
4638 +RECURSIVE              = NO
4639 +EXCLUDE                = 
4640 +EXCLUDE_SYMLINKS       = NO
4641 +EXCLUDE_PATTERNS       = 
4642 +EXAMPLE_PATH           = 
4643 +EXAMPLE_PATTERNS       = *
4644 +EXAMPLE_RECURSIVE      = NO
4645 +IMAGE_PATH             = 
4646 +INPUT_FILTER           = 
4647 +FILTER_PATTERNS        = 
4648 +FILTER_SOURCE_FILES    = NO
4649 +#---------------------------------------------------------------------------
4650 +# configuration options related to source browsing
4651 +#---------------------------------------------------------------------------
4652 +SOURCE_BROWSER         = NO
4653 +INLINE_SOURCES         = NO
4654 +STRIP_CODE_COMMENTS    = YES
4655 +REFERENCED_BY_RELATION = YES
4656 +REFERENCES_RELATION    = YES
4657 +USE_HTAGS              = NO
4658 +VERBATIM_HEADERS       = NO
4659 +#---------------------------------------------------------------------------
4660 +# configuration options related to the alphabetical class index
4661 +#---------------------------------------------------------------------------
4662 +ALPHABETICAL_INDEX     = NO
4663 +COLS_IN_ALPHA_INDEX    = 5
4664 +IGNORE_PREFIX          = 
4665 +#---------------------------------------------------------------------------
4666 +# configuration options related to the HTML output
4667 +#---------------------------------------------------------------------------
4668 +GENERATE_HTML          = YES
4669 +HTML_OUTPUT            = html
4670 +HTML_FILE_EXTENSION    = .html
4671 +HTML_HEADER            = 
4672 +HTML_FOOTER            = 
4673 +HTML_STYLESHEET        = 
4674 +HTML_ALIGN_MEMBERS     = YES
4675 +GENERATE_HTMLHELP      = NO
4676 +CHM_FILE               = 
4677 +HHC_LOCATION           = 
4678 +GENERATE_CHI           = NO
4679 +BINARY_TOC             = NO
4680 +TOC_EXPAND             = NO
4681 +DISABLE_INDEX          = NO
4682 +ENUM_VALUES_PER_LINE   = 4
4683 +GENERATE_TREEVIEW      = YES
4684 +TREEVIEW_WIDTH         = 250
4685 +#---------------------------------------------------------------------------
4686 +# configuration options related to the LaTeX output
4687 +#---------------------------------------------------------------------------
4688 +GENERATE_LATEX         = NO
4689 +LATEX_OUTPUT           = latex
4690 +LATEX_CMD_NAME         = latex
4691 +MAKEINDEX_CMD_NAME     = makeindex
4692 +COMPACT_LATEX          = NO
4693 +PAPER_TYPE             = a4wide
4694 +EXTRA_PACKAGES         = 
4695 +LATEX_HEADER           = 
4696 +PDF_HYPERLINKS         = NO
4697 +USE_PDFLATEX           = NO
4698 +LATEX_BATCHMODE        = NO
4699 +LATEX_HIDE_INDICES     = NO
4700 +#---------------------------------------------------------------------------
4701 +# configuration options related to the RTF output
4702 +#---------------------------------------------------------------------------
4703 +GENERATE_RTF           = NO
4704 +RTF_OUTPUT             = rtf
4705 +COMPACT_RTF            = NO
4706 +RTF_HYPERLINKS         = NO
4707 +RTF_STYLESHEET_FILE    = 
4708 +RTF_EXTENSIONS_FILE    = 
4709 +#---------------------------------------------------------------------------
4710 +# configuration options related to the man page output
4711 +#---------------------------------------------------------------------------
4712 +GENERATE_MAN           = NO
4713 +MAN_OUTPUT             = man
4714 +MAN_EXTENSION          = .3
4715 +MAN_LINKS              = NO
4716 +#---------------------------------------------------------------------------
4717 +# configuration options related to the XML output
4718 +#---------------------------------------------------------------------------
4719 +GENERATE_XML           = NO
4720 +XML_OUTPUT             = xml
4721 +XML_SCHEMA             = 
4722 +XML_DTD                = 
4723 +XML_PROGRAMLISTING     = YES
4724 +#---------------------------------------------------------------------------
4725 +# configuration options for the AutoGen Definitions output
4726 +#---------------------------------------------------------------------------
4727 +GENERATE_AUTOGEN_DEF   = NO
4728 +#---------------------------------------------------------------------------
4729 +# configuration options related to the Perl module output
4730 +#---------------------------------------------------------------------------
4731 +GENERATE_PERLMOD       = NO
4732 +PERLMOD_LATEX          = NO
4733 +PERLMOD_PRETTY         = YES
4734 +PERLMOD_MAKEVAR_PREFIX = 
4735 +#---------------------------------------------------------------------------
4736 +# Configuration options related to the preprocessor   
4737 +#---------------------------------------------------------------------------
4738 +ENABLE_PREPROCESSING   = YES
4739 +MACRO_EXPANSION        = NO
4740 +EXPAND_ONLY_PREDEF     = NO
4741 +SEARCH_INCLUDES        = YES
4742 +INCLUDE_PATH           = 
4743 +INCLUDE_FILE_PATTERNS  = 
4744 +PREDEFINED             = DEBUG DEBUG_MEMORY
4745 +EXPAND_AS_DEFINED      = 
4746 +SKIP_FUNCTION_MACROS   = YES
4747 +#---------------------------------------------------------------------------
4748 +# Configuration::additions related to external references   
4749 +#---------------------------------------------------------------------------
4750 +TAGFILES               = 
4751 +GENERATE_TAGFILE       = 
4752 +ALLEXTERNALS           = NO
4753 +EXTERNAL_GROUPS        = YES
4754 +PERL_PATH              = /usr/bin/perl
4755 +#---------------------------------------------------------------------------
4756 +# Configuration options related to the dot tool   
4757 +#---------------------------------------------------------------------------
4758 +CLASS_DIAGRAMS         = YES
4759 +HIDE_UNDOC_RELATIONS   = YES
4760 +HAVE_DOT               = NO
4761 +CLASS_GRAPH            = YES
4762 +COLLABORATION_GRAPH    = YES
4763 +GROUP_GRAPHS           = YES
4764 +UML_LOOK               = NO
4765 +TEMPLATE_RELATIONS     = NO
4766 +INCLUDE_GRAPH          = NO
4767 +INCLUDED_BY_GRAPH      = YES
4768 +CALL_GRAPH             = NO
4769 +GRAPHICAL_HIERARCHY    = YES
4770 +DIRECTORY_GRAPH        = YES
4771 +DOT_IMAGE_FORMAT       = png
4772 +DOT_PATH               = 
4773 +DOTFILE_DIRS           = 
4774 +MAX_DOT_GRAPH_DEPTH    = 1000
4775 +DOT_TRANSPARENT        = NO
4776 +DOT_MULTI_TARGETS      = NO
4777 +GENERATE_LEGEND        = YES
4778 +DOT_CLEANUP            = YES
4779 +#---------------------------------------------------------------------------
4780 +# Configuration::additions related to the search engine   
4781 +#---------------------------------------------------------------------------
4782 +SEARCHENGINE           = NO
4783 diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.c b/drivers/usb/host/dwc_common_port/dwc_cc.c
4784 new file mode 100644
4785 index 0000000..613c901
4786 --- /dev/null
4787 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.c
4788 @@ -0,0 +1,532 @@
4789 +/* =========================================================================
4790 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
4791 + * $Revision: #4 $
4792 + * $Date: 2010/11/04 $
4793 + * $Change: 1621692 $
4794 + *
4795 + * Synopsys Portability Library Software and documentation
4796 + * (hereinafter, "Software") is an Unsupported proprietary work of
4797 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
4798 + * between Synopsys and you.
4799 + *
4800 + * The Software IS NOT an item of Licensed Software or Licensed Product
4801 + * under any End User Software License Agreement or Agreement for
4802 + * Licensed Product with Synopsys or any supplement thereto. You are
4803 + * permitted to use and redistribute this Software in source and binary
4804 + * forms, with or without modification, provided that redistributions
4805 + * of source code must retain this notice. You may not view, use,
4806 + * disclose, copy or distribute this file or any information contained
4807 + * herein except pursuant to this license grant from Synopsys. If you
4808 + * do not agree with this notice, including the disclaimer below, then
4809 + * you are not authorized to use the Software.
4810 + *
4811 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
4812 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4813 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
4814 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
4815 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4816 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4817 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4818 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
4819 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4820 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4821 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
4822 + * DAMAGE.
4823 + * ========================================================================= */
4824 +#ifdef DWC_CCLIB
4825 +
4826 +#include "dwc_cc.h"
4827 +
4828 +typedef struct dwc_cc
4829 +{
4830 +       uint32_t uid;
4831 +       uint8_t chid[16];
4832 +       uint8_t cdid[16];
4833 +       uint8_t ck[16];
4834 +       uint8_t *name;
4835 +       uint8_t length;
4836 +        DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
4837 +} dwc_cc_t;
4838 +
4839 +DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
4840 +
4841 +/** The main structure for CC management.  */
4842 +struct dwc_cc_if
4843 +{
4844 +       dwc_mutex_t *mutex;
4845 +       char *filename;
4846 +
4847 +       unsigned is_host:1;
4848 +
4849 +       dwc_notifier_t *notifier;
4850 +
4851 +       struct context_list list;
4852 +};
4853 +
4854 +#ifdef DEBUG
4855 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
4856 +{
4857 +       int i;
4858 +       DWC_PRINTF("%s: ", name);
4859 +       for (i=0; i<len; i++) {
4860 +               DWC_PRINTF("%02x ", bytes[i]);
4861 +       }
4862 +       DWC_PRINTF("\n");
4863 +}
4864 +#else
4865 +#define dump_bytes(x...)
4866 +#endif
4867 +
4868 +static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
4869 +{
4870 +       dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
4871 +       if (!cc) {
4872 +               return NULL;
4873 +       }
4874 +       DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
4875 +
4876 +       if (name) {
4877 +               cc->length = length;
4878 +               cc->name = dwc_alloc(mem_ctx, length);
4879 +               if (!cc->name) {
4880 +                       dwc_free(mem_ctx, cc);
4881 +                       return NULL;
4882 +               }
4883 +
4884 +               DWC_MEMCPY(cc->name, name, length);
4885 +       }
4886 +
4887 +       return cc;
4888 +}
4889 +
4890 +static void free_cc(void *mem_ctx, dwc_cc_t *cc)
4891 +{
4892 +       if (cc->name) {
4893 +               dwc_free(mem_ctx, cc->name);
4894 +       }
4895 +       dwc_free(mem_ctx, cc);
4896 +}
4897 +
4898 +static uint32_t next_uid(dwc_cc_if_t *cc_if)
4899 +{
4900 +       uint32_t uid = 0;
4901 +       dwc_cc_t *cc;
4902 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4903 +               if (cc->uid > uid) {
4904 +                       uid = cc->uid;
4905 +               }
4906 +       }
4907 +
4908 +       if (uid == 0) {
4909 +               uid = 255;
4910 +       }
4911 +
4912 +       return uid + 1;
4913 +}
4914 +
4915 +static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
4916 +{
4917 +       dwc_cc_t *cc;
4918 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4919 +               if (cc->uid == uid) {
4920 +                       return cc;
4921 +               }
4922 +       }
4923 +       return NULL;
4924 +}
4925 +
4926 +static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
4927 +{
4928 +       unsigned int size = 0;
4929 +       dwc_cc_t *cc;
4930 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4931 +               size += (48 + 1);
4932 +               if (cc->name) {
4933 +                       size += cc->length;
4934 +               }
4935 +       }
4936 +       return size;
4937 +}
4938 +
4939 +static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
4940 +{
4941 +       uint32_t uid = 0;
4942 +       dwc_cc_t *cc;
4943 +
4944 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4945 +               if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
4946 +                       uid = cc->uid;
4947 +                       break;
4948 +               }
4949 +       }
4950 +       return uid;
4951 +}
4952 +static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
4953 +{
4954 +       uint32_t uid = 0;
4955 +       dwc_cc_t *cc;
4956 +
4957 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4958 +               if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
4959 +                       uid = cc->uid;
4960 +                       break;
4961 +               }
4962 +       }
4963 +       return uid;
4964 +}
4965 +
4966 +/* Internal cc_add */
4967 +static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
4968 +                     uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4969 +{
4970 +       dwc_cc_t *cc;
4971 +       uint32_t uid;
4972 +
4973 +       if (cc_if->is_host) {
4974 +               uid = cc_match_cdid(cc_if, cdid);
4975 +       }
4976 +       else {
4977 +               uid = cc_match_chid(cc_if, chid);
4978 +       }
4979 +
4980 +       if (uid) {
4981 +               DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
4982 +               cc = cc_find(cc_if, uid);
4983 +       }
4984 +       else {
4985 +               cc = alloc_cc(mem_ctx, name, length);
4986 +               cc->uid = next_uid(cc_if);
4987 +               DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
4988 +       }
4989 +
4990 +       DWC_MEMCPY(&(cc->chid[0]), chid, 16);
4991 +       DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
4992 +       DWC_MEMCPY(&(cc->ck[0]), ck, 16);
4993 +
4994 +       DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
4995 +       dump_bytes("CHID", cc->chid, 16);
4996 +       dump_bytes("CDID", cc->cdid, 16);
4997 +       dump_bytes("CK", cc->ck, 16);
4998 +       return cc->uid;
4999 +}
5000 +
5001 +/* Internal cc_clear */
5002 +static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
5003 +{
5004 +       while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
5005 +               dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
5006 +               DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
5007 +               free_cc(mem_ctx, cc);
5008 +       }
5009 +}
5010 +
5011 +dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, 
5012 +                            dwc_notifier_t *notifier, unsigned is_host)
5013 +{
5014 +       dwc_cc_if_t *cc_if = NULL;
5015 +
5016 +       /* Allocate a common_cc_if structure */
5017 +       cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
5018 +
5019 +       if (!cc_if)
5020 +               return NULL;
5021 +
5022 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
5023 +       DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
5024 +#else
5025 +       cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
5026 +#endif
5027 +       if (!cc_if->mutex) {
5028 +               dwc_free(mem_ctx, cc_if);
5029 +               return NULL;
5030 +       }
5031 +
5032 +       DWC_CIRCLEQ_INIT(&cc_if->list);
5033 +       cc_if->is_host = is_host;
5034 +       cc_if->notifier = notifier;
5035 +       return cc_if;
5036 +}
5037 +
5038 +void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
5039 +{
5040 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
5041 +       DWC_MUTEX_FREE(cc_if->mutex);
5042 +#else
5043 +       dwc_mutex_free(mtx_ctx, cc_if->mutex);
5044 +#endif
5045 +       cc_clear(mem_ctx, cc_if);
5046 +       dwc_free(mem_ctx, cc_if);
5047 +}
5048 +
5049 +static void cc_changed(dwc_cc_if_t *cc_if)
5050 +{
5051 +       if (cc_if->notifier) {
5052 +               dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
5053 +       }
5054 +}
5055 +
5056 +void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
5057 +{
5058 +       DWC_MUTEX_LOCK(cc_if->mutex);
5059 +       cc_clear(mem_ctx, cc_if);
5060 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5061 +       cc_changed(cc_if);
5062 +}
5063 +
5064 +int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
5065 +                  uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
5066 +{
5067 +       uint32_t uid;
5068 +
5069 +       DWC_MUTEX_LOCK(cc_if->mutex);
5070 +       uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
5071 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5072 +       cc_changed(cc_if);
5073 +
5074 +       return uid;
5075 +}
5076 +
5077 +void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,
5078 +                  uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
5079 +{
5080 +       dwc_cc_t* cc;
5081 +
5082 +       DWC_DEBUGC("Change connection context %d", id);
5083 +
5084 +       DWC_MUTEX_LOCK(cc_if->mutex);
5085 +       cc = cc_find(cc_if, id);
5086 +       if (!cc) {
5087 +               DWC_ERROR("Uid %d not found in cc list\n", id);
5088 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5089 +               return;
5090 +       }
5091 +
5092 +       if (chid) {
5093 +               DWC_MEMCPY(&(cc->chid[0]), chid, 16);
5094 +       }
5095 +       if (cdid) {
5096 +               DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
5097 +       }
5098 +       if (ck) {
5099 +               DWC_MEMCPY(&(cc->ck[0]), ck, 16);
5100 +       }
5101 +
5102 +       if (name) {
5103 +               if (cc->name) {
5104 +                       dwc_free(mem_ctx, cc->name);
5105 +               }
5106 +               cc->name = dwc_alloc(mem_ctx, length);
5107 +               if (!cc->name) {
5108 +                       DWC_ERROR("Out of memory in dwc_cc_change()\n");
5109 +                       DWC_MUTEX_UNLOCK(cc_if->mutex);
5110 +                       return;
5111 +               }
5112 +               cc->length = length;
5113 +               DWC_MEMCPY(cc->name, name, length);
5114 +       }
5115 +
5116 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5117 +
5118 +       cc_changed(cc_if);
5119 +
5120 +       DWC_DEBUGC("Changed connection context id=%d\n", id);
5121 +       dump_bytes("New CHID", cc->chid, 16);
5122 +       dump_bytes("New CDID", cc->cdid, 16);
5123 +       dump_bytes("New CK", cc->ck, 16);
5124 +}
5125 +
5126 +void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
5127 +{
5128 +       dwc_cc_t *cc;
5129 +
5130 +       DWC_DEBUGC("Removing connection context %d", id);
5131 +
5132 +       DWC_MUTEX_LOCK(cc_if->mutex);
5133 +       cc = cc_find(cc_if, id);
5134 +       if (!cc) {
5135 +               DWC_ERROR("Uid %d not found in cc list\n", id);
5136 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5137 +               return;
5138 +       }
5139 +
5140 +       DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
5141 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5142 +       free_cc(mem_ctx, cc);
5143 +
5144 +       cc_changed(cc_if);
5145 +}
5146 +
5147 +uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
5148 +{
5149 +       uint8_t *buf, *x;
5150 +       uint8_t zero = 0;
5151 +       dwc_cc_t *cc;
5152 +
5153 +       DWC_MUTEX_LOCK(cc_if->mutex);
5154 +       *length = cc_data_size(cc_if);
5155 +       if (!(*length)) {
5156 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5157 +               return NULL;
5158 +       }
5159 +
5160 +       DWC_DEBUGC("Creating data for saving (length=%d)", *length);
5161 +
5162 +       buf = dwc_alloc(mem_ctx, *length);
5163 +       if (!buf) {
5164 +               *length = 0;
5165 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5166 +               return NULL;
5167 +       }
5168 +
5169 +       x = buf;
5170 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
5171 +               DWC_MEMCPY(x, cc->chid, 16);
5172 +               x += 16;
5173 +               DWC_MEMCPY(x, cc->cdid, 16);
5174 +               x += 16;
5175 +               DWC_MEMCPY(x, cc->ck, 16);
5176 +               x += 16;
5177 +               if (cc->name) {
5178 +                       DWC_MEMCPY(x, &cc->length, 1);
5179 +                       x += 1;
5180 +                       DWC_MEMCPY(x, cc->name, cc->length);
5181 +                       x += cc->length;
5182 +               }
5183 +               else {
5184 +                       DWC_MEMCPY(x, &zero, 1);
5185 +                       x += 1;
5186 +               }
5187 +       }
5188 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5189 +
5190 +       return buf;
5191 +}
5192 +
5193 +void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
5194 +{
5195 +       uint8_t name_length;
5196 +       uint8_t *name;
5197 +       uint8_t *chid;
5198 +       uint8_t *cdid;
5199 +       uint8_t *ck;
5200 +       uint32_t i = 0;
5201 +
5202 +       DWC_MUTEX_LOCK(cc_if->mutex);
5203 +       cc_clear(mem_ctx, cc_if);
5204 +
5205 +       while (i < length) {
5206 +               chid = &data[i];
5207 +               i += 16;
5208 +               cdid = &data[i];
5209 +               i += 16;
5210 +               ck = &data[i];
5211 +               i += 16;
5212 +
5213 +               name_length = data[i];
5214 +               i ++;
5215 +
5216 +               if (name_length) {
5217 +                       name = &data[i];
5218 +                       i += name_length;
5219 +               }
5220 +               else {
5221 +                       name = NULL;
5222 +               }
5223 +
5224 +               /* check to see if we haven't overflown the buffer */
5225 +               if (i > length) {
5226 +                       DWC_ERROR("Data format error while attempting to load CCs "
5227 +                                 "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
5228 +                       break;
5229 +               }
5230 +
5231 +               cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
5232 +       }
5233 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5234 +
5235 +       cc_changed(cc_if);
5236 +}
5237 +
5238 +uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
5239 +{
5240 +       uint32_t uid = 0;
5241 +
5242 +       DWC_MUTEX_LOCK(cc_if->mutex);
5243 +       uid = cc_match_chid(cc_if, chid);
5244 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5245 +       return uid;
5246 +}
5247 +uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
5248 +{
5249 +       uint32_t uid = 0;
5250 +
5251 +       DWC_MUTEX_LOCK(cc_if->mutex);
5252 +       uid = cc_match_cdid(cc_if, cdid);
5253 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5254 +       return uid;
5255 +}
5256 +
5257 +uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
5258 +{
5259 +       uint8_t *ck = NULL;
5260 +       dwc_cc_t *cc;
5261 +
5262 +       DWC_MUTEX_LOCK(cc_if->mutex);
5263 +       cc = cc_find(cc_if, id);
5264 +       if (cc) {
5265 +               ck = cc->ck;
5266 +       }
5267 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5268 +
5269 +       return ck;
5270 +
5271 +}
5272 +
5273 +uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
5274 +{
5275 +       uint8_t *retval = NULL;
5276 +       dwc_cc_t *cc;
5277 +
5278 +       DWC_MUTEX_LOCK(cc_if->mutex);
5279 +       cc = cc_find(cc_if, id);
5280 +       if (cc) {
5281 +               retval = cc->chid;
5282 +       }
5283 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5284 +
5285 +       return retval;
5286 +}
5287 +
5288 +uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
5289 +{
5290 +       uint8_t *retval = NULL;
5291 +       dwc_cc_t *cc;
5292 +
5293 +       DWC_MUTEX_LOCK(cc_if->mutex);
5294 +       cc = cc_find(cc_if, id);
5295 +       if (cc) {
5296 +               retval = cc->cdid;
5297 +       }
5298 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5299 +
5300 +       return retval;
5301 +}
5302 +
5303 +uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
5304 +{
5305 +       uint8_t *retval = NULL;
5306 +       dwc_cc_t *cc;
5307 +
5308 +       DWC_MUTEX_LOCK(cc_if->mutex);
5309 +       *length = 0;
5310 +       cc = cc_find(cc_if, id);
5311 +       if (cc) {
5312 +               *length = cc->length;
5313 +               retval = cc->name;
5314 +       }
5315 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5316 +
5317 +       return retval;
5318 +}
5319 +
5320 +#endif /* DWC_CCLIB */
5321 diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.h b/drivers/usb/host/dwc_common_port/dwc_cc.h
5322 new file mode 100644
5323 index 0000000..6b2bbaf
5324 --- /dev/null
5325 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.h
5326 @@ -0,0 +1,225 @@
5327 +/* =========================================================================
5328 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $
5329 + * $Revision: #4 $
5330 + * $Date: 2010/09/28 $
5331 + * $Change: 1596182 $
5332 + *
5333 + * Synopsys Portability Library Software and documentation
5334 + * (hereinafter, "Software") is an Unsupported proprietary work of
5335 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
5336 + * between Synopsys and you.
5337 + *
5338 + * The Software IS NOT an item of Licensed Software or Licensed Product
5339 + * under any End User Software License Agreement or Agreement for
5340 + * Licensed Product with Synopsys or any supplement thereto. You are
5341 + * permitted to use and redistribute this Software in source and binary
5342 + * forms, with or without modification, provided that redistributions
5343 + * of source code must retain this notice. You may not view, use,
5344 + * disclose, copy or distribute this file or any information contained
5345 + * herein except pursuant to this license grant from Synopsys. If you
5346 + * do not agree with this notice, including the disclaimer below, then
5347 + * you are not authorized to use the Software.
5348 + *
5349 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
5350 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5351 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
5352 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
5353 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5354 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5355 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5356 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
5357 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5358 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
5359 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
5360 + * DAMAGE.
5361 + * ========================================================================= */
5362 +#ifndef _DWC_CC_H_
5363 +#define _DWC_CC_H_
5364 +
5365 +#ifdef __cplusplus
5366 +extern "C" {
5367 +#endif
5368 +
5369 +/** @file
5370 + *
5371 + * This file defines the Context Context library.
5372 + *
5373 + * The main data structure is dwc_cc_if_t which is returned by either the
5374 + * dwc_cc_if_alloc function or returned by the module to the user via a provided
5375 + * function. The data structure is opaque and should only be manipulated via the
5376 + * functions provied in this API.
5377 + *
5378 + * It manages a list of connection contexts and operations can be performed to
5379 + * add, remove, query, search, and change, those contexts.  Additionally,
5380 + * a dwc_notifier_t object can be requested from the manager so that
5381 + * the user can be notified whenever the context list has changed.
5382 + */
5383 +
5384 +#include "dwc_os.h"
5385 +#include "dwc_list.h"
5386 +#include "dwc_notifier.h"
5387 +
5388 +
5389 +/* Notifications */
5390 +#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"
5391 +
5392 +struct dwc_cc_if;
5393 +typedef struct dwc_cc_if dwc_cc_if_t;
5394 +
5395 +
5396 +/** @name Connection Context Operations */
5397 +/** @{ */
5398 +
5399 +/** This function allocates memory for a dwc_cc_if_t structure, initializes
5400 + * fields to default values, and returns a pointer to the structure or NULL on
5401 + * error. */
5402 +extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
5403 +                                   dwc_notifier_t *notifier, unsigned is_host);
5404 +
5405 +/** Frees the memory for the specified CC structure allocated from
5406 + * dwc_cc_if_alloc(). */
5407 +extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if);
5408 +
5409 +/** Removes all contexts from the connection context list */
5410 +extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if);
5411 +
5412 +/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.
5413 + * If a CHID already exists, the CK and name are overwritten.  Statistics are
5414 + * not overwritten.
5415 + *
5416 + * @param cc_if The cc_if structure.
5417 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.
5418 + * @param ck A pointer to the 16-byte CK.  This value will be copied.
5419 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.
5420 + * @param name An optional host friendly name as defined in the association model
5421 + * spec.  Must be a UTF16-LE unicode string.  Can be NULL to indicated no name.
5422 + * @param length The length othe unicode string.
5423 + * @return A unique identifier used to refer to this context that is valid for
5424 + * as long as this context is still in the list. */
5425 +extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
5426 +                         uint8_t *cdid, uint8_t *ck, uint8_t *name,
5427 +                         uint8_t length);
5428 +
5429 +/** Changes the CHID, CK, CDID, or Name values of a connection context in the
5430 + * list, preserving any accumulated statistics.  This would typically be called
5431 + * if the host decideds to change the context with a SET_CONNECTION request.
5432 + *
5433 + * @param cc_if The cc_if structure.
5434 + * @param id The identifier of the connection context.
5435 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.  NULL
5436 + * indicates no change.
5437 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.  NULL
5438 + * indicates no change.
5439 + * @param ck A pointer to the 16-byte CK.  This value will be copied.  NULL
5440 + * indicates no change.
5441 + * @param name Host friendly name UTF16-LE.  NULL indicates no change.
5442 + * @param length Length of name. */
5443 +extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id,
5444 +                         uint8_t *chid, uint8_t *cdid, uint8_t *ck,
5445 +                         uint8_t *name, uint8_t length);
5446 +
5447 +/** Remove the specified connection context.
5448 + * @param cc_if The cc_if structure.
5449 + * @param id The identifier of the connection context to remove. */
5450 +extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id);
5451 +
5452 +/** Get a binary block of data for the connection context list and attributes.
5453 + * This data can be used by the OS specific driver to save the connection
5454 + * context list into non-volatile memory.
5455 + *
5456 + * @param cc_if The cc_if structure.
5457 + * @param length Return the length of the data buffer.
5458 + * @return A pointer to the data buffer.  The memory for this buffer should be
5459 + * freed with DWC_FREE() after use. */
5460 +extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if,
5461 +                                    unsigned int *length);
5462 +
5463 +/** Restore the connection context list from the binary data that was previously
5464 + * returned from a call to dwc_cc_data_for_save.  This can be used by the OS specific
5465 + * driver to load a connection context list from non-volatile memory.
5466 + *
5467 + * @param cc_if The cc_if structure.
5468 + * @param data The data bytes as returned from dwc_cc_data_for_save.
5469 + * @param length The length of the data. */
5470 +extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if,
5471 +                                    uint8_t *data, unsigned int length);
5472 +
5473 +/** Find the connection context from the specified CHID.
5474 + *
5475 + * @param cc_if The cc_if structure.
5476 + * @param chid A pointer to the CHID data.
5477 + * @return A non-zero identifier of the connection context if the CHID matches.
5478 + * Otherwise returns 0. */
5479 +extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);
5480 +
5481 +/** Find the connection context from the specified CDID.
5482 + *
5483 + * @param cc_if The cc_if structure.
5484 + * @param cdid A pointer to the CDID data.
5485 + * @return A non-zero identifier of the connection context if the CHID matches.
5486 + * Otherwise returns 0. */
5487 +extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);
5488 +
5489 +/** Retrieve the CK from the specified connection context.
5490 + *
5491 + * @param cc_if The cc_if structure.
5492 + * @param id The identifier of the connection context.
5493 + * @return A pointer to the CK data.  The memory does not need to be freed. */
5494 +extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);
5495 +
5496 +/** Retrieve the CHID from the specified connection context.
5497 + *
5498 + * @param cc_if The cc_if structure.
5499 + * @param id The identifier of the connection context.
5500 + * @return A pointer to the CHID data.  The memory does not need to be freed. */
5501 +extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);
5502 +
5503 +/** Retrieve the CDID from the specified connection context.
5504 + *
5505 + * @param cc_if The cc_if structure.
5506 + * @param id The identifier of the connection context.
5507 + * @return A pointer to the CDID data.  The memory does not need to be freed. */
5508 +extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);
5509 +
5510 +extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);
5511 +
5512 +/** Checks a buffer for non-zero.
5513 + * @param id A pointer to a 16 byte buffer. 
5514 + * @return true if the 16 byte value is non-zero. */
5515 +static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {
5516 +       int i;
5517 +       for (i=0; i<16; i++) {
5518 +               if (id[i]) return 1;
5519 +       }
5520 +       return 0;
5521 +}
5522 +
5523 +/** Checks a buffer for zero.
5524 + * @param id A pointer to a 16 byte buffer. 
5525 + * @return true if the 16 byte value is zero. */
5526 +static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {
5527 +       return !dwc_assoc_is_not_zero_id(id);
5528 +}
5529 +
5530 +/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into
5531 + * buffer. */
5532 +static inline int dwc_print_id_string(char *buffer, uint8_t *id) {
5533 +       char *ptr = buffer;
5534 +       int i;
5535 +       for (i=0; i<16; i++) {
5536 +               ptr += DWC_SPRINTF(ptr, "%02x", id[i]);
5537 +               if (i < 15) {
5538 +                       ptr += DWC_SPRINTF(ptr, " ");
5539 +               }
5540 +       }
5541 +       return ptr - buffer;
5542 +}
5543 +
5544 +/** @} */
5545 +
5546 +#ifdef __cplusplus
5547 +}
5548 +#endif
5549 +
5550 +#endif /* _DWC_CC_H_ */
5551 +
5552 diff --git a/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
5553 new file mode 100644
5554 index 0000000..6dd04b5
5555 --- /dev/null
5556 +++ b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
5557 @@ -0,0 +1,1308 @@
5558 +#include "dwc_os.h"
5559 +#include "dwc_list.h"
5560 +
5561 +#ifdef DWC_CCLIB
5562 +# include "dwc_cc.h"
5563 +#endif
5564 +
5565 +#ifdef DWC_CRYPTOLIB
5566 +# include "dwc_modpow.h"
5567 +# include "dwc_dh.h"
5568 +# include "dwc_crypto.h"
5569 +#endif
5570 +
5571 +#ifdef DWC_NOTIFYLIB
5572 +# include "dwc_notifier.h"
5573 +#endif
5574 +
5575 +/* OS-Level Implementations */
5576 +
5577 +/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */
5578 +
5579 +
5580 +/* MISC */
5581 +
5582 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
5583 +{
5584 +       return memset(dest, byte, size);
5585 +}
5586 +
5587 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
5588 +{
5589 +       return memcpy(dest, src, size);
5590 +}
5591 +
5592 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
5593 +{
5594 +       bcopy(src, dest, size);
5595 +       return dest;
5596 +}
5597 +
5598 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
5599 +{
5600 +       return memcmp(m1, m2, size);
5601 +}
5602 +
5603 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
5604 +{
5605 +       return strncmp(s1, s2, size);
5606 +}
5607 +
5608 +int DWC_STRCMP(void *s1, void *s2)
5609 +{
5610 +       return strcmp(s1, s2);
5611 +}
5612 +
5613 +int DWC_STRLEN(char const *str)
5614 +{
5615 +       return strlen(str);
5616 +}
5617 +
5618 +char *DWC_STRCPY(char *to, char const *from)
5619 +{
5620 +       return strcpy(to, from);
5621 +}
5622 +
5623 +char *DWC_STRDUP(char const *str)
5624 +{
5625 +       int len = DWC_STRLEN(str) + 1;
5626 +       char *new = DWC_ALLOC_ATOMIC(len);
5627 +
5628 +       if (!new) {
5629 +               return NULL;
5630 +       }
5631 +
5632 +       DWC_MEMCPY(new, str, len);
5633 +       return new;
5634 +}
5635 +
5636 +int DWC_ATOI(char *str, int32_t *value)
5637 +{
5638 +       char *end = NULL;
5639 +
5640 +       *value = strtol(str, &end, 0);
5641 +       if (*end == '\0') {
5642 +               return 0;
5643 +       }
5644 +
5645 +       return -1;
5646 +}
5647 +
5648 +int DWC_ATOUI(char *str, uint32_t *value)
5649 +{
5650 +       char *end = NULL;
5651 +
5652 +       *value = strtoul(str, &end, 0);
5653 +       if (*end == '\0') {
5654 +               return 0;
5655 +       }
5656 +
5657 +       return -1;
5658 +}
5659 +
5660 +
5661 +#ifdef DWC_UTFLIB
5662 +/* From usbstring.c */
5663 +
5664 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
5665 +{
5666 +       int     count = 0;
5667 +       u8      c;
5668 +       u16     uchar;
5669 +
5670 +       /* this insists on correct encodings, though not minimal ones.
5671 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
5672 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
5673 +        */
5674 +       while (len != 0 && (c = (u8) *s++) != 0) {
5675 +               if (unlikely(c & 0x80)) {
5676 +                       // 2-byte sequence:
5677 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
5678 +                       if ((c & 0xe0) == 0xc0) {
5679 +                               uchar = (c & 0x1f) << 6;
5680 +
5681 +                               c = (u8) *s++;
5682 +                               if ((c & 0xc0) != 0xc0)
5683 +                                       goto fail;
5684 +                               c &= 0x3f;
5685 +                               uchar |= c;
5686 +
5687 +                       // 3-byte sequence (most CJKV characters):
5688 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
5689 +                       } else if ((c & 0xf0) == 0xe0) {
5690 +                               uchar = (c & 0x0f) << 12;
5691 +
5692 +                               c = (u8) *s++;
5693 +                               if ((c & 0xc0) != 0xc0)
5694 +                                       goto fail;
5695 +                               c &= 0x3f;
5696 +                               uchar |= c << 6;
5697 +
5698 +                               c = (u8) *s++;
5699 +                               if ((c & 0xc0) != 0xc0)
5700 +                                       goto fail;
5701 +                               c &= 0x3f;
5702 +                               uchar |= c;
5703 +
5704 +                               /* no bogus surrogates */
5705 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
5706 +                                       goto fail;
5707 +
5708 +                       // 4-byte sequence (surrogate pairs, currently rare):
5709 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
5710 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
5711 +                       // (uuuuu = wwww + 1)
5712 +                       // FIXME accept the surrogate code points (only)
5713 +                       } else
5714 +                               goto fail;
5715 +               } else
5716 +                       uchar = c;
5717 +               put_unaligned (cpu_to_le16 (uchar), cp++);
5718 +               count++;
5719 +               len--;
5720 +       }
5721 +       return count;
5722 +fail:
5723 +       return -1;
5724 +}
5725 +
5726 +#endif /* DWC_UTFLIB */
5727 +
5728 +
5729 +/* dwc_debug.h */
5730 +
5731 +dwc_bool_t DWC_IN_IRQ(void)
5732 +{
5733 +//     return in_irq();
5734 +       return 0;
5735 +}
5736 +
5737 +dwc_bool_t DWC_IN_BH(void)
5738 +{
5739 +//     return in_softirq();
5740 +       return 0;
5741 +}
5742 +
5743 +void DWC_VPRINTF(char *format, va_list args)
5744 +{
5745 +       vprintf(format, args);
5746 +}
5747 +
5748 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
5749 +{
5750 +       return vsnprintf(str, size, format, args);
5751 +}
5752 +
5753 +void DWC_PRINTF(char *format, ...)
5754 +{
5755 +       va_list args;
5756 +
5757 +       va_start(args, format);
5758 +       DWC_VPRINTF(format, args);
5759 +       va_end(args);
5760 +}
5761 +
5762 +int DWC_SPRINTF(char *buffer, char *format, ...)
5763 +{
5764 +       int retval;
5765 +       va_list args;
5766 +
5767 +       va_start(args, format);
5768 +       retval = vsprintf(buffer, format, args);
5769 +       va_end(args);
5770 +       return retval;
5771 +}
5772 +
5773 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
5774 +{
5775 +       int retval;
5776 +       va_list args;
5777 +
5778 +       va_start(args, format);
5779 +       retval = vsnprintf(buffer, size, format, args);
5780 +       va_end(args);
5781 +       return retval;
5782 +}
5783 +
5784 +void __DWC_WARN(char *format, ...)
5785 +{
5786 +       va_list args;
5787 +
5788 +       va_start(args, format);
5789 +       DWC_VPRINTF(format, args);
5790 +       va_end(args);
5791 +}
5792 +
5793 +void __DWC_ERROR(char *format, ...)
5794 +{
5795 +       va_list args;
5796 +
5797 +       va_start(args, format);
5798 +       DWC_VPRINTF(format, args);
5799 +       va_end(args);
5800 +}
5801 +
5802 +void DWC_EXCEPTION(char *format, ...)
5803 +{
5804 +       va_list args;
5805 +
5806 +       va_start(args, format);
5807 +       DWC_VPRINTF(format, args);
5808 +       va_end(args);
5809 +//     BUG_ON(1);      ???
5810 +}
5811 +
5812 +#ifdef DEBUG
5813 +void __DWC_DEBUG(char *format, ...)
5814 +{
5815 +       va_list args;
5816 +
5817 +       va_start(args, format);
5818 +       DWC_VPRINTF(format, args);
5819 +       va_end(args);
5820 +}
5821 +#endif
5822 +
5823 +
5824 +/* dwc_mem.h */
5825 +
5826 +#if 0
5827 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
5828 +                               uint32_t align,
5829 +                               uint32_t alloc)
5830 +{
5831 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
5832 +                                               size, align, alloc);
5833 +       return (dwc_pool_t *)pool;
5834 +}
5835 +
5836 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
5837 +{
5838 +       dma_pool_destroy((struct dma_pool *)pool);
5839 +}
5840 +
5841 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5842 +{
5843 +//     return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
5844 +       return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
5845 +}
5846 +
5847 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5848 +{
5849 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
5850 +       memset(..);
5851 +}
5852 +
5853 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
5854 +{
5855 +       dma_pool_free(pool, vaddr, daddr);
5856 +}
5857 +#endif
5858 +
5859 +static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
5860 +{
5861 +       if (error)
5862 +               return;
5863 +       *(bus_addr_t *)arg = segs[0].ds_addr;
5864 +}
5865 +
5866 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
5867 +{
5868 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5869 +       int error;
5870 +
5871 +       error = bus_dma_tag_create(
5872 +#if __FreeBSD_version >= 700000
5873 +                       bus_get_dma_tag(dma->dev),      /* parent */
5874 +#else
5875 +                       NULL,                           /* parent */
5876 +#endif
5877 +                       4, 0,                           /* alignment, bounds */
5878 +                       BUS_SPACE_MAXADDR_32BIT,        /* lowaddr */
5879 +                       BUS_SPACE_MAXADDR,              /* highaddr */
5880 +                       NULL, NULL,                     /* filter, filterarg */
5881 +                       size,                           /* maxsize */
5882 +                       1,                              /* nsegments */
5883 +                       size,                           /* maxsegsize */
5884 +                       0,                              /* flags */
5885 +                       NULL,                           /* lockfunc */
5886 +                       NULL,                           /* lockarg */
5887 +                       &dma->dma_tag);
5888 +       if (error) {
5889 +               device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n",
5890 +                             __func__, error);
5891 +               goto fail_0;
5892 +       }
5893 +
5894 +       error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr,
5895 +                                BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
5896 +       if (error) {
5897 +               device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n",
5898 +                             __func__, (uintmax_t)size, error);
5899 +               goto fail_1;
5900 +       }
5901 +
5902 +       dma->dma_paddr = 0;
5903 +       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size,
5904 +                               dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT);
5905 +       if (error || dma->dma_paddr == 0) {
5906 +               device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n",
5907 +                             __func__, error);
5908 +               goto fail_2;
5909 +       }
5910 +
5911 +       *dma_addr = dma->dma_paddr;
5912 +       return dma->dma_vaddr;
5913 +
5914 +fail_2:
5915 +       bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5916 +fail_1:
5917 +       bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5918 +       bus_dma_tag_destroy(dma->dma_tag);
5919 +fail_0:
5920 +       dma->dma_map = NULL;
5921 +       dma->dma_tag = NULL;
5922 +
5923 +       return NULL;
5924 +}
5925 +
5926 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
5927 +{
5928 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5929 +
5930 +       if (dma->dma_tag == NULL)
5931 +               return;
5932 +       if (dma->dma_map != NULL) {
5933 +               bus_dmamap_sync(dma->dma_tag, dma->dma_map,
5934 +                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
5935 +               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5936 +               bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5937 +               dma->dma_map = NULL;
5938 +       }
5939 +
5940 +       bus_dma_tag_destroy(dma->dma_tag);
5941 +       dma->dma_tag = NULL;
5942 +}
5943 +
5944 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
5945 +{
5946 +       return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
5947 +}
5948 +
5949 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
5950 +{
5951 +       return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
5952 +}
5953 +
5954 +void __DWC_FREE(void *mem_ctx, void *addr)
5955 +{
5956 +       free(addr, M_DEVBUF);
5957 +}
5958 +
5959 +
5960 +#ifdef DWC_CRYPTOLIB
5961 +/* dwc_crypto.h */
5962 +
5963 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
5964 +{
5965 +       get_random_bytes(buffer, length);
5966 +}
5967 +
5968 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
5969 +{
5970 +       struct crypto_blkcipher *tfm;
5971 +       struct blkcipher_desc desc;
5972 +       struct scatterlist sgd;
5973 +       struct scatterlist sgs;
5974 +
5975 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
5976 +       if (tfm == NULL) {
5977 +               printk("failed to load transform for aes CBC\n");
5978 +               return -1;
5979 +       }
5980 +
5981 +       crypto_blkcipher_setkey(tfm, key, keylen);
5982 +       crypto_blkcipher_set_iv(tfm, iv, 16);
5983 +
5984 +       sg_init_one(&sgd, out, messagelen);
5985 +       sg_init_one(&sgs, message, messagelen);
5986 +
5987 +       desc.tfm = tfm;
5988 +       desc.flags = 0;
5989 +
5990 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
5991 +               crypto_free_blkcipher(tfm);
5992 +               DWC_ERROR("AES CBC encryption failed");
5993 +               return -1;
5994 +       }
5995 +
5996 +       crypto_free_blkcipher(tfm);
5997 +       return 0;
5998 +}
5999 +
6000 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
6001 +{
6002 +       struct crypto_hash *tfm;
6003 +       struct hash_desc desc;
6004 +       struct scatterlist sg;
6005 +
6006 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
6007 +       if (IS_ERR(tfm)) {
6008 +               DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
6009 +               return 0;
6010 +       }
6011 +       desc.tfm = tfm;
6012 +       desc.flags = 0;
6013 +
6014 +       sg_init_one(&sg, message, len);
6015 +       crypto_hash_digest(&desc, &sg, len, out);
6016 +       crypto_free_hash(tfm);
6017 +
6018 +       return 1;
6019 +}
6020 +
6021 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
6022 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
6023 +{
6024 +       struct crypto_hash *tfm;
6025 +       struct hash_desc desc;
6026 +       struct scatterlist sg;
6027 +
6028 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
6029 +       if (IS_ERR(tfm)) {
6030 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
6031 +               return 0;
6032 +       }
6033 +       desc.tfm = tfm;
6034 +       desc.flags = 0;
6035 +
6036 +       sg_init_one(&sg, message, messagelen);
6037 +       crypto_hash_setkey(tfm, key, keylen);
6038 +       crypto_hash_digest(&desc, &sg, messagelen, out);
6039 +       crypto_free_hash(tfm);
6040 +
6041 +       return 1;
6042 +}
6043 +
6044 +#endif /* DWC_CRYPTOLIB */
6045 +
6046 +
6047 +/* Byte Ordering Conversions */
6048 +
6049 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
6050 +{
6051 +#ifdef __LITTLE_ENDIAN
6052 +       return *p;
6053 +#else
6054 +       uint8_t *u_p = (uint8_t *)p;
6055 +
6056 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6057 +#endif
6058 +}
6059 +
6060 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
6061 +{
6062 +#ifdef __BIG_ENDIAN
6063 +       return *p;
6064 +#else
6065 +       uint8_t *u_p = (uint8_t *)p;
6066 +
6067 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6068 +#endif
6069 +}
6070 +
6071 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
6072 +{
6073 +#ifdef __LITTLE_ENDIAN
6074 +       return *p;
6075 +#else
6076 +       uint8_t *u_p = (uint8_t *)p;
6077 +
6078 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6079 +#endif
6080 +}
6081 +
6082 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
6083 +{
6084 +#ifdef __BIG_ENDIAN
6085 +       return *p;
6086 +#else
6087 +       uint8_t *u_p = (uint8_t *)p;
6088 +
6089 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6090 +#endif
6091 +}
6092 +
6093 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
6094 +{
6095 +#ifdef __LITTLE_ENDIAN
6096 +       return *p;
6097 +#else
6098 +       uint8_t *u_p = (uint8_t *)p;
6099 +       return (u_p[1] | (u_p[0] << 8));
6100 +#endif
6101 +}
6102 +
6103 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
6104 +{
6105 +#ifdef __BIG_ENDIAN
6106 +       return *p;
6107 +#else
6108 +       uint8_t *u_p = (uint8_t *)p;
6109 +       return (u_p[1] | (u_p[0] << 8));
6110 +#endif
6111 +}
6112 +
6113 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
6114 +{
6115 +#ifdef __LITTLE_ENDIAN
6116 +       return *p;
6117 +#else
6118 +       uint8_t *u_p = (uint8_t *)p;
6119 +       return (u_p[1] | (u_p[0] << 8));
6120 +#endif
6121 +}
6122 +
6123 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
6124 +{
6125 +#ifdef __BIG_ENDIAN
6126 +       return *p;
6127 +#else
6128 +       uint8_t *u_p = (uint8_t *)p;
6129 +       return (u_p[1] | (u_p[0] << 8));
6130 +#endif
6131 +}
6132 +
6133 +
6134 +/* Registers */
6135 +
6136 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
6137 +{
6138 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6139 +       bus_size_t ior = (bus_size_t)reg;
6140 +
6141 +       return bus_space_read_4(io->iot, io->ioh, ior);
6142 +}
6143 +
6144 +#if 0
6145 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
6146 +{
6147 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6148 +       bus_size_t ior = (bus_size_t)reg;
6149 +
6150 +       return bus_space_read_8(io->iot, io->ioh, ior);
6151 +}
6152 +#endif
6153 +
6154 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
6155 +{
6156 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6157 +       bus_size_t ior = (bus_size_t)reg;
6158 +
6159 +       bus_space_write_4(io->iot, io->ioh, ior, value);
6160 +}
6161 +
6162 +#if 0
6163 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
6164 +{
6165 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6166 +       bus_size_t ior = (bus_size_t)reg;
6167 +
6168 +       bus_space_write_8(io->iot, io->ioh, ior, value);
6169 +}
6170 +#endif
6171 +
6172 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
6173 +                     uint32_t set_mask)
6174 +{
6175 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6176 +       bus_size_t ior = (bus_size_t)reg;
6177 +
6178 +       bus_space_write_4(io->iot, io->ioh, ior,
6179 +                         (bus_space_read_4(io->iot, io->ioh, ior) &
6180 +                          ~clear_mask) | set_mask);
6181 +}
6182 +
6183 +#if 0
6184 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
6185 +                     uint64_t set_mask)
6186 +{
6187 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6188 +       bus_size_t ior = (bus_size_t)reg;
6189 +
6190 +       bus_space_write_8(io->iot, io->ioh, ior,
6191 +                         (bus_space_read_8(io->iot, io->ioh, ior) &
6192 +                          ~clear_mask) | set_mask);
6193 +}
6194 +#endif
6195 +
6196 +
6197 +/* Locking */
6198 +
6199 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
6200 +{
6201 +       struct mtx *sl = DWC_ALLOC(sizeof(*sl));
6202 +
6203 +       if (!sl) {
6204 +               DWC_ERROR("Cannot allocate memory for spinlock");
6205 +               return NULL;
6206 +       }
6207 +
6208 +       mtx_init(sl, "dw3spn", NULL, MTX_SPIN);
6209 +       return (dwc_spinlock_t *)sl;
6210 +}
6211 +
6212 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
6213 +{
6214 +       struct mtx *sl = (struct mtx *)lock;
6215 +
6216 +       mtx_destroy(sl);
6217 +       DWC_FREE(sl);
6218 +}
6219 +
6220 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
6221 +{
6222 +       mtx_lock_spin((struct mtx *)lock);      // ???
6223 +}
6224 +
6225 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
6226 +{
6227 +       mtx_unlock_spin((struct mtx *)lock);    // ???
6228 +}
6229 +
6230 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
6231 +{
6232 +       mtx_lock_spin((struct mtx *)lock);
6233 +}
6234 +
6235 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
6236 +{
6237 +       mtx_unlock_spin((struct mtx *)lock);
6238 +}
6239 +
6240 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
6241 +{
6242 +       struct mtx *m;
6243 +       dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx));
6244 +
6245 +       if (!mutex) {
6246 +               DWC_ERROR("Cannot allocate memory for mutex");
6247 +               return NULL;
6248 +       }
6249 +
6250 +       m = (struct mtx *)mutex;
6251 +       mtx_init(m, "dw3mtx", NULL, MTX_DEF);
6252 +       return mutex;
6253 +}
6254 +
6255 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
6256 +#else
6257 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
6258 +{
6259 +       mtx_destroy((struct mtx *)mutex);
6260 +       DWC_FREE(mutex);
6261 +}
6262 +#endif
6263 +
6264 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
6265 +{
6266 +       struct mtx *m = (struct mtx *)mutex;
6267 +
6268 +       mtx_lock(m);
6269 +}
6270 +
6271 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
6272 +{
6273 +       struct mtx *m = (struct mtx *)mutex;
6274 +
6275 +       return mtx_trylock(m);
6276 +}
6277 +
6278 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
6279 +{
6280 +       struct mtx *m = (struct mtx *)mutex;
6281 +
6282 +       mtx_unlock(m);
6283 +}
6284 +
6285 +
6286 +/* Timing */
6287 +
6288 +void DWC_UDELAY(uint32_t usecs)
6289 +{
6290 +       DELAY(usecs);
6291 +}
6292 +
6293 +void DWC_MDELAY(uint32_t msecs)
6294 +{
6295 +       do {
6296 +               DELAY(1000);
6297 +       } while (--msecs);
6298 +}
6299 +
6300 +void DWC_MSLEEP(uint32_t msecs)
6301 +{
6302 +       struct timeval tv;
6303 +
6304 +       tv.tv_sec = msecs / 1000;
6305 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6306 +       pause("dw3slp", tvtohz(&tv));
6307 +}
6308 +
6309 +uint32_t DWC_TIME(void)
6310 +{
6311 +       struct timeval tv;
6312 +
6313 +       microuptime(&tv);       // or getmicrouptime? (less precise, but faster)
6314 +       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
6315 +}
6316 +
6317 +
6318 +/* Timers */
6319 +
6320 +struct dwc_timer {
6321 +       struct callout t;
6322 +       char *name;
6323 +       dwc_spinlock_t *lock;
6324 +       dwc_timer_callback_t cb;
6325 +       void *data;
6326 +};
6327 +
6328 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
6329 +{
6330 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
6331 +
6332 +       if (!t) {
6333 +               DWC_ERROR("Cannot allocate memory for timer");
6334 +               return NULL;
6335 +       }
6336 +
6337 +       callout_init(&t->t, 1);
6338 +
6339 +       t->name = DWC_STRDUP(name);
6340 +       if (!t->name) {
6341 +               DWC_ERROR("Cannot allocate memory for timer->name");
6342 +               goto no_name;
6343 +       }
6344 +
6345 +       t->lock = DWC_SPINLOCK_ALLOC();
6346 +       if (!t->lock) {
6347 +               DWC_ERROR("Cannot allocate memory for lock");
6348 +               goto no_lock;
6349 +       }
6350 +
6351 +       t->cb = cb;
6352 +       t->data = data;
6353 +
6354 +       return t;
6355 +
6356 + no_lock:
6357 +       DWC_FREE(t->name);
6358 + no_name:
6359 +       DWC_FREE(t);
6360 +
6361 +       return NULL;
6362 +}
6363 +
6364 +void DWC_TIMER_FREE(dwc_timer_t *timer)
6365 +{
6366 +       callout_stop(&timer->t);
6367 +       DWC_SPINLOCK_FREE(timer->lock);
6368 +       DWC_FREE(timer->name);
6369 +       DWC_FREE(timer);
6370 +}
6371 +
6372 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
6373 +{
6374 +       struct timeval tv;
6375 +
6376 +       tv.tv_sec = time / 1000;
6377 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6378 +       callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
6379 +}
6380 +
6381 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
6382 +{
6383 +       callout_stop(&timer->t);
6384 +}
6385 +
6386 +
6387 +/* Wait Queues */
6388 +
6389 +struct dwc_waitq {
6390 +       struct mtx lock;
6391 +       int abort;
6392 +};
6393 +
6394 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
6395 +{
6396 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
6397 +
6398 +       if (!wq) {
6399 +               DWC_ERROR("Cannot allocate memory for waitqueue");
6400 +               return NULL;
6401 +       }
6402 +
6403 +       mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF);
6404 +       wq->abort = 0;
6405 +
6406 +       return wq;
6407 +}
6408 +
6409 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
6410 +{
6411 +       mtx_destroy(&wq->lock);
6412 +       DWC_FREE(wq);
6413 +}
6414 +
6415 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
6416 +{
6417 +//     intrmask_t ipl;
6418 +       int result = 0;
6419 +
6420 +       mtx_lock(&wq->lock);
6421 +//     ipl = splbio();
6422 +
6423 +       /* Skip the sleep if already aborted or triggered */
6424 +       if (!wq->abort && !cond(data)) {
6425 +//             splx(ipl);
6426 +               result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout
6427 +//             ipl = splbio();
6428 +       }
6429 +
6430 +       if (result == ERESTART) {       // signaled - restart
6431 +               result = -DWC_E_RESTART;
6432 +
6433 +       } else if (result == EINTR) {   // signaled - interrupt
6434 +               result = -DWC_E_ABORT;
6435 +
6436 +       } else if (wq->abort) {
6437 +               result = -DWC_E_ABORT;
6438 +
6439 +       } else {
6440 +               result = 0;
6441 +       }
6442 +
6443 +       wq->abort = 0;
6444 +//     splx(ipl);
6445 +       mtx_unlock(&wq->lock);
6446 +       return result;
6447 +}
6448 +
6449 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
6450 +                              void *data, int32_t msecs)
6451 +{
6452 +       struct timeval tv, tv1, tv2;
6453 +//     intrmask_t ipl;
6454 +       int result = 0;
6455 +
6456 +       tv.tv_sec = msecs / 1000;
6457 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6458 +
6459 +       mtx_lock(&wq->lock);
6460 +//     ipl = splbio();
6461 +
6462 +       /* Skip the sleep if already aborted or triggered */
6463 +       if (!wq->abort && !cond(data)) {
6464 +//             splx(ipl);
6465 +               getmicrouptime(&tv1);
6466 +               result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv));
6467 +               getmicrouptime(&tv2);
6468 +//             ipl = splbio();
6469 +       }
6470 +
6471 +       if (result == 0) {                      // awoken
6472 +               if (wq->abort) {
6473 +                       result = -DWC_E_ABORT;
6474 +               } else {
6475 +                       tv2.tv_usec -= tv1.tv_usec;
6476 +                       if (tv2.tv_usec < 0) {
6477 +                               tv2.tv_usec += 1000000;
6478 +                               tv2.tv_sec--;
6479 +                       }
6480 +
6481 +                       tv2.tv_sec -= tv1.tv_sec;
6482 +                       result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
6483 +                       result = msecs - result;
6484 +                       if (result <= 0)
6485 +                               result = 1;
6486 +               }
6487 +       } else if (result == ERESTART) {        // signaled - restart
6488 +               result = -DWC_E_RESTART;
6489 +
6490 +       } else if (result == EINTR) {           // signaled - interrupt
6491 +               result = -DWC_E_ABORT;
6492 +
6493 +       } else {                                // timed out
6494 +               result = -DWC_E_TIMEOUT;
6495 +       }
6496 +
6497 +       wq->abort = 0;
6498 +//     splx(ipl);
6499 +       mtx_unlock(&wq->lock);
6500 +       return result;
6501 +}
6502 +
6503 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
6504 +{
6505 +       wakeup(wq);
6506 +}
6507 +
6508 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
6509 +{
6510 +//     intrmask_t ipl;
6511 +
6512 +       mtx_lock(&wq->lock);
6513 +//     ipl = splbio();
6514 +       wq->abort = 1;
6515 +       wakeup(wq);
6516 +//     splx(ipl);
6517 +       mtx_unlock(&wq->lock);
6518 +}
6519 +
6520 +
6521 +/* Threading */
6522 +
6523 +struct dwc_thread {
6524 +       struct proc *proc;
6525 +       int abort;
6526 +};
6527 +
6528 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
6529 +{
6530 +       int retval;
6531 +       dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
6532 +
6533 +       if (!thread) {
6534 +               return NULL;
6535 +       }
6536 +
6537 +       thread->abort = 0;
6538 +       retval = kthread_create((void (*)(void *))func, data, &thread->proc,
6539 +                               RFPROC | RFNOWAIT, 0, "%s", name);
6540 +       if (retval) {
6541 +               DWC_FREE(thread);
6542 +               return NULL;
6543 +       }
6544 +
6545 +       return thread;
6546 +}
6547 +
6548 +int DWC_THREAD_STOP(dwc_thread_t *thread)
6549 +{
6550 +       int retval;
6551 +
6552 +       thread->abort = 1;
6553 +       retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
6554 +
6555 +       if (retval == 0) {
6556 +               /* DWC_THREAD_EXIT() will free the thread struct */
6557 +               return 0;
6558 +       }
6559 +
6560 +       /* NOTE: We leak the thread struct if thread doesn't die */
6561 +
6562 +       if (retval == EWOULDBLOCK) {
6563 +               return -DWC_E_TIMEOUT;
6564 +       }
6565 +
6566 +       return -DWC_E_UNKNOWN;
6567 +}
6568 +
6569 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
6570 +{
6571 +       return thread->abort;
6572 +}
6573 +
6574 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
6575 +{
6576 +       wakeup(&thread->abort);
6577 +       DWC_FREE(thread);
6578 +       kthread_exit(0);
6579 +}
6580 +
6581 +
6582 +/* tasklets
6583 + - Runs in interrupt context (cannot sleep)
6584 + - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ]
6585 + - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ]
6586 + */
6587 +struct dwc_tasklet {
6588 +       struct task t;
6589 +       dwc_tasklet_callback_t cb;
6590 +       void *data;
6591 +};
6592 +
6593 +static void tasklet_callback(void *data, int pending)  // what to do with pending ???
6594 +{
6595 +       dwc_tasklet_t *task = (dwc_tasklet_t *)data;
6596 +
6597 +       task->cb(task->data);
6598 +}
6599 +
6600 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
6601 +{
6602 +       dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
6603 +
6604 +       if (task) {
6605 +               task->cb = cb;
6606 +               task->data = data;
6607 +               TASK_INIT(&task->t, 0, tasklet_callback, task);
6608 +       } else {
6609 +               DWC_ERROR("Cannot allocate memory for tasklet");
6610 +       }
6611 +
6612 +       return task;
6613 +}
6614 +
6615 +void DWC_TASK_FREE(dwc_tasklet_t *task)
6616 +{
6617 +       taskqueue_drain(taskqueue_fast, &task->t);      // ???
6618 +       DWC_FREE(task);
6619 +}
6620 +
6621 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
6622 +{
6623 +       /* Uses predefined system queue */
6624 +       taskqueue_enqueue_fast(taskqueue_fast, &task->t);
6625 +}
6626 +
6627 +
6628 +/* workqueues
6629 + - Runs in process context (can sleep)
6630 + */
6631 +typedef struct work_container {
6632 +       dwc_work_callback_t cb;
6633 +       void *data;
6634 +       dwc_workq_t *wq;
6635 +       char *name;
6636 +       int hz;
6637 +
6638 +#ifdef DEBUG
6639 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
6640 +#endif
6641 +       struct task task;
6642 +} work_container_t;
6643 +
6644 +#ifdef DEBUG
6645 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
6646 +#endif
6647 +
6648 +struct dwc_workq {
6649 +       struct taskqueue *taskq;
6650 +       dwc_spinlock_t *lock;
6651 +       dwc_waitq_t *waitq;
6652 +       int pending;
6653 +
6654 +#ifdef DEBUG
6655 +       struct work_container_queue entries;
6656 +#endif
6657 +};
6658 +
6659 +static void do_work(void *data, int pending)   // what to do with pending ???
6660 +{
6661 +       work_container_t *container = (work_container_t *)data;
6662 +       dwc_workq_t *wq = container->wq;
6663 +       dwc_irqflags_t flags;
6664 +
6665 +       if (container->hz) {
6666 +               pause("dw3wrk", container->hz);
6667 +       }
6668 +
6669 +       container->cb(container->data);
6670 +       DWC_DEBUG("Work done: %s, container=%p", container->name, container);
6671 +
6672 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6673 +
6674 +#ifdef DEBUG
6675 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
6676 +#endif
6677 +       if (container->name)
6678 +               DWC_FREE(container->name);
6679 +       DWC_FREE(container);
6680 +       wq->pending--;
6681 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6682 +       DWC_WAITQ_TRIGGER(wq->waitq);
6683 +}
6684 +
6685 +static int work_done(void *data)
6686 +{
6687 +       dwc_workq_t *workq = (dwc_workq_t *)data;
6688 +
6689 +       return workq->pending == 0;
6690 +}
6691 +
6692 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
6693 +{
6694 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
6695 +}
6696 +
6697 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
6698 +{
6699 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
6700 +
6701 +       if (!wq) {
6702 +               DWC_ERROR("Cannot allocate memory for workqueue");
6703 +               return NULL;
6704 +       }
6705 +
6706 +       wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq);
6707 +       if (!wq->taskq) {
6708 +               DWC_ERROR("Cannot allocate memory for taskqueue");
6709 +               goto no_taskq;
6710 +       }
6711 +
6712 +       wq->pending = 0;
6713 +
6714 +       wq->lock = DWC_SPINLOCK_ALLOC();
6715 +       if (!wq->lock) {
6716 +               DWC_ERROR("Cannot allocate memory for spinlock");
6717 +               goto no_lock;
6718 +       }
6719 +
6720 +       wq->waitq = DWC_WAITQ_ALLOC();
6721 +       if (!wq->waitq) {
6722 +               DWC_ERROR("Cannot allocate memory for waitqueue");
6723 +               goto no_waitq;
6724 +       }
6725 +
6726 +       taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk");
6727 +
6728 +#ifdef DEBUG
6729 +       DWC_CIRCLEQ_INIT(&wq->entries);
6730 +#endif
6731 +       return wq;
6732 +
6733 + no_waitq:
6734 +       DWC_SPINLOCK_FREE(wq->lock);
6735 + no_lock:
6736 +       taskqueue_free(wq->taskq);
6737 + no_taskq:
6738 +       DWC_FREE(wq);
6739 +
6740 +       return NULL;
6741 +}
6742 +
6743 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
6744 +{
6745 +#ifdef DEBUG
6746 +       dwc_irqflags_t flags;
6747 +
6748 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6749 +
6750 +       if (wq->pending != 0) {
6751 +               struct work_container *container;
6752 +
6753 +               DWC_ERROR("Destroying work queue with pending work");
6754 +
6755 +               DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) {
6756 +                       DWC_ERROR("Work %s still pending", container->name);
6757 +               }
6758 +       }
6759 +
6760 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6761 +#endif
6762 +       DWC_WAITQ_FREE(wq->waitq);
6763 +       DWC_SPINLOCK_FREE(wq->lock);
6764 +       taskqueue_free(wq->taskq);
6765 +       DWC_FREE(wq);
6766 +}
6767 +
6768 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
6769 +                       char *format, ...)
6770 +{
6771 +       dwc_irqflags_t flags;
6772 +       work_container_t *container;
6773 +       static char name[128];
6774 +       va_list args;
6775 +
6776 +       va_start(args, format);
6777 +       DWC_VSNPRINTF(name, 128, format, args);
6778 +       va_end(args);
6779 +
6780 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6781 +       wq->pending++;
6782 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6783 +       DWC_WAITQ_TRIGGER(wq->waitq);
6784 +
6785 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
6786 +       if (!container) {
6787 +               DWC_ERROR("Cannot allocate memory for container");
6788 +               return;
6789 +       }
6790 +
6791 +       container->name = DWC_STRDUP(name);
6792 +       if (!container->name) {
6793 +               DWC_ERROR("Cannot allocate memory for container->name");
6794 +               DWC_FREE(container);
6795 +               return;
6796 +       }
6797 +
6798 +       container->cb = cb;
6799 +       container->data = data;
6800 +       container->wq = wq;
6801 +       container->hz = 0;
6802 +
6803 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6804 +
6805 +       TASK_INIT(&container->task, 0, do_work, container);
6806 +
6807 +#ifdef DEBUG
6808 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6809 +#endif
6810 +       taskqueue_enqueue_fast(wq->taskq, &container->task);
6811 +}
6812 +
6813 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
6814 +                               void *data, uint32_t time, char *format, ...)
6815 +{
6816 +       dwc_irqflags_t flags;
6817 +       work_container_t *container;
6818 +       static char name[128];
6819 +       struct timeval tv;
6820 +       va_list args;
6821 +
6822 +       va_start(args, format);
6823 +       DWC_VSNPRINTF(name, 128, format, args);
6824 +       va_end(args);
6825 +
6826 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6827 +       wq->pending++;
6828 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6829 +       DWC_WAITQ_TRIGGER(wq->waitq);
6830 +
6831 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
6832 +       if (!container) {
6833 +               DWC_ERROR("Cannot allocate memory for container");
6834 +               return;
6835 +       }
6836 +
6837 +       container->name = DWC_STRDUP(name);
6838 +       if (!container->name) {
6839 +               DWC_ERROR("Cannot allocate memory for container->name");
6840 +               DWC_FREE(container);
6841 +               return;
6842 +       }
6843 +
6844 +       container->cb = cb;
6845 +       container->data = data;
6846 +       container->wq = wq;
6847 +
6848 +       tv.tv_sec = time / 1000;
6849 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6850 +       container->hz = tvtohz(&tv);
6851 +
6852 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6853 +
6854 +       TASK_INIT(&container->task, 0, do_work, container);
6855 +
6856 +#ifdef DEBUG
6857 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6858 +#endif
6859 +       taskqueue_enqueue_fast(wq->taskq, &container->task);
6860 +}
6861 +
6862 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
6863 +{
6864 +       return wq->pending;
6865 +}
6866 diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
6867 new file mode 100644
6868 index 0000000..f00a9ff
6869 --- /dev/null
6870 +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
6871 @@ -0,0 +1,1421 @@
6872 +#include <linux/kernel.h>
6873 +#include <linux/init.h>
6874 +#include <linux/module.h>
6875 +#include <linux/kthread.h>
6876 +
6877 +#ifdef DWC_CCLIB
6878 +# include "dwc_cc.h"
6879 +#endif
6880 +
6881 +#ifdef DWC_CRYPTOLIB
6882 +# include "dwc_modpow.h"
6883 +# include "dwc_dh.h"
6884 +# include "dwc_crypto.h"
6885 +#endif
6886 +
6887 +#ifdef DWC_NOTIFYLIB
6888 +# include "dwc_notifier.h"
6889 +#endif
6890 +
6891 +/* OS-Level Implementations */
6892 +
6893 +/* This is the Linux kernel implementation of the DWC platform library. */
6894 +#include <linux/moduleparam.h>
6895 +#include <linux/ctype.h>
6896 +#include <linux/crypto.h>
6897 +#include <linux/delay.h>
6898 +#include <linux/device.h>
6899 +#include <linux/dma-mapping.h>
6900 +#include <linux/cdev.h>
6901 +#include <linux/errno.h>
6902 +#include <linux/interrupt.h>
6903 +#include <linux/jiffies.h>
6904 +#include <linux/list.h>
6905 +#include <linux/pci.h>
6906 +#include <linux/random.h>
6907 +#include <linux/scatterlist.h>
6908 +#include <linux/slab.h>
6909 +#include <linux/stat.h>
6910 +#include <linux/string.h>
6911 +#include <linux/timer.h>
6912 +#include <linux/usb.h>
6913 +
6914 +#include <linux/version.h>
6915 +
6916 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
6917 +# include <linux/usb/gadget.h>
6918 +#else
6919 +# include <linux/usb_gadget.h>
6920 +#endif
6921 +
6922 +#include <asm/io.h>
6923 +#include <asm/page.h>
6924 +#include <asm/uaccess.h>
6925 +#include <asm/unaligned.h>
6926 +
6927 +#include "dwc_os.h"
6928 +#include "dwc_list.h"
6929 +
6930 +
6931 +/* MISC */
6932 +
6933 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
6934 +{
6935 +       return memset(dest, byte, size);
6936 +}
6937 +
6938 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
6939 +{
6940 +       return memcpy(dest, src, size);
6941 +}
6942 +
6943 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
6944 +{
6945 +       return memmove(dest, src, size);
6946 +}
6947 +
6948 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
6949 +{
6950 +       return memcmp(m1, m2, size);
6951 +}
6952 +
6953 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
6954 +{
6955 +       return strncmp(s1, s2, size);
6956 +}
6957 +
6958 +int DWC_STRCMP(void *s1, void *s2)
6959 +{
6960 +       return strcmp(s1, s2);
6961 +}
6962 +
6963 +int DWC_STRLEN(char const *str)
6964 +{
6965 +       return strlen(str);
6966 +}
6967 +
6968 +char *DWC_STRCPY(char *to, char const *from)
6969 +{
6970 +       return strcpy(to, from);
6971 +}
6972 +
6973 +char *DWC_STRDUP(char const *str)
6974 +{
6975 +       int len = DWC_STRLEN(str) + 1;
6976 +       char *new = DWC_ALLOC_ATOMIC(len);
6977 +
6978 +       if (!new) {
6979 +               return NULL;
6980 +       }
6981 +
6982 +       DWC_MEMCPY(new, str, len);
6983 +       return new;
6984 +}
6985 +
6986 +int DWC_ATOI(const char *str, int32_t *value)
6987 +{
6988 +       char *end = NULL;
6989 +
6990 +       *value = simple_strtol(str, &end, 0);
6991 +       if (*end == '\0') {
6992 +               return 0;
6993 +       }
6994 +
6995 +       return -1;
6996 +}
6997 +
6998 +int DWC_ATOUI(const char *str, uint32_t *value)
6999 +{
7000 +       char *end = NULL;
7001 +
7002 +       *value = simple_strtoul(str, &end, 0);
7003 +       if (*end == '\0') {
7004 +               return 0;
7005 +       }
7006 +
7007 +       return -1;
7008 +}
7009 +
7010 +
7011 +#ifdef DWC_UTFLIB
7012 +/* From usbstring.c */
7013 +
7014 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
7015 +{
7016 +       int     count = 0;
7017 +       u8      c;
7018 +       u16     uchar;
7019 +
7020 +       /* this insists on correct encodings, though not minimal ones.
7021 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
7022 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
7023 +        */
7024 +       while (len != 0 && (c = (u8) *s++) != 0) {
7025 +               if (unlikely(c & 0x80)) {
7026 +                       // 2-byte sequence:
7027 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
7028 +                       if ((c & 0xe0) == 0xc0) {
7029 +                               uchar = (c & 0x1f) << 6;
7030 +
7031 +                               c = (u8) *s++;
7032 +                               if ((c & 0xc0) != 0xc0)
7033 +                                       goto fail;
7034 +                               c &= 0x3f;
7035 +                               uchar |= c;
7036 +
7037 +                       // 3-byte sequence (most CJKV characters):
7038 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
7039 +                       } else if ((c & 0xf0) == 0xe0) {
7040 +                               uchar = (c & 0x0f) << 12;
7041 +
7042 +                               c = (u8) *s++;
7043 +                               if ((c & 0xc0) != 0xc0)
7044 +                                       goto fail;
7045 +                               c &= 0x3f;
7046 +                               uchar |= c << 6;
7047 +
7048 +                               c = (u8) *s++;
7049 +                               if ((c & 0xc0) != 0xc0)
7050 +                                       goto fail;
7051 +                               c &= 0x3f;
7052 +                               uchar |= c;
7053 +
7054 +                               /* no bogus surrogates */
7055 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
7056 +                                       goto fail;
7057 +
7058 +                       // 4-byte sequence (surrogate pairs, currently rare):
7059 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
7060 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
7061 +                       // (uuuuu = wwww + 1)
7062 +                       // FIXME accept the surrogate code points (only)
7063 +                       } else
7064 +                               goto fail;
7065 +               } else
7066 +                       uchar = c;
7067 +               put_unaligned (cpu_to_le16 (uchar), cp++);
7068 +               count++;
7069 +               len--;
7070 +       }
7071 +       return count;
7072 +fail:
7073 +       return -1;
7074 +}
7075 +#endif /* DWC_UTFLIB */
7076 +
7077 +
7078 +/* dwc_debug.h */
7079 +
7080 +dwc_bool_t DWC_IN_IRQ(void)
7081 +{
7082 +       return in_irq();
7083 +}
7084 +
7085 +dwc_bool_t DWC_IN_BH(void)
7086 +{
7087 +       return in_softirq();
7088 +}
7089 +
7090 +void DWC_VPRINTF(char *format, va_list args)
7091 +{
7092 +       vprintk(format, args);
7093 +}
7094 +
7095 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
7096 +{
7097 +       return vsnprintf(str, size, format, args);
7098 +}
7099 +
7100 +void DWC_PRINTF(char *format, ...)
7101 +{
7102 +       va_list args;
7103 +
7104 +       va_start(args, format);
7105 +       DWC_VPRINTF(format, args);
7106 +       va_end(args);
7107 +}
7108 +
7109 +int DWC_SPRINTF(char *buffer, char *format, ...)
7110 +{
7111 +       int retval;
7112 +       va_list args;
7113 +
7114 +       va_start(args, format);
7115 +       retval = vsprintf(buffer, format, args);
7116 +       va_end(args);
7117 +       return retval;
7118 +}
7119 +
7120 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
7121 +{
7122 +       int retval;
7123 +       va_list args;
7124 +
7125 +       va_start(args, format);
7126 +       retval = vsnprintf(buffer, size, format, args);
7127 +       va_end(args);
7128 +       return retval;
7129 +}
7130 +
7131 +void __DWC_WARN(char *format, ...)
7132 +{
7133 +       va_list args;
7134 +
7135 +       va_start(args, format);
7136 +       DWC_PRINTF(KERN_WARNING);
7137 +       DWC_VPRINTF(format, args);
7138 +       va_end(args);
7139 +}
7140 +
7141 +void __DWC_ERROR(char *format, ...)
7142 +{
7143 +       va_list args;
7144 +
7145 +       va_start(args, format);
7146 +       DWC_PRINTF(KERN_ERR);
7147 +       DWC_VPRINTF(format, args);
7148 +       va_end(args);
7149 +}
7150 +
7151 +void DWC_EXCEPTION(char *format, ...)
7152 +{
7153 +       va_list args;
7154 +
7155 +       va_start(args, format);
7156 +       DWC_PRINTF(KERN_ERR);
7157 +       DWC_VPRINTF(format, args);
7158 +       va_end(args);
7159 +       BUG_ON(1);
7160 +}
7161 +
7162 +#ifdef DEBUG
7163 +void __DWC_DEBUG(char *format, ...)
7164 +{
7165 +       va_list args;
7166 +
7167 +       va_start(args, format);
7168 +       DWC_PRINTF(KERN_DEBUG);
7169 +       DWC_VPRINTF(format, args);
7170 +       va_end(args);
7171 +}
7172 +#endif
7173 +
7174 +
7175 +/* dwc_mem.h */
7176 +
7177 +#if 0
7178 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
7179 +                               uint32_t align,
7180 +                               uint32_t alloc)
7181 +{
7182 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
7183 +                                               size, align, alloc);
7184 +       return (dwc_pool_t *)pool;
7185 +}
7186 +
7187 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
7188 +{
7189 +       dma_pool_destroy((struct dma_pool *)pool);
7190 +}
7191 +
7192 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
7193 +{
7194 +       return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
7195 +}
7196 +
7197 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
7198 +{
7199 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
7200 +       memset(..);
7201 +}
7202 +
7203 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
7204 +{
7205 +       dma_pool_free(pool, vaddr, daddr);
7206 +}
7207 +#endif
7208 +
7209 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
7210 +{
7211 +#ifdef xxCOSIM /* Only works for 32-bit cosim */
7212 +       void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL);
7213 +#else
7214 +       void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32);
7215 +#endif
7216 +       if (!buf) {
7217 +               return NULL;
7218 +       }
7219 +
7220 +       memset(buf, 0, (size_t)size);
7221 +       return buf;
7222 +}
7223 +
7224 +void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
7225 +{
7226 +       void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);
7227 +       if (!buf) {
7228 +               return NULL;
7229 +       }
7230 +       memset(buf, 0, (size_t)size);
7231 +       return buf;
7232 +}
7233 +
7234 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
7235 +{
7236 +       dma_free_coherent(dma_ctx, size, virt_addr, dma_addr);
7237 +}
7238 +
7239 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
7240 +{
7241 +       return kzalloc(size, GFP_KERNEL);
7242 +}
7243 +
7244 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
7245 +{
7246 +       return kzalloc(size, GFP_ATOMIC);
7247 +}
7248 +
7249 +void __DWC_FREE(void *mem_ctx, void *addr)
7250 +{
7251 +       kfree(addr);
7252 +}
7253 +
7254 +
7255 +#ifdef DWC_CRYPTOLIB
7256 +/* dwc_crypto.h */
7257 +
7258 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
7259 +{
7260 +       get_random_bytes(buffer, length);
7261 +}
7262 +
7263 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
7264 +{
7265 +       struct crypto_blkcipher *tfm;
7266 +       struct blkcipher_desc desc;
7267 +       struct scatterlist sgd;
7268 +       struct scatterlist sgs;
7269 +
7270 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
7271 +       if (tfm == NULL) {
7272 +               printk("failed to load transform for aes CBC\n");
7273 +               return -1;
7274 +       }
7275 +
7276 +       crypto_blkcipher_setkey(tfm, key, keylen);
7277 +       crypto_blkcipher_set_iv(tfm, iv, 16);
7278 +
7279 +       sg_init_one(&sgd, out, messagelen);
7280 +       sg_init_one(&sgs, message, messagelen);
7281 +
7282 +       desc.tfm = tfm;
7283 +       desc.flags = 0;
7284 +
7285 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
7286 +               crypto_free_blkcipher(tfm);
7287 +               DWC_ERROR("AES CBC encryption failed");
7288 +               return -1;
7289 +       }
7290 +
7291 +       crypto_free_blkcipher(tfm);
7292 +       return 0;
7293 +}
7294 +
7295 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
7296 +{
7297 +       struct crypto_hash *tfm;
7298 +       struct hash_desc desc;
7299 +       struct scatterlist sg;
7300 +
7301 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
7302 +       if (IS_ERR(tfm)) {
7303 +               DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));
7304 +               return 0;
7305 +       }
7306 +       desc.tfm = tfm;
7307 +       desc.flags = 0;
7308 +
7309 +       sg_init_one(&sg, message, len);
7310 +       crypto_hash_digest(&desc, &sg, len, out);
7311 +       crypto_free_hash(tfm);
7312 +
7313 +       return 1;
7314 +}
7315 +
7316 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
7317 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
7318 +{
7319 +       struct crypto_hash *tfm;
7320 +       struct hash_desc desc;
7321 +       struct scatterlist sg;
7322 +
7323 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
7324 +       if (IS_ERR(tfm)) {
7325 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));
7326 +               return 0;
7327 +       }
7328 +       desc.tfm = tfm;
7329 +       desc.flags = 0;
7330 +
7331 +       sg_init_one(&sg, message, messagelen);
7332 +       crypto_hash_setkey(tfm, key, keylen);
7333 +       crypto_hash_digest(&desc, &sg, messagelen, out);
7334 +       crypto_free_hash(tfm);
7335 +
7336 +       return 1;
7337 +}
7338 +#endif /* DWC_CRYPTOLIB */
7339 +
7340 +
7341 +/* Byte Ordering Conversions */
7342 +
7343 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
7344 +{
7345 +#ifdef __LITTLE_ENDIAN
7346 +       return *p;
7347 +#else
7348 +       uint8_t *u_p = (uint8_t *)p;
7349 +
7350 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7351 +#endif
7352 +}
7353 +
7354 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
7355 +{
7356 +#ifdef __BIG_ENDIAN
7357 +       return *p;
7358 +#else
7359 +       uint8_t *u_p = (uint8_t *)p;
7360 +
7361 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7362 +#endif
7363 +}
7364 +
7365 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
7366 +{
7367 +#ifdef __LITTLE_ENDIAN
7368 +       return *p;
7369 +#else
7370 +       uint8_t *u_p = (uint8_t *)p;
7371 +
7372 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7373 +#endif
7374 +}
7375 +
7376 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
7377 +{
7378 +#ifdef __BIG_ENDIAN
7379 +       return *p;
7380 +#else
7381 +       uint8_t *u_p = (uint8_t *)p;
7382 +
7383 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7384 +#endif
7385 +}
7386 +
7387 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
7388 +{
7389 +#ifdef __LITTLE_ENDIAN
7390 +       return *p;
7391 +#else
7392 +       uint8_t *u_p = (uint8_t *)p;
7393 +       return (u_p[1] | (u_p[0] << 8));
7394 +#endif
7395 +}
7396 +
7397 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
7398 +{
7399 +#ifdef __BIG_ENDIAN
7400 +       return *p;
7401 +#else
7402 +       uint8_t *u_p = (uint8_t *)p;
7403 +       return (u_p[1] | (u_p[0] << 8));
7404 +#endif
7405 +}
7406 +
7407 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
7408 +{
7409 +#ifdef __LITTLE_ENDIAN
7410 +       return *p;
7411 +#else
7412 +       uint8_t *u_p = (uint8_t *)p;
7413 +       return (u_p[1] | (u_p[0] << 8));
7414 +#endif
7415 +}
7416 +
7417 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
7418 +{
7419 +#ifdef __BIG_ENDIAN
7420 +       return *p;
7421 +#else
7422 +       uint8_t *u_p = (uint8_t *)p;
7423 +       return (u_p[1] | (u_p[0] << 8));
7424 +#endif
7425 +}
7426 +
7427 +
7428 +/* Registers */
7429 +
7430 +uint32_t DWC_READ_REG32(uint32_t volatile *reg)
7431 +{
7432 +       return readl(reg);
7433 +}
7434 +
7435 +#if 0
7436 +uint64_t DWC_READ_REG64(uint64_t volatile *reg)
7437 +{
7438 +}
7439 +#endif
7440 +
7441 +void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)
7442 +{
7443 +       writel(value, reg);
7444 +}
7445 +
7446 +#if 0
7447 +void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
7448 +{
7449 +}
7450 +#endif
7451 +
7452 +void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
7453 +{
7454 +       writel((readl(reg) & ~clear_mask) | set_mask, reg);
7455 +}
7456 +
7457 +#if 0
7458 +void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask)
7459 +{
7460 +}
7461 +#endif
7462 +
7463 +
7464 +/* Locking */
7465 +
7466 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
7467 +{
7468 +       spinlock_t *sl = (spinlock_t *)1;
7469 +
7470 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7471 +       sl = DWC_ALLOC(sizeof(*sl));
7472 +       if (!sl) {
7473 +               DWC_ERROR("Cannot allocate memory for spinlock\n");
7474 +               return NULL;
7475 +       }
7476 +
7477 +       spin_lock_init(sl);
7478 +#endif
7479 +       return (dwc_spinlock_t *)sl;
7480 +}
7481 +
7482 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
7483 +{
7484 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7485 +       DWC_FREE(lock);
7486 +#endif
7487 +}
7488 +
7489 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
7490 +{
7491 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7492 +       spin_lock((spinlock_t *)lock);
7493 +#endif
7494 +}
7495 +
7496 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
7497 +{
7498 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7499 +       spin_unlock((spinlock_t *)lock);
7500 +#endif
7501 +}
7502 +
7503 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
7504 +{
7505 +       dwc_irqflags_t f;
7506 +
7507 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7508 +       spin_lock_irqsave((spinlock_t *)lock, f);
7509 +#else
7510 +       local_irq_save(f);
7511 +#endif
7512 +       *flags = f;
7513 +}
7514 +
7515 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
7516 +{
7517 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7518 +       spin_unlock_irqrestore((spinlock_t *)lock, flags);
7519 +#else
7520 +       local_irq_restore(flags);
7521 +#endif
7522 +}
7523 +
7524 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
7525 +{
7526 +       struct mutex *m;
7527 +       dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex));
7528 +
7529 +       if (!mutex) {
7530 +               DWC_ERROR("Cannot allocate memory for mutex\n");
7531 +               return NULL;
7532 +       }
7533 +
7534 +       m = (struct mutex *)mutex;
7535 +       mutex_init(m);
7536 +       return mutex;
7537 +}
7538 +
7539 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
7540 +#else
7541 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
7542 +{
7543 +       mutex_destroy((struct mutex *)mutex);
7544 +       DWC_FREE(mutex);
7545 +}
7546 +#endif
7547 +
7548 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
7549 +{
7550 +       struct mutex *m = (struct mutex *)mutex;
7551 +       mutex_lock(m);
7552 +}
7553 +
7554 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
7555 +{
7556 +       struct mutex *m = (struct mutex *)mutex;
7557 +       return mutex_trylock(m);
7558 +}
7559 +
7560 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
7561 +{
7562 +       struct mutex *m = (struct mutex *)mutex;
7563 +       mutex_unlock(m);
7564 +}
7565 +
7566 +
7567 +/* Timing */
7568 +
7569 +void DWC_UDELAY(uint32_t usecs)
7570 +{
7571 +       udelay(usecs);
7572 +}
7573 +
7574 +void DWC_MDELAY(uint32_t msecs)
7575 +{
7576 +       mdelay(msecs);
7577 +}
7578 +
7579 +void DWC_MSLEEP(uint32_t msecs)
7580 +{
7581 +       msleep(msecs);
7582 +}
7583 +
7584 +uint32_t DWC_TIME(void)
7585 +{
7586 +       return jiffies_to_msecs(jiffies);
7587 +}
7588 +
7589 +
7590 +/* Timers */
7591 +
7592 +struct dwc_timer {
7593 +       struct timer_list *t;
7594 +       char *name;
7595 +       dwc_timer_callback_t cb;
7596 +       void *data;
7597 +       uint8_t scheduled;
7598 +       dwc_spinlock_t *lock;
7599 +};
7600 +
7601 +static void timer_callback(unsigned long data)
7602 +{
7603 +       dwc_timer_t *timer = (dwc_timer_t *)data;
7604 +       dwc_irqflags_t flags;
7605 +
7606 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7607 +       timer->scheduled = 0;
7608 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7609 +       DWC_DEBUGC("Timer %s callback", timer->name);
7610 +       timer->cb(timer->data);
7611 +}
7612 +
7613 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
7614 +{
7615 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
7616 +
7617 +       if (!t) {
7618 +               DWC_ERROR("Cannot allocate memory for timer");
7619 +               return NULL;
7620 +       }
7621 +
7622 +       t->t = DWC_ALLOC(sizeof(*t->t));
7623 +       if (!t->t) {
7624 +               DWC_ERROR("Cannot allocate memory for timer->t");
7625 +               goto no_timer;
7626 +       }
7627 +
7628 +       t->name = DWC_STRDUP(name);
7629 +       if (!t->name) {
7630 +               DWC_ERROR("Cannot allocate memory for timer->name");
7631 +               goto no_name;
7632 +       }
7633 +
7634 +       t->lock = DWC_SPINLOCK_ALLOC();
7635 +       if (!t->lock) {
7636 +               DWC_ERROR("Cannot allocate memory for lock");
7637 +               goto no_lock;
7638 +       }
7639 +
7640 +       t->scheduled = 0;
7641 +       t->t->base = &boot_tvec_bases;
7642 +       t->t->expires = jiffies;
7643 +       setup_timer(t->t, timer_callback, (unsigned long)t);
7644 +
7645 +       t->cb = cb;
7646 +       t->data = data;
7647 +
7648 +       return t;
7649 +
7650 + no_lock:
7651 +       DWC_FREE(t->name);
7652 + no_name:
7653 +       DWC_FREE(t->t);
7654 + no_timer:
7655 +       DWC_FREE(t);
7656 +       return NULL;
7657 +}
7658 +
7659 +void DWC_TIMER_FREE(dwc_timer_t *timer)
7660 +{
7661 +       dwc_irqflags_t flags;
7662 +
7663 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7664 +
7665 +       if (timer->scheduled) {
7666 +               del_timer(timer->t);
7667 +               timer->scheduled = 0;
7668 +       }
7669 +
7670 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7671 +       DWC_SPINLOCK_FREE(timer->lock);
7672 +       DWC_FREE(timer->t);
7673 +       DWC_FREE(timer->name);
7674 +       DWC_FREE(timer);
7675 +}
7676 +
7677 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
7678 +{
7679 +       dwc_irqflags_t flags;
7680 +
7681 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7682 +
7683 +       if (!timer->scheduled) {
7684 +               timer->scheduled = 1;
7685 +               DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time);
7686 +               timer->t->expires = jiffies + msecs_to_jiffies(time);
7687 +               add_timer(timer->t);
7688 +       } else {
7689 +               DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time);
7690 +               mod_timer(timer->t, jiffies + msecs_to_jiffies(time));
7691 +       }
7692 +
7693 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7694 +}
7695 +
7696 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
7697 +{
7698 +       del_timer(timer->t);
7699 +}
7700 +
7701 +
7702 +/* Wait Queues */
7703 +
7704 +struct dwc_waitq {
7705 +       wait_queue_head_t queue;
7706 +       int abort;
7707 +};
7708 +
7709 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
7710 +{
7711 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
7712 +
7713 +       if (!wq) {
7714 +               DWC_ERROR("Cannot allocate memory for waitqueue\n");
7715 +               return NULL;
7716 +       }
7717 +
7718 +       init_waitqueue_head(&wq->queue);
7719 +       wq->abort = 0;
7720 +       return wq;
7721 +}
7722 +
7723 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
7724 +{
7725 +       DWC_FREE(wq);
7726 +}
7727 +
7728 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
7729 +{
7730 +       int result = wait_event_interruptible(wq->queue,
7731 +                                             cond(data) || wq->abort);
7732 +       if (result == -ERESTARTSYS) {
7733 +               wq->abort = 0;
7734 +               return -DWC_E_RESTART;
7735 +       }
7736 +
7737 +       if (wq->abort == 1) {
7738 +               wq->abort = 0;
7739 +               return -DWC_E_ABORT;
7740 +       }
7741 +
7742 +       wq->abort = 0;
7743 +
7744 +       if (result == 0) {
7745 +               return 0;
7746 +       }
7747 +
7748 +       return -DWC_E_UNKNOWN;
7749 +}
7750 +
7751 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
7752 +                              void *data, int32_t msecs)
7753 +{
7754 +       int32_t tmsecs;
7755 +       int result = wait_event_interruptible_timeout(wq->queue,
7756 +                                                     cond(data) || wq->abort,
7757 +                                                     msecs_to_jiffies(msecs));
7758 +       if (result == -ERESTARTSYS) {
7759 +               wq->abort = 0;
7760 +               return -DWC_E_RESTART;
7761 +       }
7762 +
7763 +       if (wq->abort == 1) {
7764 +               wq->abort = 0;
7765 +               return -DWC_E_ABORT;
7766 +       }
7767 +
7768 +       wq->abort = 0;
7769 +
7770 +       if (result > 0) {
7771 +               tmsecs = jiffies_to_msecs(result);
7772 +               if (!tmsecs) {
7773 +                       return 1;
7774 +               }
7775 +
7776 +               return tmsecs;
7777 +       }
7778 +
7779 +       if (result == 0) {
7780 +               return -DWC_E_TIMEOUT;
7781 +       }
7782 +
7783 +       return -DWC_E_UNKNOWN;
7784 +}
7785 +
7786 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
7787 +{
7788 +       wq->abort = 0;
7789 +       wake_up_interruptible(&wq->queue);
7790 +}
7791 +
7792 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
7793 +{
7794 +       wq->abort = 1;
7795 +       wake_up_interruptible(&wq->queue);
7796 +}
7797 +
7798 +
7799 +/* Threading */
7800 +
7801 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
7802 +{
7803 +       struct task_struct *thread = kthread_run(func, data, name);
7804 +
7805 +       if (thread == ERR_PTR(-ENOMEM)) {
7806 +               return NULL;
7807 +       }
7808 +
7809 +       return (dwc_thread_t *)thread;
7810 +}
7811 +
7812 +int DWC_THREAD_STOP(dwc_thread_t *thread)
7813 +{
7814 +       return kthread_stop((struct task_struct *)thread);
7815 +}
7816 +
7817 +dwc_bool_t DWC_THREAD_SHOULD_STOP(void)
7818 +{
7819 +       return kthread_should_stop();
7820 +}
7821 +
7822 +
7823 +/* tasklets
7824 + - run in interrupt context (cannot sleep)
7825 + - each tasklet runs on a single CPU
7826 + - different tasklets can be running simultaneously on different CPUs
7827 + */
7828 +struct dwc_tasklet {
7829 +       struct tasklet_struct t;
7830 +       dwc_tasklet_callback_t cb;
7831 +       void *data;
7832 +};
7833 +
7834 +static void tasklet_callback(unsigned long data)
7835 +{
7836 +       dwc_tasklet_t *t = (dwc_tasklet_t *)data;
7837 +       t->cb(t->data);
7838 +}
7839 +
7840 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
7841 +{
7842 +       dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));
7843 +
7844 +       if (t) {
7845 +               t->cb = cb;
7846 +               t->data = data;
7847 +               tasklet_init(&t->t, tasklet_callback, (unsigned long)t);
7848 +       } else {
7849 +               DWC_ERROR("Cannot allocate memory for tasklet\n");
7850 +       }
7851 +
7852 +       return t;
7853 +}
7854 +
7855 +void DWC_TASK_FREE(dwc_tasklet_t *task)
7856 +{
7857 +       DWC_FREE(task);
7858 +}
7859 +
7860 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
7861 +{
7862 +       tasklet_schedule(&task->t);
7863 +}
7864 +
7865 +
7866 +/* workqueues
7867 + - run in process context (can sleep)
7868 + */
7869 +typedef struct work_container {
7870 +       dwc_work_callback_t cb;
7871 +       void *data;
7872 +       dwc_workq_t *wq;
7873 +       char *name;
7874 +
7875 +#ifdef DEBUG
7876 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
7877 +#endif
7878 +       struct delayed_work work;
7879 +} work_container_t;
7880 +
7881 +#ifdef DEBUG
7882 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
7883 +#endif
7884 +
7885 +struct dwc_workq {
7886 +       struct workqueue_struct *wq;
7887 +       dwc_spinlock_t *lock;
7888 +       dwc_waitq_t *waitq;
7889 +       int pending;
7890 +
7891 +#ifdef DEBUG
7892 +       struct work_container_queue entries;
7893 +#endif
7894 +};
7895 +
7896 +static void do_work(struct work_struct *work)
7897 +{
7898 +       dwc_irqflags_t flags;
7899 +       struct delayed_work *dw = container_of(work, struct delayed_work, work);
7900 +       work_container_t *container = container_of(dw, struct work_container, work);
7901 +       dwc_workq_t *wq = container->wq;
7902 +
7903 +       container->cb(container->data);
7904 +
7905 +#ifdef DEBUG
7906 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
7907 +#endif
7908 +       DWC_DEBUGC("Work done: %s, container=%p", container->name, container);
7909 +       if (container->name) {
7910 +               DWC_FREE(container->name);
7911 +       }
7912 +       DWC_FREE(container);
7913 +
7914 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7915 +       wq->pending--;
7916 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7917 +       DWC_WAITQ_TRIGGER(wq->waitq);
7918 +}
7919 +
7920 +static int work_done(void *data)
7921 +{
7922 +       dwc_workq_t *workq = (dwc_workq_t *)data;
7923 +       return workq->pending == 0;
7924 +}
7925 +
7926 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
7927 +{
7928 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
7929 +}
7930 +
7931 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
7932 +{
7933 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
7934 +
7935 +       if (!wq) {
7936 +               return NULL;
7937 +       }
7938 +
7939 +       wq->wq = create_singlethread_workqueue(name);
7940 +       if (!wq->wq) {
7941 +               goto no_wq;
7942 +       }
7943 +
7944 +       wq->pending = 0;
7945 +
7946 +       wq->lock = DWC_SPINLOCK_ALLOC();
7947 +       if (!wq->lock) {
7948 +               goto no_lock;
7949 +       }
7950 +
7951 +       wq->waitq = DWC_WAITQ_ALLOC();
7952 +       if (!wq->waitq) {
7953 +               goto no_waitq;
7954 +       }
7955 +
7956 +#ifdef DEBUG
7957 +       DWC_CIRCLEQ_INIT(&wq->entries);
7958 +#endif
7959 +       return wq;
7960 +
7961 + no_waitq:
7962 +       DWC_SPINLOCK_FREE(wq->lock);
7963 + no_lock:
7964 +       destroy_workqueue(wq->wq);
7965 + no_wq:
7966 +       DWC_FREE(wq);
7967 +
7968 +       return NULL;
7969 +}
7970 +
7971 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
7972 +{
7973 +#ifdef DEBUG
7974 +       if (wq->pending != 0) {
7975 +               struct work_container *wc;
7976 +               DWC_ERROR("Destroying work queue with pending work");
7977 +               DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {
7978 +                       DWC_ERROR("Work %s still pending", wc->name);
7979 +               }
7980 +       }
7981 +#endif
7982 +       destroy_workqueue(wq->wq);
7983 +       DWC_SPINLOCK_FREE(wq->lock);
7984 +       DWC_WAITQ_FREE(wq->waitq);
7985 +       DWC_FREE(wq);
7986 +}
7987 +
7988 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
7989 +                       char *format, ...)
7990 +{
7991 +       dwc_irqflags_t flags;
7992 +       work_container_t *container;
7993 +       static char name[128];
7994 +       va_list args;
7995 +
7996 +       va_start(args, format);
7997 +       DWC_VSNPRINTF(name, 128, format, args);
7998 +       va_end(args);
7999 +
8000 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
8001 +       wq->pending++;
8002 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
8003 +       DWC_WAITQ_TRIGGER(wq->waitq);
8004 +
8005 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
8006 +       if (!container) {
8007 +               DWC_ERROR("Cannot allocate memory for container\n");
8008 +               return;
8009 +       }
8010 +
8011 +       container->name = DWC_STRDUP(name);
8012 +       if (!container->name) {
8013 +               DWC_ERROR("Cannot allocate memory for container->name\n");
8014 +               DWC_FREE(container);
8015 +               return;
8016 +       }
8017 +
8018 +       container->cb = cb;
8019 +       container->data = data;
8020 +       container->wq = wq;
8021 +       DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
8022 +       INIT_WORK(&container->work.work, do_work);
8023 +
8024 +#ifdef DEBUG
8025 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
8026 +#endif
8027 +       queue_work(wq->wq, &container->work.work);
8028 +}
8029 +
8030 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
8031 +                               void *data, uint32_t time, char *format, ...)
8032 +{
8033 +       dwc_irqflags_t flags;
8034 +       work_container_t *container;
8035 +       static char name[128];
8036 +       va_list args;
8037 +
8038 +       va_start(args, format);
8039 +       DWC_VSNPRINTF(name, 128, format, args);
8040 +       va_end(args);
8041 +
8042 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
8043 +       wq->pending++;
8044 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
8045 +       DWC_WAITQ_TRIGGER(wq->waitq);
8046 +
8047 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
8048 +       if (!container) {
8049 +               DWC_ERROR("Cannot allocate memory for container\n");
8050 +               return;
8051 +       }
8052 +
8053 +       container->name = DWC_STRDUP(name);
8054 +       if (!container->name) {
8055 +               DWC_ERROR("Cannot allocate memory for container->name\n");
8056 +               DWC_FREE(container);
8057 +               return;
8058 +       }
8059 +
8060 +       container->cb = cb;
8061 +       container->data = data;
8062 +       container->wq = wq;
8063 +       DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
8064 +       INIT_DELAYED_WORK(&container->work, do_work);
8065 +
8066 +#ifdef DEBUG
8067 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
8068 +#endif
8069 +       queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));
8070 +}
8071 +
8072 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
8073 +{
8074 +       return wq->pending;
8075 +}
8076 +
8077 +
8078 +#ifdef DWC_LIBMODULE
8079 +
8080 +#ifdef DWC_CCLIB
8081 +/* CC */
8082 +EXPORT_SYMBOL(dwc_cc_if_alloc);
8083 +EXPORT_SYMBOL(dwc_cc_if_free);
8084 +EXPORT_SYMBOL(dwc_cc_clear);
8085 +EXPORT_SYMBOL(dwc_cc_add);
8086 +EXPORT_SYMBOL(dwc_cc_remove);
8087 +EXPORT_SYMBOL(dwc_cc_change);
8088 +EXPORT_SYMBOL(dwc_cc_data_for_save);
8089 +EXPORT_SYMBOL(dwc_cc_restore_from_data);
8090 +EXPORT_SYMBOL(dwc_cc_match_chid);
8091 +EXPORT_SYMBOL(dwc_cc_match_cdid);
8092 +EXPORT_SYMBOL(dwc_cc_ck);
8093 +EXPORT_SYMBOL(dwc_cc_chid);
8094 +EXPORT_SYMBOL(dwc_cc_cdid);
8095 +EXPORT_SYMBOL(dwc_cc_name);
8096 +#endif /* DWC_CCLIB */
8097 +
8098 +#ifdef DWC_CRYPTOLIB
8099 +# ifndef CONFIG_MACH_IPMATE
8100 +/* Modpow */
8101 +EXPORT_SYMBOL(dwc_modpow);
8102 +
8103 +/* DH */
8104 +EXPORT_SYMBOL(dwc_dh_modpow);
8105 +EXPORT_SYMBOL(dwc_dh_derive_keys);
8106 +EXPORT_SYMBOL(dwc_dh_pk);
8107 +# endif        /* CONFIG_MACH_IPMATE */
8108 +
8109 +/* Crypto */
8110 +EXPORT_SYMBOL(dwc_wusb_aes_encrypt);
8111 +EXPORT_SYMBOL(dwc_wusb_cmf);
8112 +EXPORT_SYMBOL(dwc_wusb_prf);
8113 +EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);
8114 +EXPORT_SYMBOL(dwc_wusb_gen_nonce);
8115 +EXPORT_SYMBOL(dwc_wusb_gen_key);
8116 +EXPORT_SYMBOL(dwc_wusb_gen_mic);
8117 +#endif /* DWC_CRYPTOLIB */
8118 +
8119 +/* Notification */
8120 +#ifdef DWC_NOTIFYLIB
8121 +EXPORT_SYMBOL(dwc_alloc_notification_manager);
8122 +EXPORT_SYMBOL(dwc_free_notification_manager);
8123 +EXPORT_SYMBOL(dwc_register_notifier);
8124 +EXPORT_SYMBOL(dwc_unregister_notifier);
8125 +EXPORT_SYMBOL(dwc_add_observer);
8126 +EXPORT_SYMBOL(dwc_remove_observer);
8127 +EXPORT_SYMBOL(dwc_notify);
8128 +#endif
8129 +
8130 +/* Memory Debugging Routines */
8131 +#ifdef DWC_DEBUG_MEMORY
8132 +EXPORT_SYMBOL(dwc_alloc_debug);
8133 +EXPORT_SYMBOL(dwc_alloc_atomic_debug);
8134 +EXPORT_SYMBOL(dwc_free_debug);
8135 +EXPORT_SYMBOL(dwc_dma_alloc_debug);
8136 +EXPORT_SYMBOL(dwc_dma_free_debug);
8137 +#endif
8138 +
8139 +EXPORT_SYMBOL(DWC_MEMSET);
8140 +EXPORT_SYMBOL(DWC_MEMCPY);
8141 +EXPORT_SYMBOL(DWC_MEMMOVE);
8142 +EXPORT_SYMBOL(DWC_MEMCMP);
8143 +EXPORT_SYMBOL(DWC_STRNCMP);
8144 +EXPORT_SYMBOL(DWC_STRCMP);
8145 +EXPORT_SYMBOL(DWC_STRLEN);
8146 +EXPORT_SYMBOL(DWC_STRCPY);
8147 +EXPORT_SYMBOL(DWC_STRDUP);
8148 +EXPORT_SYMBOL(DWC_ATOI);
8149 +EXPORT_SYMBOL(DWC_ATOUI);
8150 +
8151 +#ifdef DWC_UTFLIB
8152 +EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);
8153 +#endif /* DWC_UTFLIB */
8154 +
8155 +EXPORT_SYMBOL(DWC_IN_IRQ);
8156 +EXPORT_SYMBOL(DWC_IN_BH);
8157 +EXPORT_SYMBOL(DWC_VPRINTF);
8158 +EXPORT_SYMBOL(DWC_VSNPRINTF);
8159 +EXPORT_SYMBOL(DWC_PRINTF);
8160 +EXPORT_SYMBOL(DWC_SPRINTF);
8161 +EXPORT_SYMBOL(DWC_SNPRINTF);
8162 +EXPORT_SYMBOL(__DWC_WARN);
8163 +EXPORT_SYMBOL(__DWC_ERROR);
8164 +EXPORT_SYMBOL(DWC_EXCEPTION);
8165 +
8166 +#ifdef DEBUG
8167 +EXPORT_SYMBOL(__DWC_DEBUG);
8168 +#endif
8169 +
8170 +EXPORT_SYMBOL(__DWC_DMA_ALLOC);\r
8171 +EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
8172 +EXPORT_SYMBOL(__DWC_DMA_FREE);
8173 +EXPORT_SYMBOL(__DWC_ALLOC);
8174 +EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);
8175 +EXPORT_SYMBOL(__DWC_FREE);
8176 +
8177 +#ifdef DWC_CRYPTOLIB
8178 +EXPORT_SYMBOL(DWC_RANDOM_BYTES);
8179 +EXPORT_SYMBOL(DWC_AES_CBC);
8180 +EXPORT_SYMBOL(DWC_SHA256);
8181 +EXPORT_SYMBOL(DWC_HMAC_SHA256);
8182 +#endif
8183 +
8184 +EXPORT_SYMBOL(DWC_CPU_TO_LE32);
8185 +EXPORT_SYMBOL(DWC_CPU_TO_BE32);
8186 +EXPORT_SYMBOL(DWC_LE32_TO_CPU);
8187 +EXPORT_SYMBOL(DWC_BE32_TO_CPU);
8188 +EXPORT_SYMBOL(DWC_CPU_TO_LE16);
8189 +EXPORT_SYMBOL(DWC_CPU_TO_BE16);
8190 +EXPORT_SYMBOL(DWC_LE16_TO_CPU);
8191 +EXPORT_SYMBOL(DWC_BE16_TO_CPU);
8192 +EXPORT_SYMBOL(DWC_READ_REG32);
8193 +EXPORT_SYMBOL(DWC_WRITE_REG32);
8194 +EXPORT_SYMBOL(DWC_MODIFY_REG32);
8195 +
8196 +#if 0
8197 +EXPORT_SYMBOL(DWC_READ_REG64);
8198 +EXPORT_SYMBOL(DWC_WRITE_REG64);
8199 +EXPORT_SYMBOL(DWC_MODIFY_REG64);
8200 +#endif
8201 +
8202 +EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);
8203 +EXPORT_SYMBOL(DWC_SPINLOCK_FREE);
8204 +EXPORT_SYMBOL(DWC_SPINLOCK);
8205 +EXPORT_SYMBOL(DWC_SPINUNLOCK);
8206 +EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);
8207 +EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);
8208 +EXPORT_SYMBOL(DWC_MUTEX_ALLOC);
8209 +
8210 +#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES))
8211 +EXPORT_SYMBOL(DWC_MUTEX_FREE);
8212 +#endif
8213 +
8214 +EXPORT_SYMBOL(DWC_MUTEX_LOCK);
8215 +EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);
8216 +EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);
8217 +EXPORT_SYMBOL(DWC_UDELAY);
8218 +EXPORT_SYMBOL(DWC_MDELAY);
8219 +EXPORT_SYMBOL(DWC_MSLEEP);
8220 +EXPORT_SYMBOL(DWC_TIME);
8221 +EXPORT_SYMBOL(DWC_TIMER_ALLOC);
8222 +EXPORT_SYMBOL(DWC_TIMER_FREE);
8223 +EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);
8224 +EXPORT_SYMBOL(DWC_TIMER_CANCEL);
8225 +EXPORT_SYMBOL(DWC_WAITQ_ALLOC);
8226 +EXPORT_SYMBOL(DWC_WAITQ_FREE);
8227 +EXPORT_SYMBOL(DWC_WAITQ_WAIT);
8228 +EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);
8229 +EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);
8230 +EXPORT_SYMBOL(DWC_WAITQ_ABORT);
8231 +EXPORT_SYMBOL(DWC_THREAD_RUN);
8232 +EXPORT_SYMBOL(DWC_THREAD_STOP);
8233 +EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);
8234 +EXPORT_SYMBOL(DWC_TASK_ALLOC);
8235 +EXPORT_SYMBOL(DWC_TASK_FREE);
8236 +EXPORT_SYMBOL(DWC_TASK_SCHEDULE);
8237 +EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);
8238 +EXPORT_SYMBOL(DWC_WORKQ_ALLOC);
8239 +EXPORT_SYMBOL(DWC_WORKQ_FREE);
8240 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);
8241 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);
8242 +EXPORT_SYMBOL(DWC_WORKQ_PENDING);
8243 +
8244 +static int dwc_common_port_init_module(void)
8245 +{
8246 +       int result = 0;
8247 +
8248 +       printk(KERN_DEBUG "Module dwc_common_port init\n" );
8249 +
8250 +#ifdef DWC_DEBUG_MEMORY
8251 +       result = dwc_memory_debug_start(NULL);
8252 +       if (result) {
8253 +               printk(KERN_ERR
8254 +                      "dwc_memory_debug_start() failed with error %d\n",
8255 +                      result);
8256 +               return result;
8257 +       }
8258 +#endif
8259 +
8260 +#ifdef DWC_NOTIFYLIB
8261 +       result = dwc_alloc_notification_manager(NULL, NULL);
8262 +       if (result) {
8263 +               printk(KERN_ERR
8264 +                      "dwc_alloc_notification_manager() failed with error %d\n",
8265 +                      result);
8266 +               return result;
8267 +       }
8268 +#endif
8269 +       return result;
8270 +}
8271 +
8272 +static void dwc_common_port_exit_module(void)
8273 +{
8274 +       printk(KERN_DEBUG "Module dwc_common_port exit\n" );
8275 +
8276 +#ifdef DWC_NOTIFYLIB
8277 +       dwc_free_notification_manager();
8278 +#endif
8279 +
8280 +#ifdef DWC_DEBUG_MEMORY
8281 +       dwc_memory_debug_stop();
8282 +#endif
8283 +}
8284 +
8285 +module_init(dwc_common_port_init_module);
8286 +module_exit(dwc_common_port_exit_module);
8287 +
8288 +MODULE_DESCRIPTION("DWC Common Library - Portable version");
8289 +MODULE_AUTHOR("Synopsys Inc.");
8290 +MODULE_LICENSE ("GPL");
8291 +
8292 +#endif /* DWC_LIBMODULE */
8293 diff --git a/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
8294 new file mode 100644
8295 index 0000000..49b07e1
8296 --- /dev/null
8297 +++ b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
8298 @@ -0,0 +1,1275 @@
8299 +#include "dwc_os.h"
8300 +#include "dwc_list.h"
8301 +
8302 +#ifdef DWC_CCLIB
8303 +# include "dwc_cc.h"
8304 +#endif
8305 +
8306 +#ifdef DWC_CRYPTOLIB
8307 +# include "dwc_modpow.h"
8308 +# include "dwc_dh.h"
8309 +# include "dwc_crypto.h"
8310 +#endif
8311 +
8312 +#ifdef DWC_NOTIFYLIB
8313 +# include "dwc_notifier.h"
8314 +#endif
8315 +
8316 +/* OS-Level Implementations */
8317 +
8318 +/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */
8319 +
8320 +
8321 +/* MISC */
8322 +
8323 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
8324 +{
8325 +       return memset(dest, byte, size);
8326 +}
8327 +
8328 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
8329 +{
8330 +       return memcpy(dest, src, size);
8331 +}
8332 +
8333 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
8334 +{
8335 +       bcopy(src, dest, size);
8336 +       return dest;
8337 +}
8338 +
8339 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
8340 +{
8341 +       return memcmp(m1, m2, size);
8342 +}
8343 +
8344 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
8345 +{
8346 +       return strncmp(s1, s2, size);
8347 +}
8348 +
8349 +int DWC_STRCMP(void *s1, void *s2)
8350 +{
8351 +       return strcmp(s1, s2);
8352 +}
8353 +
8354 +int DWC_STRLEN(char const *str)
8355 +{
8356 +       return strlen(str);
8357 +}
8358 +
8359 +char *DWC_STRCPY(char *to, char const *from)
8360 +{
8361 +       return strcpy(to, from);
8362 +}
8363 +
8364 +char *DWC_STRDUP(char const *str)
8365 +{
8366 +       int len = DWC_STRLEN(str) + 1;
8367 +       char *new = DWC_ALLOC_ATOMIC(len);
8368 +
8369 +       if (!new) {
8370 +               return NULL;
8371 +       }
8372 +
8373 +       DWC_MEMCPY(new, str, len);
8374 +       return new;
8375 +}
8376 +
8377 +int DWC_ATOI(char *str, int32_t *value)
8378 +{
8379 +       char *end = NULL;
8380 +
8381 +       /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul'
8382 +        * should be equivalent on 2's complement machines
8383 +        */
8384 +       *value = strtoul(str, &end, 0);
8385 +       if (*end == '\0') {
8386 +               return 0;
8387 +       }
8388 +
8389 +       return -1;
8390 +}
8391 +
8392 +int DWC_ATOUI(char *str, uint32_t *value)
8393 +{
8394 +       char *end = NULL;
8395 +
8396 +       *value = strtoul(str, &end, 0);
8397 +       if (*end == '\0') {
8398 +               return 0;
8399 +       }
8400 +
8401 +       return -1;
8402 +}
8403 +
8404 +
8405 +#ifdef DWC_UTFLIB
8406 +/* From usbstring.c */
8407 +
8408 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
8409 +{
8410 +       int     count = 0;
8411 +       u8      c;
8412 +       u16     uchar;
8413 +
8414 +       /* this insists on correct encodings, though not minimal ones.
8415 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
8416 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
8417 +        */
8418 +       while (len != 0 && (c = (u8) *s++) != 0) {
8419 +               if (unlikely(c & 0x80)) {
8420 +                       // 2-byte sequence:
8421 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
8422 +                       if ((c & 0xe0) == 0xc0) {
8423 +                               uchar = (c & 0x1f) << 6;
8424 +
8425 +                               c = (u8) *s++;
8426 +                               if ((c & 0xc0) != 0xc0)
8427 +                                       goto fail;
8428 +                               c &= 0x3f;
8429 +                               uchar |= c;
8430 +
8431 +                       // 3-byte sequence (most CJKV characters):
8432 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
8433 +                       } else if ((c & 0xf0) == 0xe0) {
8434 +                               uchar = (c & 0x0f) << 12;
8435 +
8436 +                               c = (u8) *s++;
8437 +                               if ((c & 0xc0) != 0xc0)
8438 +                                       goto fail;
8439 +                               c &= 0x3f;
8440 +                               uchar |= c << 6;
8441 +
8442 +                               c = (u8) *s++;
8443 +                               if ((c & 0xc0) != 0xc0)
8444 +                                       goto fail;
8445 +                               c &= 0x3f;
8446 +                               uchar |= c;
8447 +
8448 +                               /* no bogus surrogates */
8449 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
8450 +                                       goto fail;
8451 +
8452 +                       // 4-byte sequence (surrogate pairs, currently rare):
8453 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
8454 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
8455 +                       // (uuuuu = wwww + 1)
8456 +                       // FIXME accept the surrogate code points (only)
8457 +                       } else
8458 +                               goto fail;
8459 +               } else
8460 +                       uchar = c;
8461 +               put_unaligned (cpu_to_le16 (uchar), cp++);
8462 +               count++;
8463 +               len--;
8464 +       }
8465 +       return count;
8466 +fail:
8467 +       return -1;
8468 +}
8469 +
8470 +#endif /* DWC_UTFLIB */
8471 +
8472 +
8473 +/* dwc_debug.h */
8474 +
8475 +dwc_bool_t DWC_IN_IRQ(void)
8476 +{
8477 +//     return in_irq();
8478 +       return 0;
8479 +}
8480 +
8481 +dwc_bool_t DWC_IN_BH(void)
8482 +{
8483 +//     return in_softirq();
8484 +       return 0;
8485 +}
8486 +
8487 +void DWC_VPRINTF(char *format, va_list args)
8488 +{
8489 +       vprintf(format, args);
8490 +}
8491 +
8492 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
8493 +{
8494 +       return vsnprintf(str, size, format, args);
8495 +}
8496 +
8497 +void DWC_PRINTF(char *format, ...)
8498 +{
8499 +       va_list args;
8500 +
8501 +       va_start(args, format);
8502 +       DWC_VPRINTF(format, args);
8503 +       va_end(args);
8504 +}
8505 +
8506 +int DWC_SPRINTF(char *buffer, char *format, ...)
8507 +{
8508 +       int retval;
8509 +       va_list args;
8510 +
8511 +       va_start(args, format);
8512 +       retval = vsprintf(buffer, format, args);
8513 +       va_end(args);
8514 +       return retval;
8515 +}
8516 +
8517 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
8518 +{
8519 +       int retval;
8520 +       va_list args;
8521 +
8522 +       va_start(args, format);
8523 +       retval = vsnprintf(buffer, size, format, args);
8524 +       va_end(args);
8525 +       return retval;
8526 +}
8527 +
8528 +void __DWC_WARN(char *format, ...)
8529 +{
8530 +       va_list args;
8531 +
8532 +       va_start(args, format);
8533 +       DWC_VPRINTF(format, args);
8534 +       va_end(args);
8535 +}
8536 +
8537 +void __DWC_ERROR(char *format, ...)
8538 +{
8539 +       va_list args;
8540 +
8541 +       va_start(args, format);
8542 +       DWC_VPRINTF(format, args);
8543 +       va_end(args);
8544 +}
8545 +
8546 +void DWC_EXCEPTION(char *format, ...)
8547 +{
8548 +       va_list args;
8549 +
8550 +       va_start(args, format);
8551 +       DWC_VPRINTF(format, args);
8552 +       va_end(args);
8553 +//     BUG_ON(1);      ???
8554 +}
8555 +
8556 +#ifdef DEBUG
8557 +void __DWC_DEBUG(char *format, ...)
8558 +{
8559 +       va_list args;
8560 +
8561 +       va_start(args, format);
8562 +       DWC_VPRINTF(format, args);
8563 +       va_end(args);
8564 +}
8565 +#endif
8566 +
8567 +
8568 +/* dwc_mem.h */
8569 +
8570 +#if 0
8571 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
8572 +                               uint32_t align,
8573 +                               uint32_t alloc)
8574 +{
8575 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
8576 +                                               size, align, alloc);
8577 +       return (dwc_pool_t *)pool;
8578 +}
8579 +
8580 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
8581 +{
8582 +       dma_pool_destroy((struct dma_pool *)pool);
8583 +}
8584 +
8585 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8586 +{
8587 +//     return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
8588 +       return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
8589 +}
8590 +
8591 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8592 +{
8593 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
8594 +       memset(..);
8595 +}
8596 +
8597 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
8598 +{
8599 +       dma_pool_free(pool, vaddr, daddr);
8600 +}
8601 +#endif
8602 +
8603 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
8604 +{
8605 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8606 +       int error;
8607 +
8608 +       error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs,
8609 +                                sizeof(dma->segs) / sizeof(dma->segs[0]),
8610 +                                &dma->nsegs, BUS_DMA_NOWAIT);
8611 +       if (error) {
8612 +               printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__,
8613 +                      (uintmax_t)size, error);
8614 +               goto fail_0;
8615 +       }
8616 +
8617 +       error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size,
8618 +                              (caddr_t *)&dma->dma_vaddr,
8619 +                              BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
8620 +       if (error) {
8621 +               printf("%s: bus_dmamem_map failed: %d\n", __func__, error);
8622 +               goto fail_1;
8623 +       }
8624 +
8625 +       error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0,
8626 +                                 BUS_DMA_NOWAIT, &dma->dma_map);
8627 +       if (error) {
8628 +               printf("%s: bus_dmamap_create failed: %d\n", __func__, error);
8629 +               goto fail_2;
8630 +       }
8631 +
8632 +       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
8633 +                               size, NULL, BUS_DMA_NOWAIT);
8634 +       if (error) {
8635 +               printf("%s: bus_dmamap_load failed: %d\n", __func__, error);
8636 +               goto fail_3;
8637 +       }
8638 +
8639 +       dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr;
8640 +       *dma_addr = dma->dma_paddr;
8641 +       return dma->dma_vaddr;
8642 +
8643 +fail_3:
8644 +       bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8645 +fail_2:
8646 +       bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8647 +fail_1:
8648 +       bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8649 +fail_0:
8650 +       dma->dma_map = NULL;
8651 +       dma->dma_vaddr = NULL;
8652 +       dma->nsegs = 0;
8653 +
8654 +       return NULL;
8655 +}
8656 +
8657 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
8658 +{
8659 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8660 +
8661 +       if (dma->dma_map != NULL) {
8662 +               bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size,
8663 +                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
8664 +               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
8665 +               bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8666 +               bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8667 +               bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8668 +               dma->dma_paddr = 0;
8669 +               dma->dma_map = NULL;
8670 +               dma->dma_vaddr = NULL;
8671 +               dma->nsegs = 0;
8672 +       }
8673 +}
8674 +
8675 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
8676 +{
8677 +       return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
8678 +}
8679 +
8680 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
8681 +{
8682 +       return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
8683 +}
8684 +
8685 +void __DWC_FREE(void *mem_ctx, void *addr)
8686 +{
8687 +       free(addr, M_DEVBUF);
8688 +}
8689 +
8690 +
8691 +#ifdef DWC_CRYPTOLIB
8692 +/* dwc_crypto.h */
8693 +
8694 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
8695 +{
8696 +       get_random_bytes(buffer, length);
8697 +}
8698 +
8699 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
8700 +{
8701 +       struct crypto_blkcipher *tfm;
8702 +       struct blkcipher_desc desc;
8703 +       struct scatterlist sgd;
8704 +       struct scatterlist sgs;
8705 +
8706 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
8707 +       if (tfm == NULL) {
8708 +               printk("failed to load transform for aes CBC\n");
8709 +               return -1;
8710 +       }
8711 +
8712 +       crypto_blkcipher_setkey(tfm, key, keylen);
8713 +       crypto_blkcipher_set_iv(tfm, iv, 16);
8714 +
8715 +       sg_init_one(&sgd, out, messagelen);
8716 +       sg_init_one(&sgs, message, messagelen);
8717 +
8718 +       desc.tfm = tfm;
8719 +       desc.flags = 0;
8720 +
8721 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
8722 +               crypto_free_blkcipher(tfm);
8723 +               DWC_ERROR("AES CBC encryption failed");
8724 +               return -1;
8725 +       }
8726 +
8727 +       crypto_free_blkcipher(tfm);
8728 +       return 0;
8729 +}
8730 +
8731 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
8732 +{
8733 +       struct crypto_hash *tfm;
8734 +       struct hash_desc desc;
8735 +       struct scatterlist sg;
8736 +
8737 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
8738 +       if (IS_ERR(tfm)) {
8739 +               DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
8740 +               return 0;
8741 +       }
8742 +       desc.tfm = tfm;
8743 +       desc.flags = 0;
8744 +
8745 +       sg_init_one(&sg, message, len);
8746 +       crypto_hash_digest(&desc, &sg, len, out);
8747 +       crypto_free_hash(tfm);
8748 +
8749 +       return 1;
8750 +}
8751 +
8752 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
8753 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
8754 +{
8755 +       struct crypto_hash *tfm;
8756 +       struct hash_desc desc;
8757 +       struct scatterlist sg;
8758 +
8759 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
8760 +       if (IS_ERR(tfm)) {
8761 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
8762 +               return 0;
8763 +       }
8764 +       desc.tfm = tfm;
8765 +       desc.flags = 0;
8766 +
8767 +       sg_init_one(&sg, message, messagelen);
8768 +       crypto_hash_setkey(tfm, key, keylen);
8769 +       crypto_hash_digest(&desc, &sg, messagelen, out);
8770 +       crypto_free_hash(tfm);
8771 +
8772 +       return 1;
8773 +}
8774 +
8775 +#endif /* DWC_CRYPTOLIB */
8776 +
8777 +
8778 +/* Byte Ordering Conversions */
8779 +
8780 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
8781 +{
8782 +#ifdef __LITTLE_ENDIAN
8783 +       return *p;
8784 +#else
8785 +       uint8_t *u_p = (uint8_t *)p;
8786 +
8787 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8788 +#endif
8789 +}
8790 +
8791 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
8792 +{
8793 +#ifdef __BIG_ENDIAN
8794 +       return *p;
8795 +#else
8796 +       uint8_t *u_p = (uint8_t *)p;
8797 +
8798 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8799 +#endif
8800 +}
8801 +
8802 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
8803 +{
8804 +#ifdef __LITTLE_ENDIAN
8805 +       return *p;
8806 +#else
8807 +       uint8_t *u_p = (uint8_t *)p;
8808 +
8809 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8810 +#endif
8811 +}
8812 +
8813 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
8814 +{
8815 +#ifdef __BIG_ENDIAN
8816 +       return *p;
8817 +#else
8818 +       uint8_t *u_p = (uint8_t *)p;
8819 +
8820 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8821 +#endif
8822 +}
8823 +
8824 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
8825 +{
8826 +#ifdef __LITTLE_ENDIAN
8827 +       return *p;
8828 +#else
8829 +       uint8_t *u_p = (uint8_t *)p;
8830 +       return (u_p[1] | (u_p[0] << 8));
8831 +#endif
8832 +}
8833 +
8834 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
8835 +{
8836 +#ifdef __BIG_ENDIAN
8837 +       return *p;
8838 +#else
8839 +       uint8_t *u_p = (uint8_t *)p;
8840 +       return (u_p[1] | (u_p[0] << 8));
8841 +#endif
8842 +}
8843 +
8844 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
8845 +{
8846 +#ifdef __LITTLE_ENDIAN
8847 +       return *p;
8848 +#else
8849 +       uint8_t *u_p = (uint8_t *)p;
8850 +       return (u_p[1] | (u_p[0] << 8));
8851 +#endif
8852 +}
8853 +
8854 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
8855 +{
8856 +#ifdef __BIG_ENDIAN
8857 +       return *p;
8858 +#else
8859 +       uint8_t *u_p = (uint8_t *)p;
8860 +       return (u_p[1] | (u_p[0] << 8));
8861 +#endif
8862 +}
8863 +
8864 +
8865 +/* Registers */
8866 +
8867 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
8868 +{
8869 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8870 +       bus_size_t ior = (bus_size_t)reg;
8871 +
8872 +       return bus_space_read_4(io->iot, io->ioh, ior);
8873 +}
8874 +
8875 +#if 0
8876 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
8877 +{
8878 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8879 +       bus_size_t ior = (bus_size_t)reg;
8880 +
8881 +       return bus_space_read_8(io->iot, io->ioh, ior);
8882 +}
8883 +#endif
8884 +
8885 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
8886 +{
8887 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8888 +       bus_size_t ior = (bus_size_t)reg;
8889 +
8890 +       bus_space_write_4(io->iot, io->ioh, ior, value);
8891 +}
8892 +
8893 +#if 0
8894 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
8895 +{
8896 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8897 +       bus_size_t ior = (bus_size_t)reg;
8898 +
8899 +       bus_space_write_8(io->iot, io->ioh, ior, value);
8900 +}
8901 +#endif
8902 +
8903 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
8904 +                     uint32_t set_mask)
8905 +{
8906 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8907 +       bus_size_t ior = (bus_size_t)reg;
8908 +
8909 +       bus_space_write_4(io->iot, io->ioh, ior,
8910 +                         (bus_space_read_4(io->iot, io->ioh, ior) &
8911 +                          ~clear_mask) | set_mask);
8912 +}
8913 +
8914 +#if 0
8915 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
8916 +                     uint64_t set_mask)
8917 +{
8918 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8919 +       bus_size_t ior = (bus_size_t)reg;
8920 +
8921 +       bus_space_write_8(io->iot, io->ioh, ior,
8922 +                         (bus_space_read_8(io->iot, io->ioh, ior) &
8923 +                          ~clear_mask) | set_mask);
8924 +}
8925 +#endif
8926 +
8927 +
8928 +/* Locking */
8929 +
8930 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
8931 +{
8932 +       struct simplelock *sl = DWC_ALLOC(sizeof(*sl));
8933 +
8934 +       if (!sl) {
8935 +               DWC_ERROR("Cannot allocate memory for spinlock");
8936 +               return NULL;
8937 +       }
8938 +
8939 +       simple_lock_init(sl);
8940 +       return (dwc_spinlock_t *)sl;
8941 +}
8942 +
8943 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
8944 +{
8945 +       struct simplelock *sl = (struct simplelock *)lock;
8946 +
8947 +       DWC_FREE(sl);
8948 +}
8949 +
8950 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
8951 +{
8952 +       simple_lock((struct simplelock *)lock);
8953 +}
8954 +
8955 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
8956 +{
8957 +       simple_unlock((struct simplelock *)lock);
8958 +}
8959 +
8960 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
8961 +{
8962 +       simple_lock((struct simplelock *)lock);
8963 +       *flags = splbio();
8964 +}
8965 +
8966 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
8967 +{
8968 +       splx(flags);
8969 +       simple_unlock((struct simplelock *)lock);
8970 +}
8971 +
8972 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
8973 +{
8974 +       dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock));
8975 +
8976 +       if (!mutex) {
8977 +               DWC_ERROR("Cannot allocate memory for mutex");
8978 +               return NULL;
8979 +       }
8980 +
8981 +       lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0);
8982 +       return mutex;
8983 +}
8984 +
8985 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
8986 +#else
8987 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
8988 +{
8989 +       DWC_FREE(mutex);
8990 +}
8991 +#endif
8992 +
8993 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
8994 +{
8995 +       lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL);
8996 +}
8997 +
8998 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
8999 +{
9000 +       int status;
9001 +
9002 +       status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL);
9003 +       return status == 0;
9004 +}
9005 +
9006 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
9007 +{
9008 +       lockmgr((struct lock *)mutex, LK_RELEASE, NULL);
9009 +}
9010 +
9011 +
9012 +/* Timing */
9013 +
9014 +void DWC_UDELAY(uint32_t usecs)
9015 +{
9016 +       DELAY(usecs);
9017 +}
9018 +
9019 +void DWC_MDELAY(uint32_t msecs)
9020 +{
9021 +       do {
9022 +               DELAY(1000);
9023 +       } while (--msecs);
9024 +}
9025 +
9026 +void DWC_MSLEEP(uint32_t msecs)
9027 +{
9028 +       struct timeval tv;
9029 +
9030 +       tv.tv_sec = msecs / 1000;
9031 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
9032 +       tsleep(&tv, 0, "dw3slp", tvtohz(&tv));
9033 +}
9034 +
9035 +uint32_t DWC_TIME(void)
9036 +{
9037 +       struct timeval tv;
9038 +
9039 +       microuptime(&tv);       // or getmicrouptime? (less precise, but faster)
9040 +       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
9041 +}
9042 +
9043 +
9044 +/* Timers */
9045 +
9046 +struct dwc_timer {
9047 +       struct callout t;
9048 +       char *name;
9049 +       dwc_spinlock_t *lock;
9050 +       dwc_timer_callback_t cb;
9051 +       void *data;
9052 +};
9053 +
9054 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
9055 +{
9056 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
9057 +
9058 +       if (!t) {
9059 +               DWC_ERROR("Cannot allocate memory for timer");
9060 +               return NULL;
9061 +       }
9062 +
9063 +       callout_init(&t->t);
9064 +
9065 +       t->name = DWC_STRDUP(name);
9066 +       if (!t->name) {
9067 +               DWC_ERROR("Cannot allocate memory for timer->name");
9068 +               goto no_name;
9069 +       }
9070 +
9071 +       t->lock = DWC_SPINLOCK_ALLOC();
9072 +       if (!t->lock) {
9073 +               DWC_ERROR("Cannot allocate memory for timer->lock");
9074 +               goto no_lock;
9075 +       }
9076 +
9077 +       t->cb = cb;
9078 +       t->data = data;
9079 +
9080 +       return t;
9081 +
9082 + no_lock:
9083 +       DWC_FREE(t->name);
9084 + no_name:
9085 +       DWC_FREE(t);
9086 +
9087 +       return NULL;
9088 +}
9089 +
9090 +void DWC_TIMER_FREE(dwc_timer_t *timer)
9091 +{
9092 +       callout_stop(&timer->t);
9093 +       DWC_SPINLOCK_FREE(timer->lock);
9094 +       DWC_FREE(timer->name);
9095 +       DWC_FREE(timer);
9096 +}
9097 +
9098 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
9099 +{
9100 +       struct timeval tv;
9101 +
9102 +       tv.tv_sec = time / 1000;
9103 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9104 +       callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
9105 +}
9106 +
9107 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
9108 +{
9109 +       callout_stop(&timer->t);
9110 +}
9111 +
9112 +
9113 +/* Wait Queues */
9114 +
9115 +struct dwc_waitq {
9116 +       struct simplelock lock;
9117 +       int abort;
9118 +};
9119 +
9120 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
9121 +{
9122 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
9123 +
9124 +       if (!wq) {
9125 +               DWC_ERROR("Cannot allocate memory for waitqueue");
9126 +               return NULL;
9127 +       }
9128 +
9129 +       simple_lock_init(&wq->lock);
9130 +       wq->abort = 0;
9131 +
9132 +       return wq;
9133 +}
9134 +
9135 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
9136 +{
9137 +       DWC_FREE(wq);
9138 +}
9139 +
9140 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
9141 +{
9142 +       int ipl;
9143 +       int result = 0;
9144 +
9145 +       simple_lock(&wq->lock);
9146 +       ipl = splbio();
9147 +
9148 +       /* Skip the sleep if already aborted or triggered */
9149 +       if (!wq->abort && !cond(data)) {
9150 +               splx(ipl);
9151 +               result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout
9152 +               ipl = splbio();
9153 +       }
9154 +
9155 +       if (result == 0) {                      // awoken
9156 +               if (wq->abort) {
9157 +                       wq->abort = 0;
9158 +                       result = -DWC_E_ABORT;
9159 +               } else {
9160 +                       result = 0;
9161 +               }
9162 +
9163 +               splx(ipl);
9164 +               simple_unlock(&wq->lock);
9165 +       } else {
9166 +               wq->abort = 0;
9167 +               splx(ipl);
9168 +               simple_unlock(&wq->lock);
9169 +
9170 +               if (result == ERESTART) {       // signaled - restart
9171 +                       result = -DWC_E_RESTART;
9172 +               } else {                        // signaled - must be EINTR
9173 +                       result = -DWC_E_ABORT;
9174 +               }
9175 +       }
9176 +
9177 +       return result;
9178 +}
9179 +
9180 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
9181 +                              void *data, int32_t msecs)
9182 +{
9183 +       struct timeval tv, tv1, tv2;
9184 +       int ipl;
9185 +       int result = 0;
9186 +
9187 +       tv.tv_sec = msecs / 1000;
9188 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
9189 +
9190 +       simple_lock(&wq->lock);
9191 +       ipl = splbio();
9192 +
9193 +       /* Skip the sleep if already aborted or triggered */
9194 +       if (!wq->abort && !cond(data)) {
9195 +               splx(ipl);
9196 +               getmicrouptime(&tv1);
9197 +               result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock);
9198 +               getmicrouptime(&tv2);
9199 +               ipl = splbio();
9200 +       }
9201 +
9202 +       if (result == 0) {                      // awoken
9203 +               if (wq->abort) {
9204 +                       wq->abort = 0;
9205 +                       splx(ipl);
9206 +                       simple_unlock(&wq->lock);
9207 +                       result = -DWC_E_ABORT;
9208 +               } else {
9209 +                       splx(ipl);
9210 +                       simple_unlock(&wq->lock);
9211 +
9212 +                       tv2.tv_usec -= tv1.tv_usec;
9213 +                       if (tv2.tv_usec < 0) {
9214 +                               tv2.tv_usec += 1000000;
9215 +                               tv2.tv_sec--;
9216 +                       }
9217 +
9218 +                       tv2.tv_sec -= tv1.tv_sec;
9219 +                       result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
9220 +                       result = msecs - result;
9221 +                       if (result <= 0)
9222 +                               result = 1;
9223 +               }
9224 +       } else {
9225 +               wq->abort = 0;
9226 +               splx(ipl);
9227 +               simple_unlock(&wq->lock);
9228 +
9229 +               if (result == ERESTART) {       // signaled - restart
9230 +                       result = -DWC_E_RESTART;
9231 +
9232 +               } else if (result == EINTR) {           // signaled - interrupt
9233 +                       result = -DWC_E_ABORT;
9234 +
9235 +               } else {                                // timed out
9236 +                       result = -DWC_E_TIMEOUT;
9237 +               }
9238 +       }
9239 +
9240 +       return result;
9241 +}
9242 +
9243 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
9244 +{
9245 +       wakeup(wq);
9246 +}
9247 +
9248 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
9249 +{
9250 +       int ipl;
9251 +
9252 +       simple_lock(&wq->lock);
9253 +       ipl = splbio();
9254 +       wq->abort = 1;
9255 +       wakeup(wq);
9256 +       splx(ipl);
9257 +       simple_unlock(&wq->lock);
9258 +}
9259 +
9260 +
9261 +/* Threading */
9262 +
9263 +struct dwc_thread {
9264 +       struct proc *proc;
9265 +       int abort;
9266 +};
9267 +
9268 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
9269 +{
9270 +       int retval;
9271 +       dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
9272 +
9273 +       if (!thread) {
9274 +               return NULL;
9275 +       }
9276 +
9277 +       thread->abort = 0;
9278 +       retval = kthread_create1((void (*)(void *))func, data, &thread->proc,
9279 +                                "%s", name);
9280 +       if (retval) {
9281 +               DWC_FREE(thread);
9282 +               return NULL;
9283 +       }
9284 +
9285 +       return thread;
9286 +}
9287 +
9288 +int DWC_THREAD_STOP(dwc_thread_t *thread)
9289 +{
9290 +       int retval;
9291 +
9292 +       thread->abort = 1;
9293 +       retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
9294 +
9295 +       if (retval == 0) {
9296 +               /* DWC_THREAD_EXIT() will free the thread struct */
9297 +               return 0;
9298 +       }
9299 +
9300 +       /* NOTE: We leak the thread struct if thread doesn't die */
9301 +
9302 +       if (retval == EWOULDBLOCK) {
9303 +               return -DWC_E_TIMEOUT;
9304 +       }
9305 +
9306 +       return -DWC_E_UNKNOWN;
9307 +}
9308 +
9309 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
9310 +{
9311 +       return thread->abort;
9312 +}
9313 +
9314 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
9315 +{
9316 +       wakeup(&thread->abort);
9317 +       DWC_FREE(thread);
9318 +       kthread_exit(0);
9319 +}
9320 +
9321 +/* tasklets
9322 + - Runs in interrupt context (cannot sleep)
9323 + - Each tasklet runs on a single CPU
9324 + - Different tasklets can be running simultaneously on different CPUs
9325 + [ On NetBSD there is no corresponding mechanism, drivers don't have bottom-
9326 +   halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ]
9327 + */
9328 +struct dwc_tasklet {
9329 +       dwc_tasklet_callback_t cb;
9330 +       void *data;
9331 +};
9332 +
9333 +static void tasklet_callback(void *data)
9334 +{
9335 +       dwc_tasklet_t *task = (dwc_tasklet_t *)data;
9336 +
9337 +       task->cb(task->data);
9338 +}
9339 +
9340 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
9341 +{
9342 +       dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
9343 +
9344 +       if (task) {
9345 +               task->cb = cb;
9346 +               task->data = data;
9347 +       } else {
9348 +               DWC_ERROR("Cannot allocate memory for tasklet");
9349 +       }
9350 +
9351 +       return task;
9352 +}
9353 +
9354 +void DWC_TASK_FREE(dwc_tasklet_t *task)
9355 +{
9356 +       DWC_FREE(task);
9357 +}
9358 +
9359 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
9360 +{
9361 +       tasklet_callback(task);
9362 +}
9363 +
9364 +
9365 +/* workqueues
9366 + - Runs in process context (can sleep)
9367 + */
9368 +typedef struct work_container {
9369 +       dwc_work_callback_t cb;
9370 +       void *data;
9371 +       dwc_workq_t *wq;
9372 +       char *name;
9373 +       int hz;
9374 +       struct work task;
9375 +} work_container_t;
9376 +
9377 +struct dwc_workq {
9378 +       struct workqueue *taskq;
9379 +       dwc_spinlock_t *lock;
9380 +       dwc_waitq_t *waitq;
9381 +       int pending;
9382 +       struct work_container *container;
9383 +};
9384 +
9385 +static void do_work(struct work *task, void *data)
9386 +{
9387 +       dwc_workq_t *wq = (dwc_workq_t *)data;
9388 +       work_container_t *container = wq->container;
9389 +       dwc_irqflags_t flags;
9390 +
9391 +       if (container->hz) {
9392 +               tsleep(container, 0, "dw3wrk", container->hz);
9393 +       }
9394 +
9395 +       container->cb(container->data);
9396 +       DWC_DEBUG("Work done: %s, container=%p", container->name, container);
9397 +
9398 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9399 +       if (container->name)
9400 +               DWC_FREE(container->name);
9401 +       DWC_FREE(container);
9402 +       wq->pending--;
9403 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9404 +       DWC_WAITQ_TRIGGER(wq->waitq);
9405 +}
9406 +
9407 +static int work_done(void *data)
9408 +{
9409 +       dwc_workq_t *workq = (dwc_workq_t *)data;
9410 +
9411 +       return workq->pending == 0;
9412 +}
9413 +
9414 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
9415 +{
9416 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
9417 +}
9418 +
9419 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
9420 +{
9421 +       int result;
9422 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
9423 +
9424 +       if (!wq) {
9425 +               DWC_ERROR("Cannot allocate memory for workqueue");
9426 +               return NULL;
9427 +       }
9428 +
9429 +       result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/,
9430 +                                 IPL_BIO, 0);
9431 +       if (result) {
9432 +               DWC_ERROR("Cannot create workqueue");
9433 +               goto no_taskq;
9434 +       }
9435 +
9436 +       wq->pending = 0;
9437 +
9438 +       wq->lock = DWC_SPINLOCK_ALLOC();
9439 +       if (!wq->lock) {
9440 +               DWC_ERROR("Cannot allocate memory for spinlock");
9441 +               goto no_lock;
9442 +       }
9443 +
9444 +       wq->waitq = DWC_WAITQ_ALLOC();
9445 +       if (!wq->waitq) {
9446 +               DWC_ERROR("Cannot allocate memory for waitqueue");
9447 +               goto no_waitq;
9448 +       }
9449 +
9450 +       return wq;
9451 +
9452 + no_waitq:
9453 +       DWC_SPINLOCK_FREE(wq->lock);
9454 + no_lock:
9455 +       workqueue_destroy(wq->taskq);
9456 + no_taskq:
9457 +       DWC_FREE(wq);
9458 +
9459 +       return NULL;
9460 +}
9461 +
9462 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
9463 +{
9464 +#ifdef DEBUG
9465 +       dwc_irqflags_t flags;
9466 +
9467 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9468 +
9469 +       if (wq->pending != 0) {
9470 +               struct work_container *container = wq->container;
9471 +
9472 +               DWC_ERROR("Destroying work queue with pending work");
9473 +
9474 +               if (container && container->name) {
9475 +                       DWC_ERROR("Work %s still pending", container->name);
9476 +               }
9477 +       }
9478 +
9479 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9480 +#endif
9481 +       DWC_WAITQ_FREE(wq->waitq);
9482 +       DWC_SPINLOCK_FREE(wq->lock);
9483 +       workqueue_destroy(wq->taskq);
9484 +       DWC_FREE(wq);
9485 +}
9486 +
9487 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
9488 +                       char *format, ...)
9489 +{
9490 +       dwc_irqflags_t flags;
9491 +       work_container_t *container;
9492 +       static char name[128];
9493 +       va_list args;
9494 +
9495 +       va_start(args, format);
9496 +       DWC_VSNPRINTF(name, 128, format, args);
9497 +       va_end(args);
9498 +
9499 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9500 +       wq->pending++;
9501 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9502 +       DWC_WAITQ_TRIGGER(wq->waitq);
9503 +
9504 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
9505 +       if (!container) {
9506 +               DWC_ERROR("Cannot allocate memory for container");
9507 +               return;
9508 +       }
9509 +
9510 +       container->name = DWC_STRDUP(name);
9511 +       if (!container->name) {
9512 +               DWC_ERROR("Cannot allocate memory for container->name");
9513 +               DWC_FREE(container);
9514 +               return;
9515 +       }
9516 +
9517 +       container->cb = cb;
9518 +       container->data = data;
9519 +       container->wq = wq;
9520 +       container->hz = 0;
9521 +       wq->container = container;
9522 +
9523 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9524 +       workqueue_enqueue(wq->taskq, &container->task);
9525 +}
9526 +
9527 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
9528 +                               void *data, uint32_t time, char *format, ...)
9529 +{
9530 +       dwc_irqflags_t flags;
9531 +       work_container_t *container;
9532 +       static char name[128];
9533 +       struct timeval tv;
9534 +       va_list args;
9535 +
9536 +       va_start(args, format);
9537 +       DWC_VSNPRINTF(name, 128, format, args);
9538 +       va_end(args);
9539 +
9540 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9541 +       wq->pending++;
9542 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9543 +       DWC_WAITQ_TRIGGER(wq->waitq);
9544 +
9545 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
9546 +       if (!container) {
9547 +               DWC_ERROR("Cannot allocate memory for container");
9548 +               return;
9549 +       }
9550 +
9551 +       container->name = DWC_STRDUP(name);
9552 +       if (!container->name) {
9553 +               DWC_ERROR("Cannot allocate memory for container->name");
9554 +               DWC_FREE(container);
9555 +               return;
9556 +       }
9557 +
9558 +       container->cb = cb;
9559 +       container->data = data;
9560 +       container->wq = wq;
9561 +       tv.tv_sec = time / 1000;
9562 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9563 +       container->hz = tvtohz(&tv);
9564 +       wq->container = container;
9565 +
9566 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9567 +       workqueue_enqueue(wq->taskq, &container->task);
9568 +}
9569 +
9570 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
9571 +{
9572 +       return wq->pending;
9573 +}
9574 diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.c b/drivers/usb/host/dwc_common_port/dwc_crypto.c
9575 new file mode 100644
9576 index 0000000..3b03532
9577 --- /dev/null
9578 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c
9579 @@ -0,0 +1,308 @@
9580 +/* =========================================================================
9581 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
9582 + * $Revision: #5 $
9583 + * $Date: 2010/09/28 $
9584 + * $Change: 1596182 $
9585 + *
9586 + * Synopsys Portability Library Software and documentation
9587 + * (hereinafter, "Software") is an Unsupported proprietary work of
9588 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9589 + * between Synopsys and you.
9590 + *
9591 + * The Software IS NOT an item of Licensed Software or Licensed Product
9592 + * under any End User Software License Agreement or Agreement for
9593 + * Licensed Product with Synopsys or any supplement thereto. You are
9594 + * permitted to use and redistribute this Software in source and binary
9595 + * forms, with or without modification, provided that redistributions
9596 + * of source code must retain this notice. You may not view, use,
9597 + * disclose, copy or distribute this file or any information contained
9598 + * herein except pursuant to this license grant from Synopsys. If you
9599 + * do not agree with this notice, including the disclaimer below, then
9600 + * you are not authorized to use the Software.
9601 + *
9602 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9603 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9604 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9605 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9606 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9607 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9608 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9609 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9610 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9611 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9612 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9613 + * DAMAGE.
9614 + * ========================================================================= */
9615 +
9616 +/** @file
9617 + * This file contains the WUSB cryptographic routines.
9618 + */
9619 +
9620 +#ifdef DWC_CRYPTOLIB
9621 +
9622 +#include "dwc_crypto.h"
9623 +#include "usb.h"
9624 +
9625 +#ifdef DEBUG
9626 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
9627 +{
9628 +       int i;
9629 +       DWC_PRINTF("%s: ", name);
9630 +       for (i=0; i<len; i++) {
9631 +               DWC_PRINTF("%02x ", bytes[i]);
9632 +       }
9633 +       DWC_PRINTF("\n");
9634 +}
9635 +#else
9636 +#define dump_bytes(x...)
9637 +#endif
9638 +
9639 +/* Display a block */
9640 +void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
9641 +{
9642 +#ifdef DWC_DEBUG_CRYPTO
9643 +       int i, blksize = 16;
9644 +
9645 +       DWC_DEBUG("%s", prefix);
9646 +
9647 +       if (suffix == NULL) {
9648 +               suffix = "\n";
9649 +               blksize = a;
9650 +       }
9651 +
9652 +       for (i = 0; i < blksize; i++)
9653 +               DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? "  " : " ");
9654 +       DWC_PRINT(suffix);
9655 +#endif
9656 +}
9657 +
9658 +/**
9659 + * Encrypts an array of bytes using the AES encryption engine.
9660 + * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
9661 + * in-place.
9662 + *
9663 + * @return  0 on success, negative error code on error.
9664 + */
9665 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
9666 +{
9667 +       u8 block_t[16];
9668 +       DWC_MEMSET(block_t, 0, 16);
9669 +
9670 +       return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
9671 +}
9672 +
9673 +/**
9674 + * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
9675 + * This function takes a data string and returns the encrypted CBC
9676 + * Counter-mode MIC.
9677 + *
9678 + * @param key     The 128-bit symmetric key.
9679 + * @param nonce   The CCM nonce.
9680 + * @param label   The unique 14-byte ASCII text label.
9681 + * @param bytes   The byte array to be encrypted.
9682 + * @param len     Length of the byte array.
9683 + * @param result  Byte array to receive the 8-byte encrypted MIC.
9684 + */
9685 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9686 +                 char *label, u8 *bytes, int len, u8 *result)
9687 +{
9688 +       u8 block_m[16];
9689 +       u8 block_x[16];
9690 +       u8 block_t[8];
9691 +       int idx, blkNum;
9692 +       u16 la = (u16)(len + 14);
9693 +
9694 +       /* Set the AES-128 key */
9695 +       //dwc_aes_setkey(tfm, key, 16);
9696 +
9697 +       /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
9698 +       block_m[0] = 0x59;
9699 +       for (idx = 0; idx < 13; idx++)
9700 +               block_m[idx + 1] = nonce[idx];
9701 +       block_m[14] = 0;
9702 +       block_m[15] = 0;
9703 +
9704 +       /* Produce the CBC IV */
9705 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
9706 +       show_block(block_m, "CBC IV in: ", "\n", 0);
9707 +       show_block(block_x, "CBC IV out:", "\n", 0);
9708 +
9709 +       /* Fill block B1 from l(a) = Blen + 14, and A */
9710 +       block_x[0] ^= (u8)(la >> 8);
9711 +       block_x[1] ^= (u8)la;
9712 +       for (idx = 0; idx < 14; idx++)
9713 +               block_x[idx + 2] ^= label[idx];
9714 +       show_block(block_x, "After xor: ", "b1\n", 16);
9715 +
9716 +       dwc_wusb_aes_encrypt(block_x, key, block_x);
9717 +       show_block(block_x, "After AES: ", "b1\n", 16);
9718 +
9719 +       idx = 0;
9720 +       blkNum = 0;
9721 +
9722 +       /* Fill remaining blocks with B */
9723 +       while (len-- > 0) {
9724 +               block_x[idx] ^= *bytes++;
9725 +               if (++idx >= 16) {
9726 +                       idx = 0;
9727 +                       show_block(block_x, "After xor: ", "\n", blkNum);
9728 +                       dwc_wusb_aes_encrypt(block_x, key, block_x);
9729 +                       show_block(block_x, "After AES: ", "\n", blkNum);
9730 +                       blkNum++;
9731 +               }
9732 +       }
9733 +
9734 +       /* Handle partial last block */
9735 +       if (idx > 0) {
9736 +               show_block(block_x, "After xor: ", "\n", blkNum);
9737 +               dwc_wusb_aes_encrypt(block_x, key, block_x);
9738 +               show_block(block_x, "After AES: ", "\n", blkNum);
9739 +       }
9740 +
9741 +       /* Save the MIC tag */
9742 +       DWC_MEMCPY(block_t, block_x, 8);
9743 +       show_block(block_t, "MIC tag  : ", NULL, 8);
9744 +
9745 +       /* Fill block A0 from flags = 0x01, N, and counter = 0 */
9746 +       block_m[0] = 0x01;
9747 +       block_m[14] = 0;
9748 +       block_m[15] = 0;
9749 +
9750 +       /* Encrypt the counter */
9751 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
9752 +       show_block(block_x, "CTR[MIC] : ", NULL, 8);
9753 +
9754 +       /* XOR with MIC tag */
9755 +       for (idx = 0; idx < 8; idx++) {
9756 +               block_t[idx] ^= block_x[idx];
9757 +       }
9758 +
9759 +       /* Return result to caller */
9760 +       DWC_MEMCPY(result, block_t, 8);
9761 +       show_block(result, "CCM-MIC  : ", NULL, 8);
9762 +
9763 +}
9764 +
9765 +/**
9766 + * The PRF function described in section 6.5 of the WUSB spec. This function
9767 + * concatenates MIC values returned from dwc_cmf() to create a value of
9768 + * the requested length.
9769 + *
9770 + * @param prf_len  Length of the PRF function in bits (64, 128, or 256).
9771 + * @param key, nonce, label, bytes, len  Same as for dwc_cmf().
9772 + * @param result   Byte array to receive the result.
9773 + */
9774 +void dwc_wusb_prf(int prf_len, u8 *key,
9775 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
9776 +{
9777 +       int i;
9778 +
9779 +       nonce[0] = 0;
9780 +       for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
9781 +               dwc_wusb_cmf(key, nonce, label, bytes, len, result);
9782 +               result += 8;
9783 +       }
9784 +}
9785 +
9786 +/**
9787 + * Fills in CCM Nonce per the WUSB spec.
9788 + *
9789 + * @param[in] haddr Host address.
9790 + * @param[in] daddr Device address.
9791 + * @param[in] tkid Session Key(PTK) identifier.
9792 + * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
9793 + */
9794 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9795 +                            uint8_t *nonce)
9796 +{
9797 +
9798 +       DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
9799 +
9800 +       DWC_MEMSET(&nonce[0], 0, 16);
9801 +
9802 +       DWC_MEMCPY(&nonce[6], tkid, 3);
9803 +       nonce[9] = daddr & 0xFF;
9804 +       nonce[10] = (daddr >> 8) & 0xFF;
9805 +       nonce[11] = haddr & 0xFF;
9806 +       nonce[12] = (haddr >> 8) & 0xFF;
9807 +
9808 +       dump_bytes("CCM nonce", nonce, 16);
9809 +}
9810 +
9811 +/**
9812 + * Generates a 16-byte cryptographic-grade random number for the Host/Device
9813 + * Nonce.
9814 + */
9815 +void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
9816 +{
9817 +       uint8_t inonce[16];
9818 +       uint32_t temp[4];
9819 +
9820 +       /* Fill in the Nonce */
9821 +       DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
9822 +       inonce[9] = addr & 0xFF;
9823 +       inonce[10] = (addr >> 8) & 0xFF;
9824 +       inonce[11] = inonce[9];
9825 +       inonce[12] = inonce[10];
9826 +
9827 +       /* Collect "randomness samples" */
9828 +       DWC_RANDOM_BYTES((uint8_t *)temp, 16);
9829 +
9830 +       dwc_wusb_prf_128((uint8_t *)temp, nonce,
9831 +                        "Random Numbers", (uint8_t *)temp, sizeof(temp),
9832 +                        nonce);
9833 +}
9834 +
9835 +/**
9836 + * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
9837 + * WUSB spec.
9838 + *
9839 + * @param[in] ccm_nonce Pointer to CCM Nonce.
9840 + * @param[in] mk Master Key to derive the session from
9841 + * @param[in] hnonce Pointer to Host Nonce.
9842 + * @param[in] dnonce Pointer to Device Nonce.
9843 + * @param[out] kck Pointer to where the KCK output is to be written.
9844 + * @param[out] ptk Pointer to where the PTK output is to be written.
9845 + */
9846 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
9847 +                     uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
9848 +{
9849 +       uint8_t idata[32];
9850 +       uint8_t odata[32];
9851 +
9852 +       dump_bytes("ck", mk, 16);
9853 +       dump_bytes("hnonce", hnonce, 16);
9854 +       dump_bytes("dnonce", dnonce, 16);
9855 +
9856 +       /* The data is the HNonce and DNonce concatenated */
9857 +       DWC_MEMCPY(&idata[0], hnonce, 16);
9858 +       DWC_MEMCPY(&idata[16], dnonce, 16);
9859 +
9860 +       dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
9861 +
9862 +       /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
9863 +       DWC_MEMCPY(kck, &odata[0], 16);
9864 +       DWC_MEMCPY(ptk, &odata[16], 16);
9865 +
9866 +       dump_bytes("kck", kck, 16);
9867 +       dump_bytes("ptk", ptk, 16);
9868 +}
9869 +
9870 +/**
9871 + * Generates the Message Integrity Code over the Handshake data per the
9872 + * WUSB spec.
9873 + *
9874 + * @param ccm_nonce Pointer to CCM Nonce.
9875 + * @param kck   Pointer to Key Confirmation Key.
9876 + * @param data  Pointer to Handshake data to be checked.
9877 + * @param mic   Pointer to where the MIC output is to be written.
9878 + */
9879 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
9880 +                     uint8_t *data, uint8_t *mic)
9881 +{
9882 +
9883 +       dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
9884 +                       data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
9885 +}
9886 +
9887 +#endif /* DWC_CRYPTOLIB */
9888 diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.h b/drivers/usb/host/dwc_common_port/dwc_crypto.h
9889 new file mode 100644
9890 index 0000000..26fcddc
9891 --- /dev/null
9892 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h
9893 @@ -0,0 +1,111 @@
9894 +/* =========================================================================
9895 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $
9896 + * $Revision: #3 $
9897 + * $Date: 2010/09/28 $
9898 + * $Change: 1596182 $
9899 + *
9900 + * Synopsys Portability Library Software and documentation
9901 + * (hereinafter, "Software") is an Unsupported proprietary work of
9902 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9903 + * between Synopsys and you.
9904 + *
9905 + * The Software IS NOT an item of Licensed Software or Licensed Product
9906 + * under any End User Software License Agreement or Agreement for
9907 + * Licensed Product with Synopsys or any supplement thereto. You are
9908 + * permitted to use and redistribute this Software in source and binary
9909 + * forms, with or without modification, provided that redistributions
9910 + * of source code must retain this notice. You may not view, use,
9911 + * disclose, copy or distribute this file or any information contained
9912 + * herein except pursuant to this license grant from Synopsys. If you
9913 + * do not agree with this notice, including the disclaimer below, then
9914 + * you are not authorized to use the Software.
9915 + *
9916 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9917 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9918 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9919 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9920 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9921 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9922 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9923 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9924 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9925 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9926 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9927 + * DAMAGE.
9928 + * ========================================================================= */
9929 +
9930 +#ifndef _DWC_CRYPTO_H_
9931 +#define _DWC_CRYPTO_H_
9932 +
9933 +#ifdef __cplusplus
9934 +extern "C" {
9935 +#endif
9936 +
9937 +/** @file
9938 + *
9939 + * This file contains declarations for the WUSB Cryptographic routines as
9940 + * defined in the WUSB spec.  They are only to be used internally by the DWC UWB
9941 + * modules.
9942 + */
9943 +
9944 +#include "dwc_os.h"
9945 +
9946 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);
9947 +
9948 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9949 +                 char *label, u8 *bytes, int len, u8 *result);
9950 +void dwc_wusb_prf(int prf_len, u8 *key,
9951 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result);
9952 +
9953 +/**
9954 + * The PRF-64 function described in section 6.5 of the WUSB spec.
9955 + *
9956 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9957 + */
9958 +static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,
9959 +                                  char *label, u8 *bytes, int len, u8 *result)
9960 +{
9961 +       dwc_wusb_prf(64, key, nonce, label, bytes, len, result);
9962 +}
9963 +
9964 +/**
9965 + * The PRF-128 function described in section 6.5 of the WUSB spec.
9966 + *
9967 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9968 + */
9969 +static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,
9970 +                                   char *label, u8 *bytes, int len, u8 *result)
9971 +{
9972 +       dwc_wusb_prf(128, key, nonce, label, bytes, len, result);
9973 +}
9974 +
9975 +/**
9976 + * The PRF-256 function described in section 6.5 of the WUSB spec.
9977 + *
9978 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9979 + */
9980 +static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,
9981 +                                   char *label, u8 *bytes, int len, u8 *result)
9982 +{
9983 +       dwc_wusb_prf(256, key, nonce, label, bytes, len, result);
9984 +}
9985 +
9986 +
9987 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9988 +                              uint8_t *nonce);
9989 +void dwc_wusb_gen_nonce(uint16_t addr,
9990 +                         uint8_t *nonce);
9991 +
9992 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,
9993 +                       uint8_t *hnonce, uint8_t *dnonce,
9994 +                       uint8_t *kck, uint8_t *ptk);
9995 +
9996 +
9997 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t
9998 +                       *kck, uint8_t *data, uint8_t *mic);
9999 +
10000 +#ifdef __cplusplus
10001 +}
10002 +#endif
10003 +
10004 +#endif /* _DWC_CRYPTO_H_ */
10005 diff --git a/drivers/usb/host/dwc_common_port/dwc_dh.c b/drivers/usb/host/dwc_common_port/dwc_dh.c
10006 new file mode 100644
10007 index 0000000..997f753
10008 --- /dev/null
10009 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.c
10010 @@ -0,0 +1,291 @@
10011 +/* =========================================================================
10012 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
10013 + * $Revision: #3 $
10014 + * $Date: 2010/09/28 $
10015 + * $Change: 1596182 $
10016 + *
10017 + * Synopsys Portability Library Software and documentation
10018 + * (hereinafter, "Software") is an Unsupported proprietary work of
10019 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
10020 + * between Synopsys and you.
10021 + *
10022 + * The Software IS NOT an item of Licensed Software or Licensed Product
10023 + * under any End User Software License Agreement or Agreement for
10024 + * Licensed Product with Synopsys or any supplement thereto. You are
10025 + * permitted to use and redistribute this Software in source and binary
10026 + * forms, with or without modification, provided that redistributions
10027 + * of source code must retain this notice. You may not view, use,
10028 + * disclose, copy or distribute this file or any information contained
10029 + * herein except pursuant to this license grant from Synopsys. If you
10030 + * do not agree with this notice, including the disclaimer below, then
10031 + * you are not authorized to use the Software.
10032 + *
10033 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
10034 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10035 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
10036 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
10037 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10038 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10039 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10040 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
10041 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10042 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
10043 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
10044 + * DAMAGE.
10045 + * ========================================================================= */
10046 +#ifdef DWC_CRYPTOLIB
10047 +
10048 +#ifndef CONFIG_MACH_IPMATE
10049 +
10050 +#include "dwc_dh.h"
10051 +#include "dwc_modpow.h"
10052 +
10053 +#ifdef DEBUG
10054 +/* This function prints out a buffer in the format described in the Association
10055 + * Model specification. */
10056 +static void dh_dump(char *str, void *_num, int len)
10057 +{
10058 +       uint8_t *num = _num;
10059 +       int i;
10060 +       DWC_PRINTF("%s\n", str);
10061 +       for (i = 0; i < len; i ++) {
10062 +               DWC_PRINTF("%02x", num[i]);
10063 +               if (((i + 1) % 2) == 0) DWC_PRINTF(" ");
10064 +               if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
10065 +       }
10066 +
10067 +       DWC_PRINTF("\n");
10068 +}
10069 +#else
10070 +#define dh_dump(_x...) do {; } while(0)
10071 +#endif
10072 +
10073 +/* Constant g value */
10074 +static __u32 dh_g[] = {
10075 +       0x02000000,
10076 +};
10077 +
10078 +/* Constant p value */
10079 +static __u32 dh_p[] = {
10080 +       0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
10081 +       0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
10082 +       0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
10083 +       0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
10084 +       0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
10085 +       0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
10086 +       0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
10087 +       0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
10088 +       0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
10089 +       0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
10090 +       0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
10091 +       0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
10092 +};
10093 +
10094 +static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
10095 +{
10096 +       uint8_t *in = _in;
10097 +       uint8_t *out = _out;
10098 +       int i;
10099 +       for (i=0; i<len; i++) {
10100 +               out[i] = in[len-1-i];
10101 +       }
10102 +}
10103 +
10104 +/* Computes the modular exponentiation (num^exp % mod).  num, exp, and mod are
10105 + * big endian numbers of size len, in bytes.  Each len value must be a multiple
10106 + * of 4. */
10107 +int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10108 +                 void *exp, uint32_t exp_len,
10109 +                 void *mod, uint32_t mod_len,
10110 +                 void *out)
10111 +{
10112 +       /* modpow() takes little endian numbers.  AM uses big-endian.  This
10113 +        * function swaps bytes of numbers before passing onto modpow. */
10114 +
10115 +       int retval = 0;
10116 +       uint32_t *result;
10117 +
10118 +       uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);
10119 +       uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);
10120 +       uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);
10121 +
10122 +       dh_swap_bytes(num, &bignum_num[1], num_len);
10123 +       bignum_num[0] = num_len / 4;
10124 +
10125 +       dh_swap_bytes(exp, &bignum_exp[1], exp_len);
10126 +       bignum_exp[0] = exp_len / 4;
10127 +
10128 +       dh_swap_bytes(mod, &bignum_mod[1], mod_len);
10129 +       bignum_mod[0] = mod_len / 4;
10130 +
10131 +       result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
10132 +       if (!result) {
10133 +               retval = -1;
10134 +               goto dh_modpow_nomem;
10135 +       }
10136 +
10137 +       dh_swap_bytes(&result[1], out, result[0] * 4);
10138 +       dwc_free(mem_ctx, result);
10139 +
10140 + dh_modpow_nomem:
10141 +       dwc_free(mem_ctx, bignum_num);
10142 +       dwc_free(mem_ctx, bignum_exp);
10143 +       dwc_free(mem_ctx, bignum_mod);
10144 +       return retval;
10145 +}
10146 +
10147 +
10148 +int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
10149 +{
10150 +       int retval;
10151 +       uint8_t m3[385];
10152 +
10153 +#ifndef DH_TEST_VECTORS
10154 +       DWC_RANDOM_BYTES(exp, 32);
10155 +#endif
10156 +
10157 +       /* Compute the pkd */
10158 +       if ((retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
10159 +                                   exp, 32,
10160 +                                   dh_p, 384, pk))) {
10161 +               return retval;
10162 +       }
10163 +
10164 +       m3[384] = nd;
10165 +       DWC_MEMCPY(&m3[0], pk, 384);
10166 +       DWC_SHA256(m3, 385, hash);
10167 +
10168 +       dh_dump("PK", pk, 384);
10169 +       dh_dump("SHA-256(M3)", hash, 32);
10170 +       return 0;
10171 +}
10172 +
10173 +int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10174 +                      uint8_t *exp, int is_host,
10175 +                      char *dd, uint8_t *ck, uint8_t *kdk)
10176 +{
10177 +       int retval;
10178 +       uint8_t mv[784];
10179 +       uint8_t sha_result[32];
10180 +       uint8_t dhkey[384];
10181 +       uint8_t shared_secret[384];
10182 +       char *message;
10183 +       uint32_t vd;
10184 +
10185 +       uint8_t *pk;
10186 +
10187 +       if (is_host) {
10188 +               pk = pkd;
10189 +       }
10190 +       else {
10191 +               pk = pkh;
10192 +       }
10193 +
10194 +       if ((retval = dwc_dh_modpow(mem_ctx, pk, 384,
10195 +                                   exp, 32,
10196 +                                   dh_p, 384, shared_secret))) {
10197 +               return retval;
10198 +       }
10199 +       dh_dump("Shared Secret", shared_secret, 384);
10200 +
10201 +       DWC_SHA256(shared_secret, 384, dhkey);
10202 +       dh_dump("DHKEY", dhkey, 384);
10203 +
10204 +       DWC_MEMCPY(&mv[0], pkd, 384);
10205 +       DWC_MEMCPY(&mv[384], pkh, 384);
10206 +       DWC_MEMCPY(&mv[768], "displayed digest", 16);
10207 +       dh_dump("MV", mv, 784);
10208 +
10209 +       DWC_SHA256(mv, 784, sha_result);
10210 +       dh_dump("SHA-256(MV)", sha_result, 32);
10211 +       dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
10212 +
10213 +       dh_swap_bytes(sha_result, &vd, 4);
10214 +#ifdef DEBUG
10215 +       DWC_PRINTF("Vd (decimal) = %d\n", vd);
10216 +#endif
10217 +
10218 +       switch (nd) {
10219 +       case 2:
10220 +               vd = vd % 100;
10221 +               DWC_SPRINTF(dd, "%02d", vd);
10222 +               break;
10223 +       case 3:
10224 +               vd = vd % 1000;
10225 +               DWC_SPRINTF(dd, "%03d", vd);
10226 +               break;
10227 +       case 4:
10228 +               vd = vd % 10000;
10229 +               DWC_SPRINTF(dd, "%04d", vd);
10230 +               break;
10231 +       }
10232 +#ifdef DEBUG
10233 +       DWC_PRINTF("Display Digits: %s\n", dd);
10234 +#endif
10235 +
10236 +       message = "connection key";
10237 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
10238 +       dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
10239 +       DWC_MEMCPY(ck, sha_result, 16);
10240 +
10241 +       message = "key derivation key";
10242 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
10243 +       dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
10244 +       DWC_MEMCPY(kdk, sha_result, 32);
10245 +
10246 +       return 0;
10247 +}
10248 +
10249 +
10250 +#ifdef DH_TEST_VECTORS
10251 +
10252 +static __u8 dh_a[] = {
10253 +       0x44, 0x00, 0x51, 0xd6,
10254 +       0xf0, 0xb5, 0x5e, 0xa9,
10255 +       0x67, 0xab, 0x31, 0xc6,
10256 +       0x8a, 0x8b, 0x5e, 0x37,
10257 +       0xd9, 0x10, 0xda, 0xe0,
10258 +       0xe2, 0xd4, 0x59, 0xa4,
10259 +       0x86, 0x45, 0x9c, 0xaa,
10260 +       0xdf, 0x36, 0x75, 0x16,
10261 +};
10262 +
10263 +static __u8 dh_b[] = {
10264 +       0x5d, 0xae, 0xc7, 0x86,
10265 +       0x79, 0x80, 0xa3, 0x24,
10266 +       0x8c, 0xe3, 0x57, 0x8f,
10267 +       0xc7, 0x5f, 0x1b, 0x0f,
10268 +       0x2d, 0xf8, 0x9d, 0x30,
10269 +       0x6f, 0xa4, 0x52, 0xcd,
10270 +       0xe0, 0x7a, 0x04, 0x8a,
10271 +       0xde, 0xd9, 0x26, 0x56,
10272 +};
10273 +
10274 +void dwc_run_dh_test_vectors(void *mem_ctx)
10275 +{
10276 +       uint8_t pkd[384];
10277 +       uint8_t pkh[384];
10278 +       uint8_t hashd[32];
10279 +       uint8_t hashh[32];
10280 +       uint8_t ck[16];
10281 +       uint8_t kdk[32];
10282 +       char dd[5];
10283 +
10284 +       DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
10285 +
10286 +       /* compute the PKd and SHA-256(PKd || Nd) */
10287 +       DWC_PRINTF("Computing PKd\n");
10288 +       dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);
10289 +
10290 +       /* compute the PKd and SHA-256(PKh || Nd) */
10291 +       DWC_PRINTF("Computing PKh\n");
10292 +       dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);
10293 +
10294 +       /* compute the dhkey */
10295 +       dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
10296 +}
10297 +#endif /* DH_TEST_VECTORS */
10298 +
10299 +#endif /* !CONFIG_MACH_IPMATE */
10300 +
10301 +#endif /* DWC_CRYPTOLIB */
10302 diff --git a/drivers/usb/host/dwc_common_port/dwc_dh.h b/drivers/usb/host/dwc_common_port/dwc_dh.h
10303 new file mode 100644
10304 index 0000000..25c1cc0
10305 --- /dev/null
10306 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.h
10307 @@ -0,0 +1,106 @@
10308 +/* =========================================================================
10309 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $
10310 + * $Revision: #4 $
10311 + * $Date: 2010/09/28 $
10312 + * $Change: 1596182 $
10313 + *
10314 + * Synopsys Portability Library Software and documentation
10315 + * (hereinafter, "Software") is an Unsupported proprietary work of
10316 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
10317 + * between Synopsys and you.
10318 + *
10319 + * The Software IS NOT an item of Licensed Software or Licensed Product
10320 + * under any End User Software License Agreement or Agreement for
10321 + * Licensed Product with Synopsys or any supplement thereto. You are
10322 + * permitted to use and redistribute this Software in source and binary
10323 + * forms, with or without modification, provided that redistributions
10324 + * of source code must retain this notice. You may not view, use,
10325 + * disclose, copy or distribute this file or any information contained
10326 + * herein except pursuant to this license grant from Synopsys. If you
10327 + * do not agree with this notice, including the disclaimer below, then
10328 + * you are not authorized to use the Software.
10329 + *
10330 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
10331 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10332 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
10333 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
10334 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10335 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10336 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10337 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
10338 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10339 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
10340 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
10341 + * DAMAGE.
10342 + * ========================================================================= */
10343 +#ifndef _DWC_DH_H_
10344 +#define _DWC_DH_H_
10345 +
10346 +#ifdef __cplusplus
10347 +extern "C" {
10348 +#endif
10349 +
10350 +#include "dwc_os.h"
10351 +
10352 +/** @file
10353 + *
10354 + * This file defines the common functions on device and host for performing
10355 + * numeric association as defined in the WUSB spec.  They are only to be
10356 + * used internally by the DWC UWB modules. */
10357 +
10358 +extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);
10359 +extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,
10360 +                             uint8_t *key, uint32_t keylen,
10361 +                             uint8_t *out);
10362 +extern int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10363 +                        void *exp, uint32_t exp_len,
10364 +                        void *mod, uint32_t mod_len,
10365 +                        void *out);
10366 +
10367 +/** Computes PKD or PKH, and SHA-256(PKd || Nd)
10368 + *
10369 + * PK = g^exp mod p.
10370 + *
10371 + * Input:
10372 + * Nd = Number of digits on the device.
10373 + *
10374 + * Output:
10375 + * exp = A 32-byte buffer to be filled with a randomly generated number.
10376 + *       used as either A or B.
10377 + * pk = A 384-byte buffer to be filled with the PKH or PKD.
10378 + * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).
10379 + */
10380 +extern int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);
10381 +
10382 +/** Computes the DHKEY, and VD.
10383 + *
10384 + * If called from host, then it will comput DHKEY=PKD^exp % p.
10385 + * If called from device, then it will comput DHKEY=PKH^exp % p.
10386 + *
10387 + * Input:
10388 + * pkd = The PKD value.
10389 + * pkh = The PKH value.
10390 + * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.
10391 + * is_host = Set to non zero if a WUSB host is calling this function.
10392 + *
10393 + * Output:
10394 +
10395 + * dd = A pointer to an buffer to be set to the displayed digits string to be shown
10396 + *      to the user.  This buffer should be at 5 bytes long to hold 4 digits plus a
10397 + *      null termination character.  This buffer can be used directly for display.
10398 + * ck = A 16-byte buffer to be filled with the CK.
10399 + * kdk = A 32-byte buffer to be filled with the KDK.
10400 + */
10401 +extern int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10402 +                             uint8_t *exp, int is_host,
10403 +                             char *dd, uint8_t *ck, uint8_t *kdk);
10404 +
10405 +#ifdef DH_TEST_VECTORS
10406 +extern void dwc_run_dh_test_vectors(void);
10407 +#endif
10408 +
10409 +#ifdef __cplusplus
10410 +}
10411 +#endif
10412 +
10413 +#endif /* _DWC_DH_H_ */
10414 diff --git a/drivers/usb/host/dwc_common_port/dwc_list.h b/drivers/usb/host/dwc_common_port/dwc_list.h
10415 new file mode 100644
10416 index 0000000..89cc325
10417 --- /dev/null
10418 +++ b/drivers/usb/host/dwc_common_port/dwc_list.h
10419 @@ -0,0 +1,594 @@
10420 +/*     $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $       */
10421 +/*     $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $       */
10422 +
10423 +/*
10424 + * Copyright (c) 1991, 1993
10425 + *     The Regents of the University of California.  All rights reserved.
10426 + *
10427 + * Redistribution and use in source and binary forms, with or without
10428 + * modification, are permitted provided that the following conditions
10429 + * are met:
10430 + * 1. Redistributions of source code must retain the above copyright
10431 + *    notice, this list of conditions and the following disclaimer.
10432 + * 2. Redistributions in binary form must reproduce the above copyright
10433 + *    notice, this list of conditions and the following disclaimer in the
10434 + *    documentation and/or other materials provided with the distribution.
10435 + * 3. Neither the name of the University nor the names of its contributors
10436 + *    may be used to endorse or promote products derived from this software
10437 + *    without specific prior written permission.
10438 + *
10439 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
10440 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10441 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10442 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
10443 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10444 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10445 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10446 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10447 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10448 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10449 + * SUCH DAMAGE.
10450 + *
10451 + *     @(#)queue.h     8.5 (Berkeley) 8/20/94
10452 + */
10453 +
10454 +#ifndef _DWC_LIST_H_
10455 +#define _DWC_LIST_H_
10456 +
10457 +#ifdef __cplusplus
10458 +extern "C" {
10459 +#endif
10460 +
10461 +/** @file
10462 + *
10463 + * This file defines linked list operations.  It is derived from BSD with
10464 + * only the MACRO names being prefixed with DWC_.  This is because a few of
10465 + * these names conflict with those on Linux.  For documentation on use, see the
10466 + * inline comments in the source code.  The original license for this source
10467 + * code applies and is preserved in the dwc_list.h source file.
10468 + */
10469 +
10470 +/*
10471 + * This file defines five types of data structures: singly-linked lists,
10472 + * lists, simple queues, tail queues, and circular queues.
10473 + *
10474 + *
10475 + * A singly-linked list is headed by a single forward pointer. The elements
10476 + * are singly linked for minimum space and pointer manipulation overhead at
10477 + * the expense of O(n) removal for arbitrary elements. New elements can be
10478 + * added to the list after an existing element or at the head of the list.
10479 + * Elements being removed from the head of the list should use the explicit
10480 + * macro for this purpose for optimum efficiency. A singly-linked list may
10481 + * only be traversed in the forward direction.  Singly-linked lists are ideal
10482 + * for applications with large datasets and few or no removals or for
10483 + * implementing a LIFO queue.
10484 + *
10485 + * A list is headed by a single forward pointer (or an array of forward
10486 + * pointers for a hash table header). The elements are doubly linked
10487 + * so that an arbitrary element can be removed without a need to
10488 + * traverse the list. New elements can be added to the list before
10489 + * or after an existing element or at the head of the list. A list
10490 + * may only be traversed in the forward direction.
10491 + *
10492 + * A simple queue is headed by a pair of pointers, one the head of the
10493 + * list and the other to the tail of the list. The elements are singly
10494 + * linked to save space, so elements can only be removed from the
10495 + * head of the list. New elements can be added to the list before or after
10496 + * an existing element, at the head of the list, or at the end of the
10497 + * list. A simple queue may only be traversed in the forward direction.
10498 + *
10499 + * A tail queue is headed by a pair of pointers, one to the head of the
10500 + * list and the other to the tail of the list. The elements are doubly
10501 + * linked so that an arbitrary element can be removed without a need to
10502 + * traverse the list. New elements can be added to the list before or
10503 + * after an existing element, at the head of the list, or at the end of
10504 + * the list. A tail queue may be traversed in either direction.
10505 + *
10506 + * A circle queue is headed by a pair of pointers, one to the head of the
10507 + * list and the other to the tail of the list. The elements are doubly
10508 + * linked so that an arbitrary element can be removed without a need to
10509 + * traverse the list. New elements can be added to the list before or after
10510 + * an existing element, at the head of the list, or at the end of the list.
10511 + * A circle queue may be traversed in either direction, but has a more
10512 + * complex end of list detection.
10513 + *
10514 + * For details on the use of these macros, see the queue(3) manual page.
10515 + */
10516 +
10517 +/*
10518 + * Double-linked List.
10519 + */
10520 +
10521 +typedef struct dwc_list_link {
10522 +       struct dwc_list_link *next;
10523 +       struct dwc_list_link *prev;
10524 +} dwc_list_link_t;
10525 +
10526 +#define DWC_LIST_INIT(link) do {       \
10527 +       (link)->next = (link);          \
10528 +       (link)->prev = (link);          \
10529 +} while (0)
10530 +
10531 +#define DWC_LIST_FIRST(link)   ((link)->next)
10532 +#define DWC_LIST_LAST(link)    ((link)->prev)
10533 +#define DWC_LIST_END(link)     (link)
10534 +#define DWC_LIST_NEXT(link)    ((link)->next)
10535 +#define DWC_LIST_PREV(link)    ((link)->prev)
10536 +#define DWC_LIST_EMPTY(link)   \
10537 +       (DWC_LIST_FIRST(link) == DWC_LIST_END(link))
10538 +#define DWC_LIST_ENTRY(link, type, field)                      \
10539 +       (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field))
10540 +
10541 +#if 0
10542 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
10543 +       (link)->next = (list)->next;                            \
10544 +       (link)->prev = (list);                                  \
10545 +       (list)->next->prev = (link);                            \
10546 +       (list)->next = (link);                                  \
10547 +} while (0)
10548 +
10549 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
10550 +       (link)->next = (list);                                  \
10551 +       (link)->prev = (list)->prev;                            \
10552 +       (list)->prev->next = (link);                            \
10553 +       (list)->prev = (link);                                  \
10554 +} while (0)
10555 +#else
10556 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
10557 +       dwc_list_link_t *__next__ = (list)->next;               \
10558 +       __next__->prev = (link);                                \
10559 +       (link)->next = __next__;                                \
10560 +       (link)->prev = (list);                                  \
10561 +       (list)->next = (link);                                  \
10562 +} while (0)
10563 +
10564 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
10565 +       dwc_list_link_t *__prev__ = (list)->prev;               \
10566 +       (list)->prev = (link);                                  \
10567 +       (link)->next = (list);                                  \
10568 +       (link)->prev = __prev__;                                \
10569 +       __prev__->next = (link);                                \
10570 +} while (0)
10571 +#endif
10572 +
10573 +#if 0
10574 +static inline void __list_add(struct list_head *new,
10575 +                              struct list_head *prev,
10576 +                              struct list_head *next)
10577 +{
10578 +        next->prev = new;
10579 +        new->next = next;
10580 +        new->prev = prev;
10581 +        prev->next = new;
10582 +}
10583 +
10584 +static inline void list_add(struct list_head *new, struct list_head *head)
10585 +{
10586 +        __list_add(new, head, head->next);
10587 +}
10588 +
10589 +static inline void list_add_tail(struct list_head *new, struct list_head *head)
10590 +{
10591 +        __list_add(new, head->prev, head);
10592 +}
10593 +
10594 +static inline void __list_del(struct list_head * prev, struct list_head * next)
10595 +{
10596 +        next->prev = prev;
10597 +        prev->next = next;
10598 +}
10599 +
10600 +static inline void list_del(struct list_head *entry)
10601 +{
10602 +        __list_del(entry->prev, entry->next);
10603 +        entry->next = LIST_POISON1;
10604 +        entry->prev = LIST_POISON2;
10605 +}
10606 +#endif
10607 +
10608 +#define DWC_LIST_REMOVE(link) do {                             \
10609 +       (link)->next->prev = (link)->prev;                      \
10610 +       (link)->prev->next = (link)->next;                      \
10611 +} while (0)
10612 +
10613 +#define DWC_LIST_REMOVE_INIT(link) do {                                \
10614 +       DWC_LIST_REMOVE(link);                                  \
10615 +       DWC_LIST_INIT(link);                                    \
10616 +} while (0)
10617 +
10618 +#define DWC_LIST_MOVE_HEAD(list, link) do {                    \
10619 +       DWC_LIST_REMOVE(link);                                  \
10620 +       DWC_LIST_INSERT_HEAD(list, link);                       \
10621 +} while (0)
10622 +
10623 +#define DWC_LIST_MOVE_TAIL(list, link) do {                    \
10624 +       DWC_LIST_REMOVE(link);                                  \
10625 +       DWC_LIST_INSERT_TAIL(list, link);                       \
10626 +} while (0)
10627 +
10628 +#define DWC_LIST_FOREACH(var, list)                            \
10629 +       for((var) = DWC_LIST_FIRST(list);                       \
10630 +           (var) != DWC_LIST_END(list);                        \
10631 +           (var) = DWC_LIST_NEXT(var))
10632 +
10633 +#define DWC_LIST_FOREACH_SAFE(var, var2, list)                 \
10634 +       for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var);  \
10635 +           (var) != DWC_LIST_END(list);                        \
10636 +           (var) = (var2), (var2) = DWC_LIST_NEXT(var2))
10637 +
10638 +#define DWC_LIST_FOREACH_REVERSE(var, list)                    \
10639 +       for((var) = DWC_LIST_LAST(list);                        \
10640 +           (var) != DWC_LIST_END(list);                        \
10641 +           (var) = DWC_LIST_PREV(var))
10642 +
10643 +/*
10644 + * Singly-linked List definitions.
10645 + */
10646 +#define DWC_SLIST_HEAD(name, type)                                     \
10647 +struct name {                                                          \
10648 +       struct type *slh_first; /* first element */                     \
10649 +}
10650 +
10651 +#define DWC_SLIST_HEAD_INITIALIZER(head)                               \
10652 +       { NULL }
10653 +
10654 +#define DWC_SLIST_ENTRY(type)                                          \
10655 +struct {                                                               \
10656 +       struct type *sle_next;  /* next element */                      \
10657 +}
10658 +
10659 +/*
10660 + * Singly-linked List access methods.
10661 + */
10662 +#define DWC_SLIST_FIRST(head)  ((head)->slh_first)
10663 +#define DWC_SLIST_END(head)            NULL
10664 +#define DWC_SLIST_EMPTY(head)  (SLIST_FIRST(head) == SLIST_END(head))
10665 +#define DWC_SLIST_NEXT(elm, field)     ((elm)->field.sle_next)
10666 +
10667 +#define DWC_SLIST_FOREACH(var, head, field)                            \
10668 +       for((var) = SLIST_FIRST(head);                                  \
10669 +           (var) != SLIST_END(head);                                   \
10670 +           (var) = SLIST_NEXT(var, field))
10671 +
10672 +#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field)              \
10673 +       for((varp) = &SLIST_FIRST((head));                              \
10674 +           ((var) = *(varp)) != SLIST_END(head);                       \
10675 +           (varp) = &SLIST_NEXT((var), field))
10676 +
10677 +/*
10678 + * Singly-linked List functions.
10679 + */
10680 +#define DWC_SLIST_INIT(head) {                                         \
10681 +       SLIST_FIRST(head) = SLIST_END(head);                            \
10682 +}
10683 +
10684 +#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do {              \
10685 +       (elm)->field.sle_next = (slistelm)->field.sle_next;             \
10686 +       (slistelm)->field.sle_next = (elm);                             \
10687 +} while (0)
10688 +
10689 +#define DWC_SLIST_INSERT_HEAD(head, elm, field) do {                   \
10690 +       (elm)->field.sle_next = (head)->slh_first;                      \
10691 +       (head)->slh_first = (elm);                                      \
10692 +} while (0)
10693 +
10694 +#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do {                   \
10695 +       (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
10696 +} while (0)
10697 +
10698 +#define DWC_SLIST_REMOVE_HEAD(head, field) do {                                \
10699 +       (head)->slh_first = (head)->slh_first->field.sle_next;          \
10700 +} while (0)
10701 +
10702 +#define DWC_SLIST_REMOVE(head, elm, type, field) do {                  \
10703 +       if ((head)->slh_first == (elm)) {                               \
10704 +               SLIST_REMOVE_HEAD((head), field);                       \
10705 +       }                                                               \
10706 +       else {                                                          \
10707 +               struct type *curelm = (head)->slh_first;                \
10708 +               while( curelm->field.sle_next != (elm) )                \
10709 +                       curelm = curelm->field.sle_next;                \
10710 +               curelm->field.sle_next =                                \
10711 +                   curelm->field.sle_next->field.sle_next;             \
10712 +       }                                                               \
10713 +} while (0)
10714 +
10715 +/*
10716 + * Simple queue definitions.
10717 + */
10718 +#define DWC_SIMPLEQ_HEAD(name, type)                                   \
10719 +struct name {                                                          \
10720 +       struct type *sqh_first; /* first element */                     \
10721 +       struct type **sqh_last; /* addr of last next element */         \
10722 +}
10723 +
10724 +#define DWC_SIMPLEQ_HEAD_INITIALIZER(head)                             \
10725 +       { NULL, &(head).sqh_first }
10726 +
10727 +#define DWC_SIMPLEQ_ENTRY(type)                                                \
10728 +struct {                                                               \
10729 +       struct type *sqe_next;  /* next element */                      \
10730 +}
10731 +
10732 +/*
10733 + * Simple queue access methods.
10734 + */
10735 +#define DWC_SIMPLEQ_FIRST(head)            ((head)->sqh_first)
10736 +#define DWC_SIMPLEQ_END(head)      NULL
10737 +#define DWC_SIMPLEQ_EMPTY(head)            (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
10738 +#define DWC_SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
10739 +
10740 +#define DWC_SIMPLEQ_FOREACH(var, head, field)                          \
10741 +       for((var) = SIMPLEQ_FIRST(head);                                \
10742 +           (var) != SIMPLEQ_END(head);                                 \
10743 +           (var) = SIMPLEQ_NEXT(var, field))
10744 +
10745 +/*
10746 + * Simple queue functions.
10747 + */
10748 +#define DWC_SIMPLEQ_INIT(head) do {                                    \
10749 +       (head)->sqh_first = NULL;                                       \
10750 +       (head)->sqh_last = &(head)->sqh_first;                          \
10751 +} while (0)
10752 +
10753 +#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do {                 \
10754 +       if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)        \
10755 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
10756 +       (head)->sqh_first = (elm);                                      \
10757 +} while (0)
10758 +
10759 +#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do {                 \
10760 +       (elm)->field.sqe_next = NULL;                                   \
10761 +       *(head)->sqh_last = (elm);                                      \
10762 +       (head)->sqh_last = &(elm)->field.sqe_next;                      \
10763 +} while (0)
10764 +
10765 +#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {       \
10766 +       if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
10767 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
10768 +       (listelm)->field.sqe_next = (elm);                              \
10769 +} while (0)
10770 +
10771 +#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do {                      \
10772 +       if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
10773 +               (head)->sqh_last = &(head)->sqh_first;                  \
10774 +} while (0)
10775 +
10776 +/*
10777 + * Tail queue definitions.
10778 + */
10779 +#define DWC_TAILQ_HEAD(name, type)                                     \
10780 +struct name {                                                          \
10781 +       struct type *tqh_first; /* first element */                     \
10782 +       struct type **tqh_last; /* addr of last next element */         \
10783 +}
10784 +
10785 +#define DWC_TAILQ_HEAD_INITIALIZER(head)                               \
10786 +       { NULL, &(head).tqh_first }
10787 +
10788 +#define DWC_TAILQ_ENTRY(type)                                          \
10789 +struct {                                                               \
10790 +       struct type *tqe_next;  /* next element */                      \
10791 +       struct type **tqe_prev; /* address of previous next element */  \
10792 +}
10793 +
10794 +/*
10795 + * tail queue access methods
10796 + */
10797 +#define DWC_TAILQ_FIRST(head)          ((head)->tqh_first)
10798 +#define DWC_TAILQ_END(head)            NULL
10799 +#define DWC_TAILQ_NEXT(elm, field)     ((elm)->field.tqe_next)
10800 +#define DWC_TAILQ_LAST(head, headname)                                 \
10801 +       (*(((struct headname *)((head)->tqh_last))->tqh_last))
10802 +/* XXX */
10803 +#define DWC_TAILQ_PREV(elm, headname, field)                           \
10804 +       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
10805 +#define DWC_TAILQ_EMPTY(head)                                          \
10806 +       (TAILQ_FIRST(head) == TAILQ_END(head))
10807 +
10808 +#define DWC_TAILQ_FOREACH(var, head, field)                            \
10809 +       for((var) = TAILQ_FIRST(head);                                  \
10810 +           (var) != TAILQ_END(head);                                   \
10811 +           (var) = TAILQ_NEXT(var, field))
10812 +
10813 +#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field)          \
10814 +       for((var) = TAILQ_LAST(head, headname);                         \
10815 +           (var) != TAILQ_END(head);                                   \
10816 +           (var) = TAILQ_PREV(var, headname, field))
10817 +
10818 +/*
10819 + * Tail queue functions.
10820 + */
10821 +#define DWC_TAILQ_INIT(head) do {                                      \
10822 +       (head)->tqh_first = NULL;                                       \
10823 +       (head)->tqh_last = &(head)->tqh_first;                          \
10824 +} while (0)
10825 +
10826 +#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do {                   \
10827 +       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
10828 +               (head)->tqh_first->field.tqe_prev =                     \
10829 +                   &(elm)->field.tqe_next;                             \
10830 +       else                                                            \
10831 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
10832 +       (head)->tqh_first = (elm);                                      \
10833 +       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
10834 +} while (0)
10835 +
10836 +#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do {                   \
10837 +       (elm)->field.tqe_next = NULL;                                   \
10838 +       (elm)->field.tqe_prev = (head)->tqh_last;                       \
10839 +       *(head)->tqh_last = (elm);                                      \
10840 +       (head)->tqh_last = &(elm)->field.tqe_next;                      \
10841 +} while (0)
10842 +
10843 +#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {         \
10844 +       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
10845 +               (elm)->field.tqe_next->field.tqe_prev =                 \
10846 +                   &(elm)->field.tqe_next;                             \
10847 +       else                                                            \
10848 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
10849 +       (listelm)->field.tqe_next = (elm);                              \
10850 +       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
10851 +} while (0)
10852 +
10853 +#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do {              \
10854 +       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
10855 +       (elm)->field.tqe_next = (listelm);                              \
10856 +       *(listelm)->field.tqe_prev = (elm);                             \
10857 +       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
10858 +} while (0)
10859 +
10860 +#define DWC_TAILQ_REMOVE(head, elm, field) do {                                \
10861 +       if (((elm)->field.tqe_next) != NULL)                            \
10862 +               (elm)->field.tqe_next->field.tqe_prev =                 \
10863 +                   (elm)->field.tqe_prev;                              \
10864 +       else                                                            \
10865 +               (head)->tqh_last = (elm)->field.tqe_prev;               \
10866 +       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
10867 +} while (0)
10868 +
10869 +#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do {                 \
10870 +       if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   \
10871 +               (elm2)->field.tqe_next->field.tqe_prev =                \
10872 +                   &(elm2)->field.tqe_next;                            \
10873 +       else                                                            \
10874 +               (head)->tqh_last = &(elm2)->field.tqe_next;             \
10875 +       (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 \
10876 +       *(elm2)->field.tqe_prev = (elm2);                               \
10877 +} while (0)
10878 +
10879 +/*
10880 + * Circular queue definitions.
10881 + */
10882 +#define DWC_CIRCLEQ_HEAD(name, type)                                   \
10883 +struct name {                                                          \
10884 +       struct type *cqh_first;         /* first element */             \
10885 +       struct type *cqh_last;          /* last element */              \
10886 +}
10887 +
10888 +#define DWC_CIRCLEQ_HEAD_INITIALIZER(head)                             \
10889 +       { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }
10890 +
10891 +#define DWC_CIRCLEQ_ENTRY(type)                                                \
10892 +struct {                                                               \
10893 +       struct type *cqe_next;          /* next element */              \
10894 +       struct type *cqe_prev;          /* previous element */          \
10895 +}
10896 +
10897 +/*
10898 + * Circular queue access methods
10899 + */
10900 +#define DWC_CIRCLEQ_FIRST(head)                ((head)->cqh_first)
10901 +#define DWC_CIRCLEQ_LAST(head)         ((head)->cqh_last)
10902 +#define DWC_CIRCLEQ_END(head)          ((void *)(head))
10903 +#define DWC_CIRCLEQ_NEXT(elm, field)   ((elm)->field.cqe_next)
10904 +#define DWC_CIRCLEQ_PREV(elm, field)   ((elm)->field.cqe_prev)
10905 +#define DWC_CIRCLEQ_EMPTY(head)                                                \
10906 +       (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))
10907 +
10908 +#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))
10909 +
10910 +#define DWC_CIRCLEQ_FOREACH(var, head, field)                          \
10911 +       for((var) = DWC_CIRCLEQ_FIRST(head);                            \
10912 +           (var) != DWC_CIRCLEQ_END(head);                             \
10913 +           (var) = DWC_CIRCLEQ_NEXT(var, field))
10914 +
10915 +#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field)                       \
10916 +       for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \
10917 +           (var) != DWC_CIRCLEQ_END(head);                                     \
10918 +           (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))
10919 +
10920 +#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field)                  \
10921 +       for((var) = DWC_CIRCLEQ_LAST(head);                             \
10922 +           (var) != DWC_CIRCLEQ_END(head);                             \
10923 +           (var) = DWC_CIRCLEQ_PREV(var, field))
10924 +
10925 +/*
10926 + * Circular queue functions.
10927 + */
10928 +#define DWC_CIRCLEQ_INIT(head) do {                                    \
10929 +       (head)->cqh_first = DWC_CIRCLEQ_END(head);                      \
10930 +       (head)->cqh_last = DWC_CIRCLEQ_END(head);                       \
10931 +} while (0)
10932 +
10933 +#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do {                                \
10934 +       (elm)->field.cqe_next = NULL;                                   \
10935 +       (elm)->field.cqe_prev = NULL;                                   \
10936 +} while (0)
10937 +
10938 +#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {       \
10939 +       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
10940 +       (elm)->field.cqe_prev = (listelm);                              \
10941 +       if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head))         \
10942 +               (head)->cqh_last = (elm);                               \
10943 +       else                                                            \
10944 +               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
10945 +       (listelm)->field.cqe_next = (elm);                              \
10946 +} while (0)
10947 +
10948 +#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {      \
10949 +       (elm)->field.cqe_next = (listelm);                              \
10950 +       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
10951 +       if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head))         \
10952 +               (head)->cqh_first = (elm);                              \
10953 +       else                                                            \
10954 +               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
10955 +       (listelm)->field.cqe_prev = (elm);                              \
10956 +} while (0)
10957 +
10958 +#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do {                 \
10959 +       (elm)->field.cqe_next = (head)->cqh_first;                      \
10960 +       (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head);                  \
10961 +       if ((head)->cqh_last == DWC_CIRCLEQ_END(head))                  \
10962 +               (head)->cqh_last = (elm);                               \
10963 +       else                                                            \
10964 +               (head)->cqh_first->field.cqe_prev = (elm);              \
10965 +       (head)->cqh_first = (elm);                                      \
10966 +} while (0)
10967 +
10968 +#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do {                 \
10969 +       (elm)->field.cqe_next = DWC_CIRCLEQ_END(head);                  \
10970 +       (elm)->field.cqe_prev = (head)->cqh_last;                       \
10971 +       if ((head)->cqh_first == DWC_CIRCLEQ_END(head))                 \
10972 +               (head)->cqh_first = (elm);                              \
10973 +       else                                                            \
10974 +               (head)->cqh_last->field.cqe_next = (elm);               \
10975 +       (head)->cqh_last = (elm);                                       \
10976 +} while (0)
10977 +
10978 +#define DWC_CIRCLEQ_REMOVE(head, elm, field) do {                      \
10979 +       if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head))             \
10980 +               (head)->cqh_last = (elm)->field.cqe_prev;               \
10981 +       else                                                            \
10982 +               (elm)->field.cqe_next->field.cqe_prev =                 \
10983 +                   (elm)->field.cqe_prev;                              \
10984 +       if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head))             \
10985 +               (head)->cqh_first = (elm)->field.cqe_next;              \
10986 +       else                                                            \
10987 +               (elm)->field.cqe_prev->field.cqe_next =                 \
10988 +                   (elm)->field.cqe_next;                              \
10989 +} while (0)
10990 +
10991 +#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do {                 \
10992 +       DWC_CIRCLEQ_REMOVE(head, elm, field);                           \
10993 +       DWC_CIRCLEQ_INIT_ENTRY(elm, field);                             \
10994 +} while (0)
10995 +
10996 +#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do {               \
10997 +       if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==         \
10998 +           DWC_CIRCLEQ_END(head))                                      \
10999 +               (head).cqh_last = (elm2);                               \
11000 +       else                                                            \
11001 +               (elm2)->field.cqe_next->field.cqe_prev = (elm2);        \
11002 +       if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==         \
11003 +           DWC_CIRCLEQ_END(head))                                      \
11004 +               (head).cqh_first = (elm2);                              \
11005 +       else                                                            \
11006 +               (elm2)->field.cqe_prev->field.cqe_next = (elm2);        \
11007 +} while (0)
11008 +
11009 +#ifdef __cplusplus
11010 +}
11011 +#endif
11012 +
11013 +#endif /* _DWC_LIST_H_ */
11014 diff --git a/drivers/usb/host/dwc_common_port/dwc_mem.c b/drivers/usb/host/dwc_common_port/dwc_mem.c
11015 new file mode 100644
11016 index 0000000..ad645ff
11017 --- /dev/null
11018 +++ b/drivers/usb/host/dwc_common_port/dwc_mem.c
11019 @@ -0,0 +1,245 @@
11020 +/* Memory Debugging */
11021 +#ifdef DWC_DEBUG_MEMORY
11022 +
11023 +#include "dwc_os.h"
11024 +#include "dwc_list.h"
11025 +
11026 +struct allocation {
11027 +       void *addr;
11028 +       void *ctx;
11029 +       char *func;
11030 +       int line;
11031 +       uint32_t size;
11032 +       int dma;
11033 +       DWC_CIRCLEQ_ENTRY(allocation) entry;
11034 +};
11035 +
11036 +DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
11037 +
11038 +struct allocation_manager {
11039 +       void *mem_ctx;
11040 +       struct allocation_queue allocations;
11041 +
11042 +       /* statistics */
11043 +       int num;
11044 +       int num_freed;
11045 +       int num_active;
11046 +       uint32_t total;
11047 +       uint32_t cur;
11048 +       uint32_t max;
11049 +};
11050 +
11051 +static struct allocation_manager *manager = NULL;
11052 +
11053 +static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr,
11054 +                         int dma)
11055 +{
11056 +       struct allocation *a;
11057 +
11058 +       DWC_ASSERT(manager != NULL, "manager not allocated");
11059 +
11060 +       a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a));
11061 +       if (!a) {
11062 +               return -DWC_E_NO_MEMORY;
11063 +       }
11064 +
11065 +       a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1);
11066 +       if (!a->func) {
11067 +               __DWC_FREE(manager->mem_ctx, a);
11068 +               return -DWC_E_NO_MEMORY;
11069 +       }
11070 +
11071 +       DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1);
11072 +       a->addr = addr;
11073 +       a->ctx = ctx;
11074 +       a->line = line;
11075 +       a->size = size;
11076 +       a->dma = dma;
11077 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
11078 +
11079 +       /* Update stats */
11080 +       manager->num++;
11081 +       manager->num_active++;
11082 +       manager->total += size;
11083 +       manager->cur += size;
11084 +
11085 +       if (manager->max < manager->cur) {
11086 +               manager->max = manager->cur;
11087 +       }
11088 +
11089 +       return 0;
11090 +}
11091 +
11092 +static struct allocation *find_allocation(void *ctx, void *addr)
11093 +{
11094 +       struct allocation *a;
11095 +
11096 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11097 +               if (a->ctx == ctx && a->addr == addr) {
11098 +                       return a;
11099 +               }
11100 +       }
11101 +
11102 +       return NULL;
11103 +}
11104 +
11105 +static void free_allocation(void *ctx, void *addr, char const *func, int line)
11106 +{
11107 +       struct allocation *a = find_allocation(ctx, addr);
11108 +
11109 +       if (!a) {
11110 +               DWC_ASSERT(0,
11111 +                          "Free of address %p that was never allocated or already freed %s:%d",
11112 +                          addr, func, line);
11113 +               return;
11114 +       }
11115 +
11116 +       DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
11117 +
11118 +       manager->num_active--;
11119 +       manager->num_freed++;
11120 +       manager->cur -= a->size;
11121 +       __DWC_FREE(manager->mem_ctx, a->func);
11122 +       __DWC_FREE(manager->mem_ctx, a);
11123 +}
11124 +
11125 +int dwc_memory_debug_start(void *mem_ctx)
11126 +{
11127 +       DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
11128 +
11129 +       if (manager) {
11130 +               return -DWC_E_BUSY;
11131 +       }
11132 +
11133 +       manager = __DWC_ALLOC(mem_ctx, sizeof(*manager));
11134 +       if (!manager) {
11135 +               return -DWC_E_NO_MEMORY;
11136 +       }
11137 +
11138 +       DWC_CIRCLEQ_INIT(&manager->allocations);
11139 +       manager->mem_ctx = mem_ctx;
11140 +       manager->num = 0;
11141 +       manager->num_freed = 0;
11142 +       manager->num_active = 0;
11143 +       manager->total = 0;
11144 +       manager->cur = 0;
11145 +       manager->max = 0;
11146 +
11147 +       return 0;
11148 +}
11149 +
11150 +void dwc_memory_debug_stop(void)
11151 +{
11152 +       struct allocation *a;
11153 +
11154 +       dwc_memory_debug_report();
11155 +
11156 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11157 +               DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
11158 +               free_allocation(a->ctx, a->addr, NULL, -1);
11159 +       }
11160 +
11161 +       __DWC_FREE(manager->mem_ctx, manager);
11162 +}
11163 +
11164 +void dwc_memory_debug_report(void)
11165 +{
11166 +       struct allocation *a;
11167 +
11168 +       DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
11169 +       DWC_PRINTF("Num Allocations = %d\n", manager->num);
11170 +       DWC_PRINTF("Freed = %d\n", manager->num_freed);
11171 +       DWC_PRINTF("Active = %d\n", manager->num_active);
11172 +       DWC_PRINTF("Current Memory Used = %d\n", manager->cur);
11173 +       DWC_PRINTF("Total Memory Used = %d\n", manager->total);
11174 +       DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
11175 +       DWC_PRINTF("Unfreed allocations:\n");
11176 +
11177 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11178 +               DWC_PRINTF("    addr=%p, size=%d from %s:%d, DMA=%d\n",
11179 +                          a->addr, a->size, a->func, a->line, a->dma);
11180 +       }
11181 +}
11182 +
11183 +/* The replacement functions */
11184 +void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line)
11185 +{
11186 +       void *addr = __DWC_ALLOC(mem_ctx, size);
11187 +
11188 +       if (!addr) {
11189 +               return NULL;
11190 +       }
11191 +
11192 +       if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
11193 +               __DWC_FREE(mem_ctx, addr);
11194 +               return NULL;
11195 +       }
11196 +
11197 +       return addr;
11198 +}
11199 +
11200 +void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func,
11201 +                            int line)
11202 +{
11203 +       void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size);
11204 +
11205 +       if (!addr) {
11206 +               return NULL;
11207 +       }
11208 +
11209 +       if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
11210 +               __DWC_FREE(mem_ctx, addr);
11211 +               return NULL;
11212 +       }
11213 +
11214 +       return addr;
11215 +}
11216 +
11217 +void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line)
11218 +{
11219 +       free_allocation(mem_ctx, addr, func, line);
11220 +       __DWC_FREE(mem_ctx, addr);
11221 +}
11222 +
11223 +void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
11224 +                         char const *func, int line)
11225 +{
11226 +       void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr);
11227 +
11228 +       if (!addr) {
11229 +               return NULL;
11230 +       }
11231 +
11232 +       if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
11233 +               __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
11234 +               return NULL;
11235 +       }
11236 +
11237 +       return addr;
11238 +}
11239 +
11240 +void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size,
11241 +                                dwc_dma_t *dma_addr, char const *func, int line)
11242 +{
11243 +       void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr);
11244 +
11245 +       if (!addr) {
11246 +               return NULL;
11247 +       }
11248 +
11249 +       if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
11250 +               __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
11251 +               return NULL;
11252 +       }
11253 +
11254 +       return addr;
11255 +}
11256 +
11257 +void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
11258 +                       dwc_dma_t dma_addr, char const *func, int line)
11259 +{
11260 +       free_allocation(dma_ctx, virt_addr, func, line);
11261 +       __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr);
11262 +}
11263 +
11264 +#endif /* DWC_DEBUG_MEMORY */
11265 diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.c b/drivers/usb/host/dwc_common_port/dwc_modpow.c
11266 new file mode 100644
11267 index 0000000..b7c456b
11268 --- /dev/null
11269 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c
11270 @@ -0,0 +1,636 @@
11271 +/* Bignum routines adapted from PUTTY sources.  PuTTY copyright notice follows.
11272 + *
11273 + * PuTTY is copyright 1997-2007 Simon Tatham.
11274 + *
11275 + * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
11276 + * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
11277 + * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
11278 + * Kuhn, and CORE SDI S.A.
11279 + *
11280 + * Permission is hereby granted, free of charge, to any person
11281 + * obtaining a copy of this software and associated documentation files
11282 + * (the "Software"), to deal in the Software without restriction,
11283 + * including without limitation the rights to use, copy, modify, merge,
11284 + * publish, distribute, sublicense, and/or sell copies of the Software,
11285 + * and to permit persons to whom the Software is furnished to do so,
11286 + * subject to the following conditions:
11287 + *
11288 + * The above copyright notice and this permission notice shall be
11289 + * included in all copies or substantial portions of the Software.
11290 +
11291 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11292 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11293 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11294 + * NONINFRINGEMENT.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
11295 + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
11296 + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
11297 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11298 + *
11299 + */
11300 +#ifdef DWC_CRYPTOLIB
11301 +
11302 +#ifndef CONFIG_MACH_IPMATE
11303 +
11304 +#include "dwc_modpow.h"
11305 +
11306 +#define BIGNUM_INT_MASK  0xFFFFFFFFUL
11307 +#define BIGNUM_TOP_BIT   0x80000000UL
11308 +#define BIGNUM_INT_BITS  32
11309 +
11310 +
11311 +static void *snmalloc(void *mem_ctx, size_t n, size_t size)
11312 +{
11313 +    void *p;
11314 +    size *= n;
11315 +    if (size == 0) size = 1;
11316 +    p = dwc_alloc(mem_ctx, size);
11317 +    return p;
11318 +}
11319 +
11320 +#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type)))
11321 +#define sfree dwc_free
11322 +
11323 +/*
11324 + * Usage notes:
11325 + *  * Do not call the DIVMOD_WORD macro with expressions such as array
11326 + *    subscripts, as some implementations object to this (see below).
11327 + *  * Note that none of the division methods below will cope if the
11328 + *    quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
11329 + *    to avoid this case.
11330 + *    If this condition occurs, in the case of the x86 DIV instruction,
11331 + *    an overflow exception will occur, which (according to a correspondent)
11332 + *    will manifest on Windows as something like
11333 + *      0xC0000095: Integer overflow
11334 + *    The C variant won't give the right answer, either.
11335 + */
11336 +
11337 +#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
11338 +
11339 +#if defined __GNUC__ && defined __i386__
11340 +#define DIVMOD_WORD(q, r, hi, lo, w) \
11341 +    __asm__("div %2" : \
11342 +           "=d" (r), "=a" (q) : \
11343 +           "r" (w), "d" (hi), "a" (lo))
11344 +#else
11345 +#define DIVMOD_WORD(q, r, hi, lo, w) do { \
11346 +    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
11347 +    q = n / w; \
11348 +    r = n % w; \
11349 +} while (0)
11350 +#endif
11351 +
11352 +//    q = n / w;                                
11353 +//    r = n % w;                                
11354 +
11355 +#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
11356 +
11357 +#define BIGNUM_INTERNAL
11358 +
11359 +static Bignum newbn(void *mem_ctx, int length)
11360 +{
11361 +    Bignum b = snewn(mem_ctx, length + 1, BignumInt);
11362 +    //if (!b)
11363 +    //abort();                /* FIXME */
11364 +    DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));
11365 +    b[0] = length;
11366 +    return b;
11367 +}
11368 +
11369 +void freebn(void *mem_ctx, Bignum b)
11370 +{
11371 +    /*
11372 +     * Burn the evidence, just in case.
11373 +     */
11374 +    DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));
11375 +    sfree(mem_ctx, b);
11376 +}
11377 +
11378 +/*
11379 + * Compute c = a * b.
11380 + * Input is in the first len words of a and b.
11381 + * Result is returned in the first 2*len words of c.
11382 + */
11383 +static void internal_mul(BignumInt *a, BignumInt *b,
11384 +                        BignumInt *c, int len)
11385 +{
11386 +    int i, j;
11387 +    BignumDblInt t;
11388 +
11389 +    for (j = 0; j < 2 * len; j++)
11390 +       c[j] = 0;
11391 +
11392 +    for (i = len - 1; i >= 0; i--) {
11393 +       t = 0;
11394 +       for (j = len - 1; j >= 0; j--) {
11395 +           t += MUL_WORD(a[i], (BignumDblInt) b[j]);
11396 +           t += (BignumDblInt) c[i + j + 1];
11397 +           c[i + j + 1] = (BignumInt) t;
11398 +           t = t >> BIGNUM_INT_BITS;
11399 +       }
11400 +       c[i] = (BignumInt) t;
11401 +    }
11402 +}
11403 +
11404 +static void internal_add_shifted(BignumInt *number,
11405 +                                unsigned n, int shift)
11406 +{
11407 +    int word = 1 + (shift / BIGNUM_INT_BITS);
11408 +    int bshift = shift % BIGNUM_INT_BITS;
11409 +    BignumDblInt addend;
11410 +
11411 +    addend = (BignumDblInt)n << bshift;
11412 +
11413 +    while (addend) {
11414 +       addend += number[word];
11415 +       number[word] = (BignumInt) addend & BIGNUM_INT_MASK;
11416 +       addend >>= BIGNUM_INT_BITS;
11417 +       word++;
11418 +    }
11419 +}
11420 +
11421 +/*
11422 + * Compute a = a % m.
11423 + * Input in first alen words of a and first mlen words of m.
11424 + * Output in first alen words of a
11425 + * (of which first alen-mlen words will be zero).
11426 + * The MSW of m MUST have its high bit set.
11427 + * Quotient is accumulated in the `quotient' array, which is a Bignum
11428 + * rather than the internal bigendian format. Quotient parts are shifted
11429 + * left by `qshift' before adding into quot.
11430 + */
11431 +static void internal_mod(BignumInt *a, int alen,
11432 +                        BignumInt *m, int mlen,
11433 +                        BignumInt *quot, int qshift)
11434 +{
11435 +    BignumInt m0, m1;
11436 +    unsigned int h;
11437 +    int i, k;
11438 +
11439 +    m0 = m[0];
11440 +    if (mlen > 1)
11441 +       m1 = m[1];
11442 +    else
11443 +       m1 = 0;
11444 +
11445 +    for (i = 0; i <= alen - mlen; i++) {
11446 +       BignumDblInt t;
11447 +       unsigned int q, r, c, ai1;
11448 +
11449 +       if (i == 0) {
11450 +           h = 0;
11451 +       } else {
11452 +           h = a[i - 1];
11453 +           a[i - 1] = 0;
11454 +       }
11455 +
11456 +       if (i == alen - 1)
11457 +           ai1 = 0;
11458 +       else
11459 +           ai1 = a[i + 1];
11460 +
11461 +       /* Find q = h:a[i] / m0 */
11462 +       if (h >= m0) {
11463 +           /*
11464 +            * Special case.
11465 +            * 
11466 +            * To illustrate it, suppose a BignumInt is 8 bits, and
11467 +            * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then
11468 +            * our initial division will be 0xA123 / 0xA1, which
11469 +            * will give a quotient of 0x100 and a divide overflow.
11470 +            * However, the invariants in this division algorithm
11471 +            * are not violated, since the full number A1:23:... is
11472 +            * _less_ than the quotient prefix A1:B2:... and so the
11473 +            * following correction loop would have sorted it out.
11474 +            * 
11475 +            * In this situation we set q to be the largest
11476 +            * quotient we _can_ stomach (0xFF, of course).
11477 +            */
11478 +           q = BIGNUM_INT_MASK;
11479 +       } else {
11480 +           /* Macro doesn't want an array subscript expression passed
11481 +            * into it (see definition), so use a temporary. */
11482 +           BignumInt tmplo = a[i];
11483 +           DIVMOD_WORD(q, r, h, tmplo, m0);
11484 +
11485 +           /* Refine our estimate of q by looking at
11486 +            h:a[i]:a[i+1] / m0:m1 */
11487 +           t = MUL_WORD(m1, q);
11488 +           if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {
11489 +               q--;
11490 +               t -= m1;
11491 +               r = (r + m0) & BIGNUM_INT_MASK;     /* overflow? */
11492 +               if (r >= (BignumDblInt) m0 &&
11493 +                   t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;
11494 +           }
11495 +       }
11496 +
11497 +       /* Subtract q * m from a[i...] */
11498 +       c = 0;
11499 +       for (k = mlen - 1; k >= 0; k--) {
11500 +           t = MUL_WORD(q, m[k]);
11501 +           t += c;
11502 +           c = (unsigned)(t >> BIGNUM_INT_BITS);
11503 +           if ((BignumInt) t > a[i + k])
11504 +               c++;
11505 +           a[i + k] -= (BignumInt) t;
11506 +       }
11507 +
11508 +       /* Add back m in case of borrow */
11509 +       if (c != h) {
11510 +           t = 0;
11511 +           for (k = mlen - 1; k >= 0; k--) {
11512 +               t += m[k];
11513 +               t += a[i + k];
11514 +               a[i + k] = (BignumInt) t;
11515 +               t = t >> BIGNUM_INT_BITS;
11516 +           }
11517 +           q--;
11518 +       }
11519 +       if (quot)
11520 +           internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));
11521 +    }
11522 +}
11523 +
11524 +/*
11525 + * Compute p % mod.
11526 + * The most significant word of mod MUST be non-zero.
11527 + * We assume that the result array is the same size as the mod array.
11528 + * We optionally write out a quotient if `quotient' is non-NULL.
11529 + * We can avoid writing out the result if `result' is NULL.
11530 + */
11531 +void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient)
11532 +{
11533 +    BignumInt *n, *m;
11534 +    int mshift;
11535 +    int plen, mlen, i, j;
11536 +
11537 +    /* Allocate m of size mlen, copy mod to m */
11538 +    /* We use big endian internally */
11539 +    mlen = mod[0];
11540 +    m = snewn(mem_ctx, mlen, BignumInt);
11541 +    //if (!m)
11542 +    //abort();                /* FIXME */
11543 +    for (j = 0; j < mlen; j++)
11544 +       m[j] = mod[mod[0] - j];
11545 +
11546 +    /* Shift m left to make msb bit set */
11547 +    for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)
11548 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11549 +           break;
11550 +    if (mshift) {
11551 +       for (i = 0; i < mlen - 1; i++)
11552 +           m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));
11553 +       m[mlen - 1] = m[mlen - 1] << mshift;
11554 +    }
11555 +
11556 +    plen = p[0];
11557 +    /* Ensure plen > mlen */
11558 +    if (plen <= mlen)
11559 +       plen = mlen + 1;
11560 +
11561 +    /* Allocate n of size plen, copy p to n */
11562 +    n = snewn(mem_ctx, plen, BignumInt);
11563 +    //if (!n)
11564 +    //abort();                /* FIXME */
11565 +    for (j = 0; j < plen; j++)
11566 +       n[j] = 0;
11567 +    for (j = 1; j <= (int)p[0]; j++)
11568 +       n[plen - j] = p[j];
11569 +
11570 +    /* Main computation */
11571 +    internal_mod(n, plen, m, mlen, quotient, mshift);
11572 +
11573 +    /* Fixup result in case the modulus was shifted */
11574 +    if (mshift) {
11575 +       for (i = plen - mlen - 1; i < plen - 1; i++)
11576 +           n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));
11577 +       n[plen - 1] = n[plen - 1] << mshift;
11578 +       internal_mod(n, plen, m, mlen, quotient, 0);
11579 +       for (i = plen - 1; i >= plen - mlen; i--)
11580 +           n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));
11581 +    }
11582 +
11583 +    /* Copy result to buffer */
11584 +    if (result) {
11585 +       for (i = 1; i <= (int)result[0]; i++) {
11586 +           int j = plen - i;
11587 +           result[i] = j >= 0 ? n[j] : 0;
11588 +       }
11589 +    }
11590 +
11591 +    /* Free temporary arrays */
11592 +    for (i = 0; i < mlen; i++)
11593 +       m[i] = 0;
11594 +    sfree(mem_ctx, m);
11595 +    for (i = 0; i < plen; i++)
11596 +       n[i] = 0;
11597 +    sfree(mem_ctx, n);
11598 +}
11599 +
11600 +/*
11601 + * Simple remainder.
11602 + */
11603 +Bignum bigmod(void *mem_ctx, Bignum a, Bignum b)
11604 +{
11605 +    Bignum r = newbn(mem_ctx, b[0]);
11606 +    bigdivmod(mem_ctx, a, b, r, NULL);
11607 +    return r;
11608 +}
11609 +
11610 +/*
11611 + * Compute (base ^ exp) % mod.
11612 + */
11613 +Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod)
11614 +{
11615 +    BignumInt *a, *b, *n, *m;
11616 +    int mshift;
11617 +    int mlen, i, j;
11618 +    Bignum base, result;
11619 +
11620 +    /*
11621 +     * The most significant word of mod needs to be non-zero. It
11622 +     * should already be, but let's make sure.
11623 +     */
11624 +    //assert(mod[mod[0]] != 0);
11625 +
11626 +    /*
11627 +     * Make sure the base is smaller than the modulus, by reducing
11628 +     * it modulo the modulus if not.
11629 +     */
11630 +    base = bigmod(mem_ctx, base_in, mod);
11631 +
11632 +    /* Allocate m of size mlen, copy mod to m */
11633 +    /* We use big endian internally */
11634 +    mlen = mod[0];
11635 +    m = snewn(mem_ctx, mlen, BignumInt);
11636 +    //if (!m)
11637 +    //abort();                /* FIXME */
11638 +    for (j = 0; j < mlen; j++)
11639 +       m[j] = mod[mod[0] - j];
11640 +
11641 +    /* Shift m left to make msb bit set */
11642 +    for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)
11643 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11644 +           break;
11645 +    if (mshift) {
11646 +       for (i = 0; i < mlen - 1; i++)
11647 +           m[i] =
11648 +               (m[i] << mshift) | (m[i + 1] >>
11649 +                                   (BIGNUM_INT_BITS - mshift));
11650 +       m[mlen - 1] = m[mlen - 1] << mshift;
11651 +    }
11652 +
11653 +    /* Allocate n of size mlen, copy base to n */
11654 +    n = snewn(mem_ctx, mlen, BignumInt);
11655 +    //if (!n)
11656 +    //abort();                /* FIXME */
11657 +    i = mlen - base[0];
11658 +    for (j = 0; j < i; j++)
11659 +       n[j] = 0;
11660 +    for (j = 0; j < base[0]; j++)
11661 +       n[i + j] = base[base[0] - j];
11662 +
11663 +    /* Allocate a and b of size 2*mlen. Set a = 1 */
11664 +    a = snewn(mem_ctx, 2 * mlen, BignumInt);
11665 +    //if (!a)
11666 +    //abort();                /* FIXME */
11667 +    b = snewn(mem_ctx, 2 * mlen, BignumInt);
11668 +    //if (!b)
11669 +    //abort();                /* FIXME */
11670 +    for (i = 0; i < 2 * mlen; i++)
11671 +       a[i] = 0;
11672 +    a[2 * mlen - 1] = 1;
11673 +
11674 +    /* Skip leading zero bits of exp. */
11675 +    i = 0;
11676 +    j = BIGNUM_INT_BITS - 1;
11677 +    while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
11678 +       j--;
11679 +       if (j < 0) {
11680 +           i++;
11681 +           j = BIGNUM_INT_BITS - 1;
11682 +       }
11683 +    }
11684 +
11685 +    /* Main computation */
11686 +    while (i < exp[0]) {
11687 +       while (j >= 0) {
11688 +           internal_mul(a + mlen, a + mlen, b, mlen);
11689 +           internal_mod(b, mlen * 2, m, mlen, NULL, 0);
11690 +           if ((exp[exp[0] - i] & (1 << j)) != 0) {
11691 +               internal_mul(b + mlen, n, a, mlen);
11692 +               internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11693 +           } else {
11694 +               BignumInt *t;
11695 +               t = a;
11696 +               a = b;
11697 +               b = t;
11698 +           }
11699 +           j--;
11700 +       }
11701 +       i++;
11702 +       j = BIGNUM_INT_BITS - 1;
11703 +    }
11704 +
11705 +    /* Fixup result in case the modulus was shifted */
11706 +    if (mshift) {
11707 +       for (i = mlen - 1; i < 2 * mlen - 1; i++)
11708 +           a[i] =
11709 +               (a[i] << mshift) | (a[i + 1] >>
11710 +                                   (BIGNUM_INT_BITS - mshift));
11711 +       a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;
11712 +       internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11713 +       for (i = 2 * mlen - 1; i >= mlen; i--)
11714 +           a[i] =
11715 +               (a[i] >> mshift) | (a[i - 1] <<
11716 +                                   (BIGNUM_INT_BITS - mshift));
11717 +    }
11718 +
11719 +    /* Copy result to buffer */
11720 +    result = newbn(mem_ctx, mod[0]);
11721 +    for (i = 0; i < mlen; i++)
11722 +       result[result[0] - i] = a[i + mlen];
11723 +    while (result[0] > 1 && result[result[0]] == 0)
11724 +       result[0]--;
11725 +
11726 +    /* Free temporary arrays */
11727 +    for (i = 0; i < 2 * mlen; i++)
11728 +       a[i] = 0;
11729 +    sfree(mem_ctx, a);
11730 +    for (i = 0; i < 2 * mlen; i++)
11731 +       b[i] = 0;
11732 +    sfree(mem_ctx, b);
11733 +    for (i = 0; i < mlen; i++)
11734 +       m[i] = 0;
11735 +    sfree(mem_ctx, m);
11736 +    for (i = 0; i < mlen; i++)
11737 +       n[i] = 0;
11738 +    sfree(mem_ctx, n);
11739 +
11740 +    freebn(mem_ctx, base);
11741 +
11742 +    return result;
11743 +}
11744 +
11745 +
11746 +#ifdef UNITTEST
11747 +
11748 +static __u32 dh_p[] = {
11749 +       96,
11750 +       0xFFFFFFFF,
11751 +       0xFFFFFFFF,
11752 +       0xA93AD2CA,
11753 +       0x4B82D120,
11754 +       0xE0FD108E,
11755 +       0x43DB5BFC,
11756 +       0x74E5AB31,
11757 +       0x08E24FA0,
11758 +       0xBAD946E2,
11759 +       0x770988C0,
11760 +       0x7A615D6C,
11761 +       0xBBE11757,
11762 +       0x177B200C,
11763 +       0x521F2B18,
11764 +       0x3EC86A64,
11765 +       0xD8760273,
11766 +       0xD98A0864,
11767 +       0xF12FFA06,
11768 +       0x1AD2EE6B,
11769 +       0xCEE3D226,
11770 +       0x4A25619D,
11771 +       0x1E8C94E0,
11772 +       0xDB0933D7,
11773 +       0xABF5AE8C,
11774 +       0xA6E1E4C7,
11775 +       0xB3970F85,
11776 +       0x5D060C7D,
11777 +       0x8AEA7157,
11778 +       0x58DBEF0A,
11779 +       0xECFB8504,
11780 +       0xDF1CBA64,
11781 +       0xA85521AB,
11782 +       0x04507A33,
11783 +       0xAD33170D,
11784 +       0x8AAAC42D,
11785 +       0x15728E5A,
11786 +       0x98FA0510,
11787 +       0x15D22618,
11788 +       0xEA956AE5,
11789 +       0x3995497C,
11790 +       0x95581718,
11791 +       0xDE2BCBF6,
11792 +       0x6F4C52C9,
11793 +       0xB5C55DF0,
11794 +       0xEC07A28F,
11795 +       0x9B2783A2,
11796 +       0x180E8603,
11797 +       0xE39E772C,
11798 +       0x2E36CE3B,
11799 +       0x32905E46,
11800 +       0xCA18217C,
11801 +       0xF1746C08,
11802 +       0x4ABC9804,
11803 +       0x670C354E,
11804 +       0x7096966D,
11805 +       0x9ED52907,
11806 +       0x208552BB,
11807 +       0x1C62F356,
11808 +       0xDCA3AD96,
11809 +       0x83655D23,
11810 +       0xFD24CF5F,
11811 +       0x69163FA8,
11812 +       0x1C55D39A,
11813 +       0x98DA4836,
11814 +       0xA163BF05,
11815 +       0xC2007CB8,
11816 +       0xECE45B3D,
11817 +       0x49286651,
11818 +       0x7C4B1FE6,
11819 +       0xAE9F2411,
11820 +       0x5A899FA5,
11821 +       0xEE386BFB,
11822 +       0xF406B7ED,
11823 +       0x0BFF5CB6,
11824 +       0xA637ED6B,
11825 +       0xF44C42E9,
11826 +       0x625E7EC6,
11827 +       0xE485B576,
11828 +       0x6D51C245,
11829 +       0x4FE1356D,
11830 +       0xF25F1437,
11831 +       0x302B0A6D,
11832 +       0xCD3A431B,
11833 +       0xEF9519B3,
11834 +       0x8E3404DD,
11835 +       0x514A0879,
11836 +       0x3B139B22,
11837 +       0x020BBEA6,
11838 +       0x8A67CC74,
11839 +       0x29024E08,
11840 +       0x80DC1CD1,
11841 +       0xC4C6628B,
11842 +       0x2168C234,
11843 +       0xC90FDAA2,
11844 +       0xFFFFFFFF,
11845 +       0xFFFFFFFF,
11846 +};
11847 +
11848 +static __u32 dh_a[] = {
11849 +       8,
11850 +       0xdf367516,
11851 +       0x86459caa,
11852 +       0xe2d459a4,
11853 +       0xd910dae0,
11854 +       0x8a8b5e37,
11855 +       0x67ab31c6,
11856 +       0xf0b55ea9,
11857 +       0x440051d6,
11858 +};
11859 +
11860 +static __u32 dh_b[] = {
11861 +       8,
11862 +       0xded92656,
11863 +       0xe07a048a,
11864 +       0x6fa452cd,
11865 +       0x2df89d30,
11866 +       0xc75f1b0f,
11867 +       0x8ce3578f, 
11868 +       0x7980a324,
11869 +       0x5daec786,
11870 +};
11871 +
11872 +static __u32 dh_g[] = {
11873 +       1,
11874 +       2,
11875 +};
11876 +
11877 +int main(void)
11878 +{
11879 +       int i;
11880 +       __u32 *k;
11881 +       k = dwc_modpow(NULL, dh_g, dh_a, dh_p);
11882 +
11883 +       printf("\n\n");
11884 +       for (i=0; i<k[0]; i++) {
11885 +               __u32 word32 = k[k[0] - i];
11886 +               __u16 l = word32 & 0xffff;
11887 +               __u16 m = (word32 & 0xffff0000) >> 16;
11888 +               printf("%04x %04x ", m, l);
11889 +               if (!((i + 1)%13)) printf("\n");
11890 +       }
11891 +       printf("\n\n");
11892 +
11893 +       if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {
11894 +               printf("PASS\n\n");
11895 +       }
11896 +       else {
11897 +               printf("FAIL\n\n");
11898 +       }
11899 +
11900 +}
11901 +
11902 +#endif /* UNITTEST */
11903 +
11904 +#endif /* CONFIG_MACH_IPMATE */
11905 +
11906 +#endif /*DWC_CRYPTOLIB */
11907 diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.h b/drivers/usb/host/dwc_common_port/dwc_modpow.h
11908 new file mode 100644
11909 index 0000000..64f00c2
11910 --- /dev/null
11911 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h
11912 @@ -0,0 +1,34 @@
11913 +/*
11914 + * dwc_modpow.h
11915 + * See dwc_modpow.c for license and changes
11916 + */
11917 +#ifndef _DWC_MODPOW_H
11918 +#define _DWC_MODPOW_H
11919 +
11920 +#ifdef __cplusplus
11921 +extern "C" {
11922 +#endif
11923 +
11924 +#include "dwc_os.h"
11925 +
11926 +/** @file
11927 + *
11928 + * This file defines the module exponentiation function which is only used
11929 + * internally by the DWC UWB modules for calculation of PKs during numeric
11930 + * association.  The routine is taken from the PUTTY, an open source terminal
11931 + * emulator.  The PUTTY License is preserved in the dwc_modpow.c file.
11932 + *
11933 + */
11934 +
11935 +typedef uint32_t BignumInt;
11936 +typedef uint64_t BignumDblInt;
11937 +typedef BignumInt *Bignum;
11938 +
11939 +/* Compute modular exponentiaion */
11940 +extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod);
11941 +
11942 +#ifdef __cplusplus
11943 +}
11944 +#endif
11945 +
11946 +#endif /* _LINUX_BIGNUM_H */
11947 diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.c b/drivers/usb/host/dwc_common_port/dwc_notifier.c
11948 new file mode 100644
11949 index 0000000..8b3772a
11950 --- /dev/null
11951 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c
11952 @@ -0,0 +1,319 @@
11953 +#ifdef DWC_NOTIFYLIB
11954 +
11955 +#include "dwc_notifier.h"
11956 +#include "dwc_list.h"
11957 +
11958 +typedef struct dwc_observer {
11959 +       void *observer;
11960 +       dwc_notifier_callback_t callback;
11961 +       void *data;
11962 +       char *notification;
11963 +       DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;
11964 +} observer_t;
11965 +
11966 +DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);
11967 +
11968 +typedef struct dwc_notifier {
11969 +       void *mem_ctx;
11970 +       void *object;
11971 +       struct observer_queue observers;
11972 +       DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;
11973 +} notifier_t;
11974 +
11975 +DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);
11976 +
11977 +typedef struct manager {
11978 +       void *mem_ctx;
11979 +       void *wkq_ctx;
11980 +       dwc_workq_t *wq;
11981 +//     dwc_mutex_t *mutex;
11982 +       struct notifier_queue notifiers;
11983 +} manager_t;
11984 +
11985 +static manager_t *manager = NULL;
11986 +
11987 +static int create_manager(void *mem_ctx, void *wkq_ctx)
11988 +{
11989 +       manager = dwc_alloc(mem_ctx, sizeof(manager_t));
11990 +       if (!manager) {
11991 +               return -DWC_E_NO_MEMORY;
11992 +       }
11993 +
11994 +       DWC_CIRCLEQ_INIT(&manager->notifiers);
11995 +
11996 +       manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ");
11997 +       if (!manager->wq) {
11998 +               return -DWC_E_NO_MEMORY;
11999 +       }
12000 +
12001 +       return 0;
12002 +}
12003 +
12004 +static void free_manager(void)
12005 +{
12006 +       dwc_workq_free(manager->wq);
12007 +
12008 +       /* All notifiers must have unregistered themselves before this module
12009 +        * can be removed.  Hitting this assertion indicates a programmer
12010 +        * error. */
12011 +       DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers),
12012 +                  "Notification manager being freed before all notifiers have been removed");
12013 +       dwc_free(manager->mem_ctx, manager);
12014 +}
12015 +
12016 +#ifdef DEBUG
12017 +static void dump_manager(void)
12018 +{
12019 +       notifier_t *n;
12020 +       observer_t *o;
12021 +
12022 +       DWC_ASSERT(manager, "Notification manager not found");
12023 +
12024 +       DWC_DEBUG("List of all notifiers and observers:\n");
12025 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
12026 +               DWC_DEBUG("Notifier %p has observers:\n", n->object);
12027 +               DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {
12028 +                       DWC_DEBUG("    %p watching %s\n", o->observer, o->notification);
12029 +               }
12030 +       }
12031 +}
12032 +#else
12033 +#define dump_manager(...)
12034 +#endif
12035 +
12036 +static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification,
12037 +                                 dwc_notifier_callback_t callback, void *data)
12038 +{
12039 +       observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t));
12040 +
12041 +       if (!new_observer) {
12042 +               return NULL;
12043 +       }
12044 +
12045 +       DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);
12046 +       new_observer->observer = observer;
12047 +       new_observer->notification = notification;
12048 +       new_observer->callback = callback;
12049 +       new_observer->data = data;
12050 +       return new_observer;
12051 +}
12052 +
12053 +static void free_observer(void *mem_ctx, observer_t *observer)
12054 +{
12055 +       dwc_free(mem_ctx, observer);
12056 +}
12057 +
12058 +static notifier_t *alloc_notifier(void *mem_ctx, void *object)
12059 +{
12060 +       notifier_t *notifier;
12061 +
12062 +       if (!object) {
12063 +               return NULL;
12064 +       }
12065 +
12066 +       notifier = dwc_alloc(mem_ctx, sizeof(notifier_t));
12067 +       if (!notifier) {
12068 +               return NULL;
12069 +       }
12070 +
12071 +       DWC_CIRCLEQ_INIT(&notifier->observers);
12072 +       DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);
12073 +
12074 +       notifier->mem_ctx = mem_ctx;
12075 +       notifier->object = object;
12076 +       return notifier;
12077 +}
12078 +
12079 +static void free_notifier(notifier_t *notifier)
12080 +{
12081 +       observer_t *observer;
12082 +
12083 +       DWC_CIRCLEQ_FOREACH(observer, &notifier->observers, list_entry) {
12084 +               free_observer(notifier->mem_ctx, observer);
12085 +       }
12086 +
12087 +       dwc_free(notifier->mem_ctx, notifier);
12088 +}
12089 +
12090 +static notifier_t *find_notifier(void *object)
12091 +{
12092 +       notifier_t *notifier;
12093 +
12094 +       DWC_ASSERT(manager, "Notification manager not found");
12095 +
12096 +       if (!object) {
12097 +               return NULL;
12098 +       }
12099 +
12100 +       DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {
12101 +               if (notifier->object == object) {
12102 +                       return notifier;
12103 +               }
12104 +       }
12105 +
12106 +       return NULL;
12107 +}
12108 +
12109 +int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx)
12110 +{
12111 +       return create_manager(mem_ctx, wkq_ctx);
12112 +}
12113 +
12114 +void dwc_free_notification_manager(void)
12115 +{
12116 +       free_manager();
12117 +}
12118 +
12119 +dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object)
12120 +{
12121 +       notifier_t *notifier;
12122 +
12123 +       DWC_ASSERT(manager, "Notification manager not found");
12124 +
12125 +       notifier = find_notifier(object);
12126 +       if (notifier) {
12127 +               DWC_ERROR("Notifier %p is already registered\n", object);
12128 +               return NULL;
12129 +       }
12130 +
12131 +       notifier = alloc_notifier(mem_ctx, object);
12132 +       if (!notifier) {
12133 +               return NULL;
12134 +       }
12135 +
12136 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);
12137 +
12138 +       DWC_INFO("Notifier %p registered", object);
12139 +       dump_manager();
12140 +
12141 +       return notifier;
12142 +}
12143 +
12144 +void dwc_unregister_notifier(dwc_notifier_t *notifier)
12145 +{
12146 +       DWC_ASSERT(manager, "Notification manager not found");
12147 +
12148 +       if (!DWC_CIRCLEQ_EMPTY(&notifier->observers)) {
12149 +               observer_t *o;
12150 +
12151 +               DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object);
12152 +               DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
12153 +                       DWC_DEBUGC("    %p watching %s\n", o->observer, o->notification);
12154 +               }
12155 +
12156 +               DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&notifier->observers),
12157 +                          "Notifier %p has active observers when removing", notifier);
12158 +       }
12159 +
12160 +       DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);
12161 +       free_notifier(notifier);
12162 +
12163 +       DWC_INFO("Notifier unregistered");
12164 +       dump_manager();
12165 +}
12166 +
12167 +/* Add an observer to observe the notifier for a particular state, event, or notification. */
12168 +int dwc_add_observer(void *observer, void *object, char *notification,
12169 +                    dwc_notifier_callback_t callback, void *data)
12170 +{
12171 +       notifier_t *notifier = find_notifier(object);
12172 +       observer_t *new_observer;
12173 +
12174 +       if (!notifier) {
12175 +               DWC_ERROR("Notifier %p is not found when adding observer\n", object);
12176 +               return -DWC_E_INVALID;
12177 +       }
12178 +
12179 +       new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data);
12180 +       if (!new_observer) {
12181 +               return -DWC_E_NO_MEMORY;
12182 +       }
12183 +
12184 +       DWC_CIRCLEQ_INSERT_TAIL(&notifier->observers, new_observer, list_entry);
12185 +
12186 +       DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",
12187 +                observer, object, notification, callback, data);
12188 +
12189 +       dump_manager();
12190 +       return 0;
12191 +}
12192 +
12193 +int dwc_remove_observer(void *observer)
12194 +{
12195 +       notifier_t *n;
12196 +
12197 +       DWC_ASSERT(manager, "Notification manager not found");
12198 +
12199 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
12200 +               observer_t *o;
12201 +               observer_t *o2;
12202 +
12203 +               DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {
12204 +                       if (o->observer == observer) {
12205 +                               DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);
12206 +                               DWC_INFO("Removing observer %p from notifier %p watching notification %s:",
12207 +                                        o->observer, n->object, o->notification);
12208 +                               free_observer(n->mem_ctx, o);
12209 +                       }
12210 +               }
12211 +       }
12212 +
12213 +       dump_manager();
12214 +       return 0;
12215 +}
12216 +
12217 +typedef struct callback_data {
12218 +       void *mem_ctx;
12219 +       dwc_notifier_callback_t cb;
12220 +       void *observer;
12221 +       void *data;
12222 +       void *object;
12223 +       char *notification;
12224 +       void *notification_data;
12225 +} cb_data_t;
12226 +
12227 +static void cb_task(void *data)
12228 +{
12229 +       cb_data_t *cb = (cb_data_t *)data;
12230 +
12231 +       cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);
12232 +       dwc_free(cb->mem_ctx, cb);
12233 +}
12234 +
12235 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)
12236 +{
12237 +       observer_t *o;
12238 +
12239 +       DWC_ASSERT(manager, "Notification manager not found");
12240 +
12241 +       DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
12242 +               int len = DWC_STRLEN(notification);
12243 +
12244 +               if (DWC_STRLEN(o->notification) != len) {
12245 +                       continue;
12246 +               }
12247 +
12248 +               if (DWC_STRNCMP(o->notification, notification, len) == 0) {
12249 +                       cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t));
12250 +
12251 +                       if (!cb_data) {
12252 +                               DWC_ERROR("Failed to allocate callback data\n");
12253 +                               return;
12254 +                       }
12255 +
12256 +                       cb_data->mem_ctx = notifier->mem_ctx;
12257 +                       cb_data->cb = o->callback;
12258 +                       cb_data->observer = o->observer;
12259 +                       cb_data->data = o->data;
12260 +                       cb_data->object = notifier->object;
12261 +                       cb_data->notification = notification;
12262 +                       cb_data->notification_data = notification_data;
12263 +                       DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification);
12264 +                       DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,
12265 +                                          "Notify callback from %p for Notification %s, to observer %p",
12266 +                                          cb_data->object, notification, cb_data->observer);
12267 +               }
12268 +       }
12269 +}
12270 +
12271 +#endif /* DWC_NOTIFYLIB */
12272 diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.h b/drivers/usb/host/dwc_common_port/dwc_notifier.h
12273 new file mode 100644
12274 index 0000000..4a8cdfe
12275 --- /dev/null
12276 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h
12277 @@ -0,0 +1,122 @@
12278 +
12279 +#ifndef __DWC_NOTIFIER_H__
12280 +#define __DWC_NOTIFIER_H__
12281 +
12282 +#ifdef __cplusplus
12283 +extern "C" {
12284 +#endif
12285 +
12286 +#include "dwc_os.h"
12287 +
12288 +/** @file
12289 + *
12290 + * A simple implementation of the Observer pattern.  Any "module" can
12291 + * register as an observer or notifier.  The notion of "module" is abstract and
12292 + * can mean anything used to identify either an observer or notifier.  Usually
12293 + * it will be a pointer to a data structure which contains some state, ie an
12294 + * object.
12295 + *
12296 + * Before any notifiers can be added, the global notification manager must be
12297 + * brought up with dwc_alloc_notification_manager().
12298 + * dwc_free_notification_manager() will bring it down and free all resources.
12299 + * These would typically be called upon module load and unload.  The
12300 + * notification manager is a single global instance that handles all registered
12301 + * observable modules and observers so this should be done only once.
12302 + *
12303 + * A module can be observable by using Notifications to publicize some general
12304 + * information about it's state or operation.  It does not care who listens, or
12305 + * even if anyone listens, or what they do with the information.  The observable
12306 + * modules do not need to know any information about it's observers or their
12307 + * interface, or their state or data.
12308 + *
12309 + * Any module can register to emit Notifications.  It should publish a list of
12310 + * notifications that it can emit and their behavior, such as when they will get
12311 + * triggered, and what information will be provided to the observer.  Then it
12312 + * should register itself as an observable module. See dwc_register_notifier().
12313 + *
12314 + * Any module can observe any observable, registered module, provided it has a
12315 + * handle to the other module and knows what notifications to observe.  See
12316 + * dwc_add_observer().
12317 + *
12318 + * A function of type dwc_notifier_callback_t is called whenever a notification
12319 + * is triggered with one or more observers observing it.  This function is
12320 + * called in it's own process so it may sleep or block if needed.  It is
12321 + * guaranteed to be called sometime after the notification has occurred and will
12322 + * be called once per each time the notification is triggered.  It will NOT be
12323 + * called in the same process context used to trigger the notification.
12324 + *
12325 + * @section Limitiations
12326 + *
12327 + * Keep in mind that Notifications that can be triggered in rapid sucession may
12328 + * schedule too many processes too handle.  Be aware of this limitation when
12329 + * designing to use notifications, and only add notifications for appropriate
12330 + * observable information.
12331 + *
12332 + * Also Notification callbacks are not synchronous.  If you need to synchronize
12333 + * the behavior between module/observer you must use other means.  And perhaps
12334 + * that will mean Notifications are not the proper solution.
12335 + */
12336 +
12337 +struct dwc_notifier;
12338 +typedef struct dwc_notifier dwc_notifier_t;
12339 +
12340 +/** The callback function must be of this type.
12341 + *
12342 + * @param object This is the object that is being observed.
12343 + * @param notification This is the notification that was triggered.
12344 + * @param observer This is the observer
12345 + * @param notification_data This is notification-specific data that the notifier
12346 + * has included in this notification.  The value of this should be published in
12347 + * the documentation of the observable module with the notifications.
12348 + * @param user_data This is any custom data that the observer provided when
12349 + * adding itself as an observer to the notification. */
12350 +typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer,
12351 +                                       void *notification_data, void *user_data);
12352 +
12353 +/** Brings up the notification manager. */
12354 +extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx);
12355 +/** Brings down the notification manager. */
12356 +extern void dwc_free_notification_manager(void);
12357 +
12358 +/** This function registers an observable module.  A dwc_notifier_t object is
12359 + * returned to the observable module.  This is an opaque object that is used by
12360 + * the observable module to trigger notifications.  This object should only be
12361 + * accessible to functions that are authorized to trigger notifications for this
12362 + * module.  Observers do not need this object. */
12363 +extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object);
12364 +
12365 +/** This function unregisters an observable module.  All observers have to be
12366 + * removed prior to unregistration. */
12367 +extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
12368 +
12369 +/** Add a module as an observer to the observable module.  The observable module
12370 + * needs to have previously registered with the notification manager.
12371 + *
12372 + * @param observer The observer module
12373 + * @param object The module to observe
12374 + * @param notification The notification to observe
12375 + * @param callback The callback function to call
12376 + * @param user_data Any additional user data to pass into the callback function */
12377 +extern int dwc_add_observer(void *observer, void *object, char *notification,
12378 +                           dwc_notifier_callback_t callback, void *user_data);
12379 +
12380 +/** Removes the specified observer from all notifications that it is currently
12381 + * observing. */
12382 +extern int dwc_remove_observer(void *observer);
12383 +
12384 +/** This function triggers a Notification.  It should be called by the
12385 + * observable module, or any module or library which the observable module
12386 + * allows to trigger notification on it's behalf.  Such as the dwc_cc_t.
12387 + *
12388 + * dwc_notify is a non-blocking function.  Callbacks are scheduled called in
12389 + * their own process context for each trigger.  Callbacks can be blocking.
12390 + * dwc_notify can be called from interrupt context if needed.
12391 + *
12392 + */
12393 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
12394 +
12395 +#ifdef __cplusplus
12396 +}
12397 +#endif
12398 +
12399 +#endif /* __DWC_NOTIFIER_H__ */
12400 diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h
12401 new file mode 100644
12402 index 0000000..308ddd5
12403 --- /dev/null
12404 +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
12405 @@ -0,0 +1,1260 @@
12406 +/* =========================================================================
12407 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
12408 + * $Revision: #14 $
12409 + * $Date: 2010/11/04 $
12410 + * $Change: 1621695 $
12411 + *
12412 + * Synopsys Portability Library Software and documentation
12413 + * (hereinafter, "Software") is an Unsupported proprietary work of
12414 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
12415 + * between Synopsys and you.
12416 + *
12417 + * The Software IS NOT an item of Licensed Software or Licensed Product
12418 + * under any End User Software License Agreement or Agreement for
12419 + * Licensed Product with Synopsys or any supplement thereto. You are
12420 + * permitted to use and redistribute this Software in source and binary
12421 + * forms, with or without modification, provided that redistributions
12422 + * of source code must retain this notice. You may not view, use,
12423 + * disclose, copy or distribute this file or any information contained
12424 + * herein except pursuant to this license grant from Synopsys. If you
12425 + * do not agree with this notice, including the disclaimer below, then
12426 + * you are not authorized to use the Software.
12427 + *
12428 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
12429 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12430 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12431 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
12432 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
12433 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
12434 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
12435 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
12436 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12437 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
12438 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
12439 + * DAMAGE.
12440 + * ========================================================================= */
12441 +#ifndef _DWC_OS_H_
12442 +#define _DWC_OS_H_
12443 +
12444 +#ifdef __cplusplus
12445 +extern "C" {
12446 +#endif
12447 +
12448 +/** @file
12449 + *
12450 + * DWC portability library, low level os-wrapper functions
12451 + *
12452 + */
12453 +
12454 +/* These basic types need to be defined by some OS header file or custom header
12455 + * file for your specific target architecture.
12456 + *
12457 + * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
12458 + *
12459 + * Any custom or alternate header file must be added and enabled here.
12460 + */
12461 +
12462 +#ifdef DWC_LINUX
12463 +# include <linux/types.h>
12464 +# ifdef CONFIG_DEBUG_MUTEXES
12465 +#  include <linux/mutex.h>
12466 +# endif
12467 +# include <linux/errno.h>
12468 +# include <stdarg.h>
12469 +#endif
12470 +
12471 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12472 +# include <os_dep.h>
12473 +#endif
12474 +
12475 +
12476 +/** @name Primitive Types and Values */
12477 +
12478 +/** We define a boolean type for consistency.  Can be either YES or NO */
12479 +typedef uint8_t dwc_bool_t;
12480 +#define YES  1
12481 +#define NO   0
12482 +
12483 +#ifdef DWC_LINUX
12484 +
12485 +/** @name Error Codes */
12486 +#define DWC_E_INVALID          EINVAL
12487 +#define DWC_E_NO_MEMORY                ENOMEM
12488 +#define DWC_E_NO_DEVICE                ENODEV
12489 +#define DWC_E_NOT_SUPPORTED    EOPNOTSUPP
12490 +#define DWC_E_TIMEOUT          ETIMEDOUT
12491 +#define DWC_E_BUSY             EBUSY
12492 +#define DWC_E_AGAIN            EAGAIN
12493 +#define DWC_E_RESTART          ERESTART
12494 +#define DWC_E_ABORT            ECONNABORTED
12495 +#define DWC_E_SHUTDOWN         ESHUTDOWN
12496 +#define DWC_E_NO_DATA          ENODATA
12497 +#define DWC_E_DISCONNECT       ECONNRESET
12498 +#define DWC_E_UNKNOWN          EINVAL
12499 +#define DWC_E_NO_STREAM_RES    ENOSR
12500 +#define DWC_E_COMMUNICATION    ECOMM
12501 +#define DWC_E_OVERFLOW         EOVERFLOW
12502 +#define DWC_E_PROTOCOL         EPROTO
12503 +#define DWC_E_IN_PROGRESS      EINPROGRESS
12504 +#define DWC_E_PIPE             EPIPE
12505 +#define DWC_E_IO               EIO
12506 +#define DWC_E_NO_SPACE         ENOSPC
12507 +
12508 +#else
12509 +
12510 +/** @name Error Codes */
12511 +#define DWC_E_INVALID          1001
12512 +#define DWC_E_NO_MEMORY                1002
12513 +#define DWC_E_NO_DEVICE                1003
12514 +#define DWC_E_NOT_SUPPORTED    1004
12515 +#define DWC_E_TIMEOUT          1005
12516 +#define DWC_E_BUSY             1006
12517 +#define DWC_E_AGAIN            1007
12518 +#define DWC_E_RESTART          1008
12519 +#define DWC_E_ABORT            1009
12520 +#define DWC_E_SHUTDOWN         1010
12521 +#define DWC_E_NO_DATA          1011
12522 +#define DWC_E_DISCONNECT       2000
12523 +#define DWC_E_UNKNOWN          3000
12524 +#define DWC_E_NO_STREAM_RES    4001
12525 +#define DWC_E_COMMUNICATION    4002
12526 +#define DWC_E_OVERFLOW         4003
12527 +#define DWC_E_PROTOCOL         4004
12528 +#define DWC_E_IN_PROGRESS      4005
12529 +#define DWC_E_PIPE             4006
12530 +#define DWC_E_IO               4007
12531 +#define DWC_E_NO_SPACE         4008
12532 +
12533 +#endif
12534 +
12535 +
12536 +/** @name Tracing/Logging Functions
12537 + *
12538 + * These function provide the capability to add tracing, debugging, and error
12539 + * messages, as well exceptions as assertions.  The WUDEV uses these
12540 + * extensively.  These could be logged to the main console, the serial port, an
12541 + * internal buffer, etc.  These functions could also be no-op if they are too
12542 + * expensive on your system.  By default undefining the DEBUG macro already
12543 + * no-ops some of these functions. */
12544 +
12545 +/** Returns non-zero if in interrupt context. */
12546 +extern dwc_bool_t DWC_IN_IRQ(void);
12547 +#define dwc_in_irq DWC_IN_IRQ
12548 +
12549 +/** Returns "IRQ" if DWC_IN_IRQ is true. */
12550 +static inline char *dwc_irq(void) {
12551 +       return DWC_IN_IRQ() ? "IRQ" : "";
12552 +}
12553 +
12554 +/** Returns non-zero if in bottom-half context. */
12555 +extern dwc_bool_t DWC_IN_BH(void);
12556 +#define dwc_in_bh DWC_IN_BH
12557 +
12558 +/** Returns "BH" if DWC_IN_BH is true. */
12559 +static inline char *dwc_bh(void) {
12560 +       return DWC_IN_BH() ? "BH" : "";
12561 +}
12562 +
12563 +/**
12564 + * A vprintf() clone.  Just call vprintf if you've got it.
12565 + */
12566 +extern void DWC_VPRINTF(char *format, va_list args);
12567 +#define dwc_vprintf DWC_VPRINTF
12568 +
12569 +/**
12570 + * A vsnprintf() clone.  Just call vprintf if you've got it.
12571 + */
12572 +extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
12573 +#define dwc_vsnprintf DWC_VSNPRINTF
12574 +
12575 +/**
12576 + * printf() clone.  Just call printf if you've go it.
12577 + */
12578 +extern void DWC_PRINTF(char *format, ...)
12579 +/* This provides compiler level static checking of the parameters if you're
12580 + * using GCC. */
12581 +#ifdef __GNUC__
12582 +       __attribute__ ((format(printf, 1, 2)));
12583 +#else
12584 +       ;
12585 +#endif
12586 +#define dwc_printf DWC_PRINTF
12587 +
12588 +/**
12589 + * sprintf() clone.  Just call sprintf if you've got it.
12590 + */
12591 +extern int DWC_SPRINTF(char *string, char *format, ...)
12592 +#ifdef __GNUC__
12593 +       __attribute__ ((format(printf, 2, 3)));
12594 +#else
12595 +       ;
12596 +#endif
12597 +#define dwc_sprintf DWC_SPRINTF
12598 +
12599 +/**
12600 + * snprintf() clone.  Just call snprintf if you've got it.
12601 + */
12602 +extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
12603 +#ifdef __GNUC__
12604 +       __attribute__ ((format(printf, 3, 4)));
12605 +#else
12606 +       ;
12607 +#endif
12608 +#define dwc_snprintf DWC_SNPRINTF
12609 +
12610 +/**
12611 + * Prints a WARNING message.  On systems that don't differentiate between
12612 + * warnings and regular log messages, just print it.  Indicates that something
12613 + * may be wrong with the driver.  Works like printf().
12614 + *
12615 + * Use the DWC_WARN macro to call this function.
12616 + */
12617 +extern void __DWC_WARN(char *format, ...)
12618 +#ifdef __GNUC__
12619 +       __attribute__ ((format(printf, 1, 2)));
12620 +#else
12621 +       ;
12622 +#endif
12623 +
12624 +/**
12625 + * Prints an error message.  On systems that don't differentiate between errors
12626 + * and regular log messages, just print it.  Indicates that something went wrong
12627 + * with the driver.  Works like printf().
12628 + *
12629 + * Use the DWC_ERROR macro to call this function.
12630 + */
12631 +extern void __DWC_ERROR(char *format, ...)
12632 +#ifdef __GNUC__
12633 +       __attribute__ ((format(printf, 1, 2)));
12634 +#else
12635 +       ;
12636 +#endif
12637 +
12638 +/**
12639 + * Prints an exception error message and takes some user-defined action such as
12640 + * print out a backtrace or trigger a breakpoint.  Indicates that something went
12641 + * abnormally wrong with the driver such as programmer error, or other
12642 + * exceptional condition.  It should not be ignored so even on systems without
12643 + * printing capability, some action should be taken to notify the developer of
12644 + * it.  Works like printf().
12645 + */
12646 +extern void DWC_EXCEPTION(char *format, ...)
12647 +#ifdef __GNUC__
12648 +       __attribute__ ((format(printf, 1, 2)));
12649 +#else
12650 +       ;
12651 +#endif
12652 +#define dwc_exception DWC_EXCEPTION
12653 +
12654 +#ifndef DWC_OTG_DEBUG_LEV
12655 +#define DWC_OTG_DEBUG_LEV 0
12656 +#endif
12657 +   
12658 +#ifdef DEBUG
12659 +/**
12660 + * Prints out a debug message.  Used for logging/trace messages.
12661 + *
12662 + * Use the DWC_DEBUG macro to call this function
12663 + */
12664 +extern void __DWC_DEBUG(char *format, ...)
12665 +#ifdef __GNUC__
12666 +       __attribute__ ((format(printf, 1, 2)));
12667 +#else
12668 +       ;
12669 +#endif
12670 +#else
12671 +#define __DWC_DEBUG printk
12672 +#endif
12673 +
12674 +/**
12675 + * Prints out a Debug message.
12676 + */
12677 +#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \
12678 +                                                __func__, dwc_irq(), ## _args)
12679 +#define dwc_debug DWC_DEBUG
12680 +/**
12681 + * Prints out a Debug message if enabled at compile time.
12682 + */
12683 +#if DWC_OTG_DEBUG_LEV > 0
12684 +#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args )
12685 +#else
12686 +#define DWC_DEBUGC(_format, _args...)
12687 +#endif
12688 +#define dwc_debugc DWC_DEBUGC
12689 +/**
12690 + * Prints out an informative message.
12691 + */
12692 +#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \
12693 +                                              dwc_irq(), ## _args)
12694 +#define dwc_info DWC_INFO
12695 +/**
12696 + * Prints out an informative message if enabled at compile time.
12697 + */
12698 +#if DWC_OTG_DEBUG_LEV > 1
12699 +#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args )
12700 +#else
12701 +#define DWC_INFOC(_format, _args...)
12702 +#endif
12703 +#define dwc_infoc DWC_INFOC
12704 +/**
12705 + * Prints out a warning message.
12706 + */
12707 +#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \
12708 +                                       dwc_irq(), __func__, __LINE__, ## _args)
12709 +#define dwc_warn DWC_WARN
12710 +/**
12711 + * Prints out an error message.
12712 + */
12713 +#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \
12714 +                                       dwc_irq(), __func__, __LINE__, ## _args)
12715 +#define dwc_error DWC_ERROR
12716 +
12717 +#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \
12718 +                                               dwc_irq(), __func__, __LINE__, ## _args)
12719 +#define dwc_proto_error DWC_PROTO_ERROR
12720 +
12721 +#ifdef DEBUG
12722 +/** Prints out a exception error message if the _expr expression fails.  Disabled
12723 + * if DEBUG is not enabled. */
12724 +#define DWC_ASSERT(_expr, _format, _args...) do { \
12725 +       if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \
12726 +                                     __FILE__, __LINE__, ## _args); } \
12727 +       } while (0)
12728 +#else
12729 +#define DWC_ASSERT(_x...)
12730 +#endif
12731 +#define dwc_assert DWC_ASSERT
12732 +
12733 +
12734 +/** @name Byte Ordering
12735 + * The following functions are for conversions between processor's byte ordering
12736 + * and specific ordering you want.
12737 + */
12738 +
12739 +/** Converts 32 bit data in CPU byte ordering to little endian. */
12740 +extern uint32_t DWC_CPU_TO_LE32(uint32_t *p);
12741 +#define dwc_cpu_to_le32 DWC_CPU_TO_LE32
12742 +
12743 +/** Converts 32 bit data in CPU byte orderint to big endian. */
12744 +extern uint32_t DWC_CPU_TO_BE32(uint32_t *p);
12745 +#define dwc_cpu_to_be32 DWC_CPU_TO_BE32
12746 +
12747 +/** Converts 32 bit little endian data to CPU byte ordering. */
12748 +extern uint32_t DWC_LE32_TO_CPU(uint32_t *p);
12749 +#define dwc_le32_to_cpu DWC_LE32_TO_CPU
12750 +
12751 +/** Converts 32 bit big endian data to CPU byte ordering. */
12752 +extern uint32_t DWC_BE32_TO_CPU(uint32_t *p);
12753 +#define dwc_be32_to_cpu DWC_BE32_TO_CPU
12754 +
12755 +/** Converts 16 bit data in CPU byte ordering to little endian. */
12756 +extern uint16_t DWC_CPU_TO_LE16(uint16_t *p);
12757 +#define dwc_cpu_to_le16 DWC_CPU_TO_LE16
12758 +
12759 +/** Converts 16 bit data in CPU byte orderint to big endian. */
12760 +extern uint16_t DWC_CPU_TO_BE16(uint16_t *p);
12761 +#define dwc_cpu_to_be16 DWC_CPU_TO_BE16
12762 +
12763 +/** Converts 16 bit little endian data to CPU byte ordering. */
12764 +extern uint16_t DWC_LE16_TO_CPU(uint16_t *p);
12765 +#define dwc_le16_to_cpu DWC_LE16_TO_CPU
12766 +
12767 +/** Converts 16 bit bi endian data to CPU byte ordering. */
12768 +extern uint16_t DWC_BE16_TO_CPU(uint16_t *p);
12769 +#define dwc_be16_to_cpu DWC_BE16_TO_CPU
12770 +
12771 +
12772 +/** @name Register Read/Write
12773 + *
12774 + * The following six functions should be implemented to read/write registers of
12775 + * 32-bit and 64-bit sizes.  All modules use this to read/write register values.
12776 + * The reg value is a pointer to the register calculated from the void *base
12777 + * variable passed into the driver when it is started.  */
12778 +
12779 +#ifdef DWC_LINUX
12780 +/* Linux doesn't need any extra parameters for register read/write, so we
12781 + * just throw away the IO context parameter.
12782 + */
12783 +/** Reads the content of a 32-bit register. */
12784 +extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
12785 +#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_)
12786 +
12787 +/** Reads the content of a 64-bit register. */
12788 +extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
12789 +#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_)
12790 +
12791 +/** Writes to a 32-bit register. */
12792 +extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
12793 +#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_)
12794 +
12795 +/** Writes to a 64-bit register. */
12796 +extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
12797 +#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_)
12798 +
12799 +/**
12800 + * Modify bit values in a register.  Using the
12801 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12802 + */
12803 +extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12804 +#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_)
12805 +extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12806 +#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_)
12807 +
12808 +#endif /* DWC_LINUX */
12809 +
12810 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12811 +typedef struct dwc_ioctx {
12812 +       struct device *dev;
12813 +       bus_space_tag_t iot;
12814 +       bus_space_handle_t ioh;
12815 +} dwc_ioctx_t;
12816 +
12817 +/** BSD needs two extra parameters for register read/write, so we pass
12818 + * them in using the IO context parameter.
12819 + */
12820 +/** Reads the content of a 32-bit register. */
12821 +extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg);
12822 +#define dwc_read_reg32 DWC_READ_REG32
12823 +
12824 +/** Reads the content of a 64-bit register. */
12825 +extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg);
12826 +#define dwc_read_reg64 DWC_READ_REG64
12827 +
12828 +/** Writes to a 32-bit register. */
12829 +extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value);
12830 +#define dwc_write_reg32 DWC_WRITE_REG32
12831 +
12832 +/** Writes to a 64-bit register. */
12833 +extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value);
12834 +#define dwc_write_reg64 DWC_WRITE_REG64
12835 +
12836 +/**
12837 + * Modify bit values in a register.  Using the
12838 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12839 + */
12840 +extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12841 +#define dwc_modify_reg32 DWC_MODIFY_REG32
12842 +extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12843 +#define dwc_modify_reg64 DWC_MODIFY_REG64
12844 +
12845 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12846 +
12847 +/** @cond */
12848 +
12849 +/** @name Some convenience MACROS used internally.  Define DWC_DEBUG_REGS to log the
12850 + * register writes. */
12851 +
12852 +#ifdef DWC_LINUX
12853 +
12854 +# ifdef DWC_DEBUG_REGS
12855 +
12856 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12857 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12858 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
12859 +} \
12860 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12861 +       DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12862 +                 &(((uint32_t*)container->regs->_reg)[num]), data); \
12863 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12864 +}
12865 +
12866 +#define dwc_define_read_write_reg(_reg,_container_type) \
12867 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12868 +       return DWC_READ_REG32(&container->regs->_reg); \
12869 +} \
12870 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12871 +       DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12872 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
12873 +}
12874 +
12875 +# else /* DWC_DEBUG_REGS */
12876 +
12877 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12878 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12879 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
12880 +} \
12881 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12882 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12883 +}
12884 +
12885 +#define dwc_define_read_write_reg(_reg,_container_type) \
12886 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12887 +       return DWC_READ_REG32(&container->regs->_reg); \
12888 +} \
12889 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12890 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
12891 +}
12892 +
12893 +# endif        /* DWC_DEBUG_REGS */
12894 +
12895 +#endif /* DWC_LINUX */
12896 +
12897 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12898 +
12899 +# ifdef DWC_DEBUG_REGS
12900 +
12901 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12902 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12903 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12904 +} \
12905 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12906 +       DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12907 +                 &(((uint32_t*)container->regs->_reg)[num]), data); \
12908 +       DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12909 +}
12910 +
12911 +#define dwc_define_read_write_reg(_reg,_container_type) \
12912 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12913 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12914 +} \
12915 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12916 +       DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12917 +       DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12918 +}
12919 +
12920 +# else /* DWC_DEBUG_REGS */
12921 +
12922 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12923 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12924 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12925 +} \
12926 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12927 +       DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12928 +}
12929 +
12930 +#define dwc_define_read_write_reg(_reg,_container_type) \
12931 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12932 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12933 +} \
12934 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12935 +       DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12936 +}
12937 +
12938 +# endif        /* DWC_DEBUG_REGS */
12939 +
12940 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12941 +
12942 +/** @endcond */
12943 +
12944 +
12945 +#ifdef DWC_CRYPTOLIB
12946 +/** @name Crypto Functions
12947 + *
12948 + * These are the low-level cryptographic functions used by the driver. */
12949 +
12950 +/** Perform AES CBC */
12951 +extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
12952 +#define dwc_aes_cbc DWC_AES_CBC
12953 +
12954 +/** Fill the provided buffer with random bytes.  These should be cryptographic grade random numbers. */
12955 +extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
12956 +#define dwc_random_bytes DWC_RANDOM_BYTES
12957 +
12958 +/** Perform the SHA-256 hash function */
12959 +extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
12960 +#define dwc_sha256 DWC_SHA256
12961 +
12962 +/** Calculated the HMAC-SHA256 */
12963 +extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
12964 +#define dwc_hmac_sha256 DWC_HMAC_SHA256
12965 +
12966 +#endif /* DWC_CRYPTOLIB */
12967 +
12968 +
12969 +/** @name Memory Allocation
12970 + *
12971 + * These function provide access to memory allocation.  There are only 2 DMA
12972 + * functions and 3 Regular memory functions that need to be implemented.  None
12973 + * of the memory debugging routines need to be implemented.  The allocation
12974 + * routines all ZERO the contents of the memory.
12975 + *
12976 + * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering.
12977 + * This checks for memory leaks, keeping track of alloc/free pairs.  It also
12978 + * keeps track of how much memory the driver is using at any given time. */
12979 +
12980 +#define DWC_PAGE_SIZE 4096
12981 +#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
12982 +#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
12983 +
12984 +#define DWC_INVALID_DMA_ADDR 0x0
12985 +
12986 +#ifdef DWC_LINUX
12987 +/** Type for a DMA address */
12988 +typedef dma_addr_t dwc_dma_t;
12989 +#endif
12990 +
12991 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12992 +typedef bus_addr_t dwc_dma_t;
12993 +#endif
12994 +
12995 +#ifdef DWC_FREEBSD
12996 +typedef struct dwc_dmactx {
12997 +       struct device *dev;
12998 +       bus_dma_tag_t dma_tag;
12999 +       bus_dmamap_t dma_map;
13000 +       bus_addr_t dma_paddr;
13001 +       void *dma_vaddr;
13002 +} dwc_dmactx_t;
13003 +#endif
13004 +
13005 +#ifdef DWC_NETBSD
13006 +typedef struct dwc_dmactx {
13007 +       struct device *dev;
13008 +       bus_dma_tag_t dma_tag;
13009 +       bus_dmamap_t dma_map;
13010 +       bus_dma_segment_t segs[1];
13011 +       int nsegs;
13012 +       bus_addr_t dma_paddr;
13013 +       void *dma_vaddr;
13014 +} dwc_dmactx_t;
13015 +#endif
13016 +
13017 +/* @todo these functions will be added in the future */
13018 +#if 0
13019 +/**
13020 + * Creates a DMA pool from which you can allocate DMA buffers.  Buffers
13021 + * allocated from this pool will be guaranteed to meet the size, alignment, and
13022 + * boundary requirements specified.
13023 + *
13024 + * @param[in] size Specifies the size of the buffers that will be allocated from
13025 + * this pool.
13026 + * @param[in] align Specifies the byte alignment requirements of the buffers
13027 + * allocated from this pool.  Must be a power of 2.
13028 + * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
13029 + * this pool must not cross.
13030 + *
13031 + * @returns A pointer to an internal opaque structure which is not to be
13032 + * accessed outside of these library functions.  Use this handle to specify
13033 + * which pools to allocate/free DMA buffers from and also to destroy the pool,
13034 + * when you are done with it.
13035 + */
13036 +extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
13037 +
13038 +/**
13039 + * Destroy a DMA pool.  All buffers allocated from that pool must be freed first.
13040 + */
13041 +extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
13042 +
13043 +/**
13044 + * Allocate a buffer from the specified DMA pool and zeros its contents.
13045 + */
13046 +extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
13047 +
13048 +/**
13049 + * Free a previously allocated buffer from the DMA pool.
13050 + */
13051 +extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
13052 +#endif
13053 +
13054 +/** Allocates a DMA capable buffer and zeroes its contents. */
13055 +extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
13056 +
13057 +/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
13058 +extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
13059 +
13060 +/** Frees a previously allocated buffer. */
13061 +extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
13062 +
13063 +/** Allocates a block of memory and zeroes its contents. */
13064 +extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size);
13065 +
13066 +/** Allocates a block of memory and zeroes its contents, in an atomic manner
13067 + * which can be used inside interrupt context.  The size should be sufficiently
13068 + * small, a few KB at most, such that failures are not likely to occur.  Can just call
13069 + * __DWC_ALLOC if it is atomic. */
13070 +extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size);
13071 +
13072 +/** Frees a previously allocated buffer. */
13073 +extern void __DWC_FREE(void *mem_ctx, void *addr);
13074 +
13075 +#ifndef DWC_DEBUG_MEMORY
13076 +
13077 +#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_)
13078 +#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_)
13079 +#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_)
13080 +
13081 +# ifdef DWC_LINUX
13082 +#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_)
13083 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_)
13084 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_)
13085 +# endif
13086 +
13087 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13088 +#define DWC_DMA_ALLOC __DWC_DMA_ALLOC
13089 +#define DWC_DMA_FREE __DWC_DMA_FREE
13090 +# endif
13091 +extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
13092 +
13093 +#else  /* DWC_DEBUG_MEMORY */
13094 +
13095 +extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line);
13096 +extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line);
13097 +extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line);
13098 +extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
13099 +                                char const *func, int line);
13100 +extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, 
13101 +                               char const *func, int line);
13102 +extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
13103 +                              dwc_dma_t dma_addr, char const *func, int line);
13104 +
13105 +extern int dwc_memory_debug_start(void *mem_ctx);
13106 +extern void dwc_memory_debug_stop(void);
13107 +extern void dwc_memory_debug_report(void);
13108 +
13109 +#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__)
13110 +#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \
13111 +                                                       __func__, __LINE__)
13112 +#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__)
13113 +
13114 +# ifdef DWC_LINUX
13115 +#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \
13116 +                                               _dma_, __func__, __LINE__)
13117 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \
13118 +                                               _dma_, __func__, __LINE__)
13119 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \
13120 +                                               _virt_, _dma_, __func__, __LINE__)
13121 +# endif
13122 +
13123 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13124 +#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \
13125 +                                               _dma_, __func__, __LINE__)
13126 +#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \
13127 +                                                _virt_, _dma_, __func__, __LINE__)
13128 +# endif
13129 +
13130 +#endif /* DWC_DEBUG_MEMORY */
13131 +
13132 +#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_)
13133 +#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_)
13134 +#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_)
13135 +
13136 +#ifdef DWC_LINUX
13137 +/* Linux doesn't need any extra parameters for DMA buffer allocation, so we
13138 + * just throw away the DMA context parameter.
13139 + */
13140 +#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_)
13141 +#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_)
13142 +#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_)
13143 +#endif
13144 +
13145 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13146 +/** BSD needs several extra parameters for DMA buffer allocation, so we pass
13147 + * them in using the DMA context parameter.
13148 + */
13149 +#define dwc_dma_alloc DWC_DMA_ALLOC
13150 +#define dwc_dma_free DWC_DMA_FREE
13151 +#endif
13152 +
13153 +
13154 +/** @name Memory and String Processing */
13155 +
13156 +/** memset() clone */
13157 +extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
13158 +#define dwc_memset DWC_MEMSET
13159 +
13160 +/** memcpy() clone */
13161 +extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
13162 +#define dwc_memcpy DWC_MEMCPY
13163 +
13164 +/** memmove() clone */
13165 +extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
13166 +#define dwc_memmove DWC_MEMMOVE
13167 +
13168 +/** memcmp() clone */
13169 +extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
13170 +#define dwc_memcmp DWC_MEMCMP
13171 +
13172 +/** strcmp() clone */
13173 +extern int DWC_STRCMP(void *s1, void *s2);
13174 +#define dwc_strcmp DWC_STRCMP
13175 +
13176 +/** strncmp() clone */
13177 +extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
13178 +#define dwc_strncmp DWC_STRNCMP
13179 +
13180 +/** strlen() clone, for NULL terminated ASCII strings */
13181 +extern int DWC_STRLEN(char const *str);
13182 +#define dwc_strlen DWC_STRLEN
13183 +
13184 +/** strcpy() clone, for NULL terminated ASCII strings */
13185 +extern char *DWC_STRCPY(char *to, const char *from);
13186 +#define dwc_strcpy DWC_STRCPY
13187 +
13188 +/** strdup() clone.  If you wish to use memory allocation debugging, this
13189 + * implementation of strdup should use the DWC_* memory routines instead of
13190 + * calling a predefined strdup.  Otherwise the memory allocated by this routine
13191 + * will not be seen by the debugging routines. */
13192 +extern char *DWC_STRDUP(char const *str);
13193 +#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_)
13194 +
13195 +/** NOT an atoi() clone.  Read the description carefully.  Returns an integer
13196 + * converted from the string str in base 10 unless the string begins with a "0x"
13197 + * in which case it is base 16.  String must be a NULL terminated sequence of
13198 + * ASCII characters and may optionally begin with whitespace, a + or -, and a
13199 + * "0x" prefix if base 16.  The remaining characters must be valid digits for
13200 + * the number and end with a NULL character.  If any invalid characters are
13201 + * encountered or it returns with a negative error code and the results of the
13202 + * conversion are undefined.  On sucess it returns 0.  Overflow conditions are
13203 + * undefined.  An example implementation using atoi() can be referenced from the
13204 + * Linux implementation. */
13205 +extern int DWC_ATOI(const char *str, int32_t *value);
13206 +#define dwc_atoi DWC_ATOI
13207 +
13208 +/** Same as above but for unsigned. */
13209 +extern int DWC_ATOUI(const char *str, uint32_t *value);
13210 +#define dwc_atoui DWC_ATOUI
13211 +
13212 +#ifdef DWC_UTFLIB
13213 +/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
13214 +extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
13215 +#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
13216 +#endif
13217 +
13218 +
13219 +/** @name Wait queues
13220 + *
13221 + * Wait queues provide a means of synchronizing between threads or processes.  A
13222 + * process can block on a waitq if some condition is not true, waiting for it to
13223 + * become true.  When the waitq is triggered all waiting process will get
13224 + * unblocked and the condition will be check again.  Waitqs should be triggered
13225 + * every time a condition can potentially change.*/
13226 +struct dwc_waitq;
13227 +
13228 +/** Type for a waitq */
13229 +typedef struct dwc_waitq dwc_waitq_t;
13230 +
13231 +/** The type of waitq condition callback function.  This is called every time
13232 + * condition is evaluated. */
13233 +typedef int (*dwc_waitq_condition_t)(void *data);
13234 +
13235 +/** Allocate a waitq */
13236 +extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
13237 +#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC()
13238 +
13239 +/** Free a waitq */
13240 +extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
13241 +#define dwc_waitq_free DWC_WAITQ_FREE
13242 +
13243 +/** Check the condition and if it is false, block on the waitq.  When unblocked, check the
13244 + * condition again.  The function returns when the condition becomes true.  The return value
13245 + * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
13246 +extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data);
13247 +#define dwc_waitq_wait DWC_WAITQ_WAIT
13248 +
13249 +/** Check the condition and if it is false, block on the waitq.  When unblocked,
13250 + * check the condition again.  The function returns when the condition become
13251 + * true or the timeout has passed.  The return value is 0 on condition true or
13252 + * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
13253 + * error. */
13254 +extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
13255 +                                     void *data, int32_t msecs);
13256 +#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
13257 +
13258 +/** Trigger a waitq, unblocking all processes.  This should be called whenever a condition
13259 + * has potentially changed. */
13260 +extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
13261 +#define dwc_waitq_trigger DWC_WAITQ_TRIGGER
13262 +
13263 +/** Unblock all processes waiting on the waitq with an ABORTED result. */
13264 +extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
13265 +#define dwc_waitq_abort DWC_WAITQ_ABORT
13266 +
13267 +
13268 +/** @name Threads
13269 + *
13270 + * A thread must be explicitly stopped.  It must check DWC_THREAD_SHOULD_STOP
13271 + * whenever it is woken up, and then return.  The DWC_THREAD_STOP function
13272 + * returns the value from the thread.
13273 + */
13274 +
13275 +struct dwc_thread;
13276 +
13277 +/** Type for a thread */
13278 +typedef struct dwc_thread dwc_thread_t;
13279 +
13280 +/** The thread function */
13281 +typedef int (*dwc_thread_function_t)(void *data);
13282 +
13283 +/** Create a thread and start it running the thread_function.  Returns a handle
13284 + * to the thread */
13285 +extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data);
13286 +#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_)
13287 +
13288 +/** Stops a thread.  Return the value returned by the thread.  Or will return
13289 + * DWC_ABORT if the thread never started. */
13290 +extern int DWC_THREAD_STOP(dwc_thread_t *thread);
13291 +#define dwc_thread_stop DWC_THREAD_STOP
13292 +
13293 +/** Signifies to the thread that it must stop. */
13294 +#ifdef DWC_LINUX
13295 +/* Linux doesn't need any parameters for kthread_should_stop() */
13296 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
13297 +#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP()
13298 +
13299 +/* No thread_exit function in Linux */
13300 +#define dwc_thread_exit(_thrd_)
13301 +#endif
13302 +
13303 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13304 +/** BSD needs the thread pointer for kthread_suspend_check() */
13305 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread);
13306 +#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
13307 +
13308 +/** The thread must call this to exit. */
13309 +extern void DWC_THREAD_EXIT(dwc_thread_t *thread);
13310 +#define dwc_thread_exit DWC_THREAD_EXIT
13311 +#endif
13312 +
13313 +
13314 +/** @name Work queues
13315 + *
13316 + * Workqs are used to queue a callback function to be called at some later time,
13317 + * in another thread. */
13318 +struct dwc_workq;
13319 +
13320 +/** Type for a workq */
13321 +typedef struct dwc_workq dwc_workq_t;
13322 +
13323 +/** The type of the callback function to be called. */
13324 +typedef void (*dwc_work_callback_t)(void *data);
13325 +
13326 +/** Allocate a workq */
13327 +extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
13328 +#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_)
13329 +
13330 +/** Free a workq.  All work must be completed before being freed. */
13331 +extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
13332 +#define dwc_workq_free DWC_WORKQ_FREE
13333 +
13334 +/** Schedule a callback on the workq, passing in data.  The function will be
13335 + * scheduled at some later time. */
13336 +extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb,
13337 +                              void *data, char *format, ...)
13338 +#ifdef __GNUC__
13339 +       __attribute__ ((format(printf, 4, 5)));
13340 +#else
13341 +       ;
13342 +#endif
13343 +#define dwc_workq_schedule DWC_WORKQ_SCHEDULE
13344 +
13345 +/** Schedule a callback on the workq, that will be called until at least
13346 + * given number miliseconds have passed. */
13347 +extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb,
13348 +                                      void *data, uint32_t time, char *format, ...)
13349 +#ifdef __GNUC__
13350 +       __attribute__ ((format(printf, 5, 6)));
13351 +#else
13352 +       ;
13353 +#endif
13354 +#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
13355 +
13356 +/** The number of processes in the workq */
13357 +extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
13358 +#define dwc_workq_pending DWC_WORKQ_PENDING
13359 +
13360 +/** Blocks until all the work in the workq is complete or timed out.  Returns <
13361 + * 0 on timeout. */
13362 +extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
13363 +#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
13364 +
13365 +
13366 +/** @name Tasklets
13367 + *
13368 + */
13369 +struct dwc_tasklet;
13370 +
13371 +/** Type for a tasklet */
13372 +typedef struct dwc_tasklet dwc_tasklet_t;
13373 +
13374 +/** The type of the callback function to be called */
13375 +typedef void (*dwc_tasklet_callback_t)(void *data);
13376 +
13377 +/** Allocates a tasklet */
13378 +extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data);
13379 +#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_)
13380 +
13381 +/** Frees a tasklet */
13382 +extern void DWC_TASK_FREE(dwc_tasklet_t *task);
13383 +#define dwc_task_free DWC_TASK_FREE
13384 +
13385 +/** Schedules a tasklet to run */
13386 +extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
13387 +#define dwc_task_schedule DWC_TASK_SCHEDULE
13388 +
13389 +
13390 +/** @name Timer
13391 + *
13392 + * Callbacks must be small and atomic.
13393 + */
13394 +struct dwc_timer;
13395 +
13396 +/** Type for a timer */
13397 +typedef struct dwc_timer dwc_timer_t;
13398 +
13399 +/** The type of the callback function to be called */
13400 +typedef void (*dwc_timer_callback_t)(void *data);
13401 +
13402 +/** Allocates a timer */
13403 +extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
13404 +#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_)
13405 +
13406 +/** Frees a timer */
13407 +extern void DWC_TIMER_FREE(dwc_timer_t *timer);
13408 +#define dwc_timer_free DWC_TIMER_FREE
13409 +
13410 +/** Schedules the timer to run at time ms from now.  And will repeat at every
13411 + * repeat_interval msec therafter
13412 + *
13413 + * Modifies a timer that is still awaiting execution to a new expiration time.
13414 + * The mod_time is added to the old time.  */
13415 +extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
13416 +#define dwc_timer_schedule DWC_TIMER_SCHEDULE
13417 +
13418 +/** Disables the timer from execution. */
13419 +extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
13420 +#define dwc_timer_cancel DWC_TIMER_CANCEL
13421 +
13422 +
13423 +/** @name Spinlocks
13424 + *
13425 + * These locks are used when the work between the lock/unlock is atomic and
13426 + * short.  Interrupts are also disabled during the lock/unlock and thus they are
13427 + * suitable to lock between interrupt/non-interrupt context.  They also lock
13428 + * between processes if you have multiple CPUs or Preemption.  If you don't have
13429 + * multiple CPUS or Preemption, then the you can simply implement the
13430 + * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts.  Because
13431 + * the work between the lock/unlock is atomic, the process context will never
13432 + * change, and so you never have to lock between processes.  */
13433 +
13434 +struct dwc_spinlock;
13435 +
13436 +/** Type for a spinlock */
13437 +typedef struct dwc_spinlock dwc_spinlock_t;
13438 +
13439 +/** Type for the 'flags' argument to spinlock funtions */
13440 +typedef unsigned long dwc_irqflags_t;
13441 +
13442 +/** Returns an initialized lock variable.  This function should allocate and
13443 + * initialize the OS-specific data structure used for locking.  This data
13444 + * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
13445 + * be freed by the DWC_FREE_LOCK when it is no longer used. */
13446 +extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
13447 +#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC()
13448 +
13449 +/** Frees an initialized lock variable. */
13450 +extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
13451 +#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_)
13452 +
13453 +/** Disables interrupts and blocks until it acquires the lock.
13454 + *
13455 + * @param lock Pointer to the spinlock.
13456 + * @param flags Unsigned long for irq flags storage.
13457 + */
13458 +extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags);
13459 +#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
13460 +
13461 +/** Re-enables the interrupt and releases the lock.
13462 + *
13463 + * @param lock Pointer to the spinlock.
13464 + * @param flags Unsigned long for irq flags storage.  Must be the same as was
13465 + * passed into DWC_LOCK.
13466 + */
13467 +extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags);
13468 +#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
13469 +
13470 +/** Blocks until it acquires the lock.
13471 + *
13472 + * @param lock Pointer to the spinlock.
13473 + */
13474 +extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
13475 +#define dwc_spinlock DWC_SPINLOCK
13476 +
13477 +/** Releases the lock.
13478 + *
13479 + * @param lock Pointer to the spinlock.
13480 + */
13481 +extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
13482 +#define dwc_spinunlock DWC_SPINUNLOCK
13483 +
13484 +
13485 +/** @name Mutexes
13486 + *
13487 + * Unlike spinlocks Mutexes lock only between processes and the work between the
13488 + * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
13489 + */
13490 +
13491 +struct dwc_mutex;
13492 +
13493 +/** Type for a mutex */
13494 +typedef struct dwc_mutex dwc_mutex_t;
13495 +
13496 +/* For Linux Mutex Debugging make it inline because the debugging routines use
13497 + * the symbol to determine recursive locking.  This makes it falsely think
13498 + * recursive locking occurs. */
13499 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13500 +#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
13501 +       __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
13502 +       mutex_init((struct mutex *)__mutexp); \
13503 +})
13504 +#endif
13505 +
13506 +/** Allocate a mutex */
13507 +extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
13508 +#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC()
13509 +
13510 +/* For memory leak debugging when using Linux Mutex Debugging */
13511 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13512 +#define DWC_MUTEX_FREE(__mutexp) do { \
13513 +       mutex_destroy((struct mutex *)__mutexp); \
13514 +       DWC_FREE(__mutexp); \
13515 +} while(0)
13516 +#else
13517 +/** Free a mutex */
13518 +extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
13519 +#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_)
13520 +#endif
13521 +
13522 +/** Lock a mutex */
13523 +extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
13524 +#define dwc_mutex_lock DWC_MUTEX_LOCK
13525 +
13526 +/** Non-blocking lock returns 1 on successful lock. */
13527 +extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
13528 +#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
13529 +
13530 +/** Unlock a mutex */
13531 +extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
13532 +#define dwc_mutex_unlock DWC_MUTEX_UNLOCK
13533 +
13534 +
13535 +/** @name Time */
13536 +
13537 +/** Microsecond delay.
13538 + *
13539 + * @param usecs  Microseconds to delay.
13540 + */
13541 +extern void DWC_UDELAY(uint32_t usecs);
13542 +#define dwc_udelay DWC_UDELAY
13543 +
13544 +/** Millisecond delay.
13545 + *
13546 + * @param msecs  Milliseconds to delay.
13547 + */
13548 +extern void DWC_MDELAY(uint32_t msecs);
13549 +#define dwc_mdelay DWC_MDELAY
13550 +
13551 +/** Non-busy waiting.
13552 + * Sleeps for specified number of milliseconds.
13553 + *
13554 + * @param msecs Milliseconds to sleep.
13555 + */
13556 +extern void DWC_MSLEEP(uint32_t msecs);
13557 +#define dwc_msleep DWC_MSLEEP
13558 +
13559 +/**
13560 + * Returns number of milliseconds since boot.
13561 + */
13562 +extern uint32_t DWC_TIME(void);
13563 +#define dwc_time DWC_TIME
13564 +
13565 +
13566 +
13567 +
13568 +/* @mainpage DWC Portability and Common Library
13569 + *
13570 + * This is the documentation for the DWC Portability and Common Library.
13571 + *
13572 + * @section intro Introduction
13573 + *
13574 + * The DWC Portability library consists of wrapper calls and data structures to
13575 + * all low-level functions which are typically provided by the OS.  The WUDEV
13576 + * driver uses only these functions.  In order to port the WUDEV driver, only
13577 + * the functions in this library need to be re-implemented, with the same
13578 + * behavior as documented here.
13579 + *
13580 + * The Common library consists of higher level functions, which rely only on
13581 + * calling the functions from the DWC Portability library.  These common
13582 + * routines are shared across modules.  Some of the common libraries need to be
13583 + * used directly by the driver programmer when porting WUDEV.  Such as the
13584 + * parameter and notification libraries.
13585 + *
13586 + * @section low Portability Library OS Wrapper Functions
13587 + *
13588 + * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
13589 + * needs to be implemented when porting, for example DWC_MUTEX_ALLOC().  All of
13590 + * these functions are included in the dwc_os.h file.
13591 + *
13592 + * There are many functions here covering a wide array of OS services.  Please
13593 + * see dwc_os.h for details, and implementation notes for each function.
13594 + *
13595 + * @section common Common Library Functions
13596 + *
13597 + * Any function starting with dwc and in all lowercase is a common library
13598 + * routine.  These functions have a portable implementation and do not need to
13599 + * be reimplemented when porting.  The common routines can be used by any
13600 + * driver, and some must be used by the end user to control the drivers.  For
13601 + * example, you must use the Parameter common library in order to set the
13602 + * parameters in the WUDEV module.
13603 + *
13604 + * The common libraries consist of the following:
13605 + *
13606 + * - Connection Contexts - Used internally and can be used by end-user.  See dwc_cc.h
13607 + * - Parameters - Used internally and can be used by end-user.  See dwc_params.h
13608 + * - Notifications - Used internally and can be used by end-user.  See dwc_notifier.h
13609 + * - Lists - Used internally and can be used by end-user.  See dwc_list.h
13610 + * - Memory Debugging - Used internally and can be used by end-user.  See dwc_os.h
13611 + * - Modpow - Used internally only.  See dwc_modpow.h
13612 + * - DH - Used internally only.  See dwc_dh.h
13613 + * - Crypto - Used internally only.  See dwc_crypto.h
13614 + *
13615 + *
13616 + * @section prereq Prerequistes For dwc_os.h
13617 + * @subsection types Data Types
13618 + *
13619 + * The dwc_os.h file assumes that several low-level data types are pre defined for the
13620 + * compilation environment.  These data types are:
13621 + *
13622 + * - uint8_t - unsigned 8-bit data type
13623 + * - int8_t - signed 8-bit data type
13624 + * - uint16_t - unsigned 16-bit data type
13625 + * - int16_t - signed 16-bit data type
13626 + * - uint32_t - unsigned 32-bit data type
13627 + * - int32_t - signed 32-bit data type
13628 + * - uint64_t - unsigned 64-bit data type
13629 + * - int64_t - signed 64-bit data type
13630 + *
13631 + * Ensure that these are defined before using dwc_os.h.  The easiest way to do
13632 + * that is to modify the top of the file to include the appropriate header.
13633 + * This is already done for the Linux environment.  If the DWC_LINUX macro is
13634 + * defined, the correct header will be added.  A standard header <stdint.h> is
13635 + * also used for environments where standard C headers are available.
13636 + *
13637 + * @subsection stdarg Variable Arguments
13638 + *
13639 + * Variable arguments are provided by a standard C header <stdarg.h>.  it is
13640 + * available in Both the Linux and ANSI C enviornment.  An equivalent must be
13641 + * provided in your enviornment in order to use dwc_os.h with the debug and
13642 + * tracing message functionality.
13643 + *
13644 + * @subsection thread Threading
13645 + *
13646 + * WUDEV Core must be run on an operating system that provides for multiple
13647 + * threads/processes.  Threading can be implemented in many ways, even in
13648 + * embedded systems without an operating system.  At the bare minimum, the
13649 + * system should be able to start any number of processes at any time to handle
13650 + * special work.  It need not be a pre-emptive system.  Process context can
13651 + * change upon a call to a blocking function.  The hardware interrupt context
13652 + * that calls the module's ISR() function must be differentiable from process
13653 + * context, even if your processes are impemented via a hardware interrupt.
13654 + * Further locking mechanism between process must exist (or be implemented), and
13655 + * process context must have a way to disable interrupts for a period of time to
13656 + * lock them out.  If all of this exists, the functions in dwc_os.h related to
13657 + * threading should be able to be implemented with the defined behavior.
13658 + *
13659 + */
13660 +
13661 +#ifdef __cplusplus
13662 +}
13663 +#endif
13664 +
13665 +#endif /* _DWC_OS_H_ */
13666 diff --git a/drivers/usb/host/dwc_common_port/usb.h b/drivers/usb/host/dwc_common_port/usb.h
13667 new file mode 100644
13668 index 0000000..27bda82
13669 --- /dev/null
13670 +++ b/drivers/usb/host/dwc_common_port/usb.h
13671 @@ -0,0 +1,946 @@
13672 +/*
13673 + * Copyright (c) 1998 The NetBSD Foundation, Inc.
13674 + * All rights reserved.
13675 + *
13676 + * This code is derived from software contributed to The NetBSD Foundation
13677 + * by Lennart Augustsson (lennart@augustsson.net) at
13678 + * Carlstedt Research & Technology.
13679 + *
13680 + * Redistribution and use in source and binary forms, with or without
13681 + * modification, are permitted provided that the following conditions
13682 + * are met:
13683 + * 1. Redistributions of source code must retain the above copyright
13684 + *    notice, this list of conditions and the following disclaimer.
13685 + * 2. Redistributions in binary form must reproduce the above copyright
13686 + *    notice, this list of conditions and the following disclaimer in the
13687 + *    documentation and/or other materials provided with the distribution.
13688 + * 3. All advertising materials mentioning features or use of this software
13689 + *    must display the following acknowledgement:
13690 + *        This product includes software developed by the NetBSD
13691 + *        Foundation, Inc. and its contributors.
13692 + * 4. Neither the name of The NetBSD Foundation nor the names of its
13693 + *    contributors may be used to endorse or promote products derived
13694 + *    from this software without specific prior written permission.
13695 + *
13696 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
13697 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13698 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
13699 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
13700 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13701 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13702 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
13703 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13704 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
13705 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
13706 + * POSSIBILITY OF SUCH DAMAGE.
13707 + */
13708 +
13709 +/* Modified by Synopsys, Inc, 12/12/2007 */
13710 +
13711 +
13712 +#ifndef _USB_H_
13713 +#define _USB_H_
13714 +
13715 +#ifdef __cplusplus
13716 +extern "C" {
13717 +#endif
13718 +
13719 +/*
13720 + * The USB records contain some unaligned little-endian word
13721 + * components.  The U[SG]ETW macros take care of both the alignment
13722 + * and endian problem and should always be used to access non-byte
13723 + * values.
13724 + */
13725 +typedef u_int8_t uByte;
13726 +typedef u_int8_t uWord[2];
13727 +typedef u_int8_t uDWord[4];
13728 +
13729 +#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
13730 +#define UCONSTW(x)     { (x) & 0xff, ((x) >> 8) & 0xff }
13731 +#define UCONSTDW(x)    { (x) & 0xff, ((x) >> 8) & 0xff, \
13732 +                         ((x) >> 16) & 0xff, ((x) >> 24) & 0xff }
13733 +
13734 +#if 1
13735 +#define UGETW(w) ((w)[0] | ((w)[1] << 8))
13736 +#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
13737 +#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
13738 +#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
13739 +                    (w)[1] = (u_int8_t)((v) >> 8), \
13740 +                    (w)[2] = (u_int8_t)((v) >> 16), \
13741 +                    (w)[3] = (u_int8_t)((v) >> 24))
13742 +#else
13743 +/*
13744 + * On little-endian machines that can handle unanliged accesses
13745 + * (e.g. i386) these macros can be replaced by the following.
13746 + */
13747 +#define UGETW(w) (*(u_int16_t *)(w))
13748 +#define USETW(w,v) (*(u_int16_t *)(w) = (v))
13749 +#define UGETDW(w) (*(u_int32_t *)(w))
13750 +#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
13751 +#endif
13752 +
13753 +/*
13754 + * Macros for accessing UAS IU fields, which are big-endian
13755 + */
13756 +#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l))
13757 +#define IUCONSTW(x)    { ((x) >> 8) & 0xff, (x) & 0xff }
13758 +#define IUCONSTDW(x)   { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
13759 +                       ((x) >> 8) & 0xff, (x) & 0xff }
13760 +#define IUGETW(w) (((w)[0] << 8) | (w)[1])
13761 +#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v))
13762 +#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
13763 +#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \
13764 +                     (w)[1] = (u_int8_t)((v) >> 16), \
13765 +                     (w)[2] = (u_int8_t)((v) >> 8), \
13766 +                     (w)[3] = (u_int8_t)(v))
13767 +
13768 +#define UPACKED __attribute__((__packed__))
13769 +
13770 +typedef struct {
13771 +       uByte           bmRequestType;
13772 +       uByte           bRequest;
13773 +       uWord           wValue;
13774 +       uWord           wIndex;
13775 +       uWord           wLength;
13776 +} UPACKED usb_device_request_t;
13777 +
13778 +#define UT_GET_DIR(a) ((a) & 0x80)
13779 +#define UT_WRITE               0x00
13780 +#define UT_READ                        0x80
13781 +
13782 +#define UT_GET_TYPE(a) ((a) & 0x60)
13783 +#define UT_STANDARD            0x00
13784 +#define UT_CLASS               0x20
13785 +#define UT_VENDOR              0x40
13786 +
13787 +#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
13788 +#define UT_DEVICE              0x00
13789 +#define UT_INTERFACE           0x01
13790 +#define UT_ENDPOINT            0x02
13791 +#define UT_OTHER               0x03
13792 +
13793 +#define UT_READ_DEVICE         (UT_READ  | UT_STANDARD | UT_DEVICE)
13794 +#define UT_READ_INTERFACE      (UT_READ  | UT_STANDARD | UT_INTERFACE)
13795 +#define UT_READ_ENDPOINT       (UT_READ  | UT_STANDARD | UT_ENDPOINT)
13796 +#define UT_WRITE_DEVICE                (UT_WRITE | UT_STANDARD | UT_DEVICE)
13797 +#define UT_WRITE_INTERFACE     (UT_WRITE | UT_STANDARD | UT_INTERFACE)
13798 +#define UT_WRITE_ENDPOINT      (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
13799 +#define UT_READ_CLASS_DEVICE   (UT_READ  | UT_CLASS | UT_DEVICE)
13800 +#define UT_READ_CLASS_INTERFACE        (UT_READ  | UT_CLASS | UT_INTERFACE)
13801 +#define UT_READ_CLASS_OTHER    (UT_READ  | UT_CLASS | UT_OTHER)
13802 +#define UT_READ_CLASS_ENDPOINT (UT_READ  | UT_CLASS | UT_ENDPOINT)
13803 +#define UT_WRITE_CLASS_DEVICE  (UT_WRITE | UT_CLASS | UT_DEVICE)
13804 +#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
13805 +#define UT_WRITE_CLASS_OTHER   (UT_WRITE | UT_CLASS | UT_OTHER)
13806 +#define UT_WRITE_CLASS_ENDPOINT        (UT_WRITE | UT_CLASS | UT_ENDPOINT)
13807 +#define UT_READ_VENDOR_DEVICE  (UT_READ  | UT_VENDOR | UT_DEVICE)
13808 +#define UT_READ_VENDOR_INTERFACE (UT_READ  | UT_VENDOR | UT_INTERFACE)
13809 +#define UT_READ_VENDOR_OTHER   (UT_READ  | UT_VENDOR | UT_OTHER)
13810 +#define UT_READ_VENDOR_ENDPOINT        (UT_READ  | UT_VENDOR | UT_ENDPOINT)
13811 +#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE)
13812 +#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
13813 +#define UT_WRITE_VENDOR_OTHER  (UT_WRITE | UT_VENDOR | UT_OTHER)
13814 +#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
13815 +
13816 +/* Requests */
13817 +#define UR_GET_STATUS          0x00
13818 +#define  USTAT_STANDARD_STATUS  0x00
13819 +#define  WUSTAT_WUSB_FEATURE    0x01
13820 +#define  WUSTAT_CHANNEL_INFO    0x02
13821 +#define  WUSTAT_RECEIVED_DATA   0x03
13822 +#define  WUSTAT_MAS_AVAILABILITY 0x04
13823 +#define  WUSTAT_CURRENT_TRANSMIT_POWER 0x05
13824 +#define UR_CLEAR_FEATURE       0x01
13825 +#define UR_SET_FEATURE         0x03
13826 +#define UR_SET_AND_TEST_FEATURE 0x0c
13827 +#define UR_SET_ADDRESS         0x05
13828 +#define UR_GET_DESCRIPTOR      0x06
13829 +#define  UDESC_DEVICE          0x01
13830 +#define  UDESC_CONFIG          0x02
13831 +#define  UDESC_STRING          0x03
13832 +#define  UDESC_INTERFACE       0x04
13833 +#define  UDESC_ENDPOINT                0x05
13834 +#define  UDESC_SS_USB_COMPANION        0x30
13835 +#define  UDESC_DEVICE_QUALIFIER        0x06
13836 +#define  UDESC_OTHER_SPEED_CONFIGURATION 0x07
13837 +#define  UDESC_INTERFACE_POWER 0x08
13838 +#define  UDESC_OTG             0x09
13839 +#define  WUDESC_SECURITY       0x0c
13840 +#define  WUDESC_KEY            0x0d
13841 +#define   WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)
13842 +#define   WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)
13843 +#define    WUD_KEY_TYPE_ASSOC    0x01
13844 +#define    WUD_KEY_TYPE_GTK      0x02
13845 +#define   WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)
13846 +#define    WUD_KEY_ORIGIN_HOST   0x00
13847 +#define    WUD_KEY_ORIGIN_DEVICE 0x01
13848 +#define  WUDESC_ENCRYPTION_TYPE        0x0e
13849 +#define  WUDESC_BOS            0x0f
13850 +#define  WUDESC_DEVICE_CAPABILITY 0x10
13851 +#define  WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11
13852 +#define  UDESC_BOS             0x0f
13853 +#define  UDESC_DEVICE_CAPABILITY 0x10
13854 +#define  UDESC_CS_DEVICE       0x21    /* class specific */
13855 +#define  UDESC_CS_CONFIG       0x22
13856 +#define  UDESC_CS_STRING       0x23
13857 +#define  UDESC_CS_INTERFACE    0x24
13858 +#define  UDESC_CS_ENDPOINT     0x25
13859 +#define  UDESC_HUB             0x29
13860 +#define UR_SET_DESCRIPTOR      0x07
13861 +#define UR_GET_CONFIG          0x08
13862 +#define UR_SET_CONFIG          0x09
13863 +#define UR_GET_INTERFACE       0x0a
13864 +#define UR_SET_INTERFACE       0x0b
13865 +#define UR_SYNCH_FRAME         0x0c
13866 +#define WUR_SET_ENCRYPTION      0x0d
13867 +#define WUR_GET_ENCRYPTION     0x0e
13868 +#define WUR_SET_HANDSHAKE      0x0f
13869 +#define WUR_GET_HANDSHAKE      0x10
13870 +#define WUR_SET_CONNECTION     0x11
13871 +#define WUR_SET_SECURITY_DATA  0x12
13872 +#define WUR_GET_SECURITY_DATA  0x13
13873 +#define WUR_SET_WUSB_DATA      0x14
13874 +#define  WUDATA_DRPIE_INFO     0x01
13875 +#define  WUDATA_TRANSMIT_DATA  0x02
13876 +#define  WUDATA_TRANSMIT_PARAMS        0x03
13877 +#define  WUDATA_RECEIVE_PARAMS 0x04
13878 +#define  WUDATA_TRANSMIT_POWER 0x05
13879 +#define WUR_LOOPBACK_DATA_WRITE        0x15
13880 +#define WUR_LOOPBACK_DATA_READ 0x16
13881 +#define WUR_SET_INTERFACE_DS   0x17
13882 +
13883 +/* Feature numbers */
13884 +#define UF_ENDPOINT_HALT       0
13885 +#define UF_DEVICE_REMOTE_WAKEUP        1
13886 +#define UF_TEST_MODE           2
13887 +#define UF_DEVICE_B_HNP_ENABLE 3
13888 +#define UF_DEVICE_A_HNP_SUPPORT        4
13889 +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
13890 +#define WUF_WUSB               3
13891 +#define  WUF_TX_DRPIE          0x0
13892 +#define  WUF_DEV_XMIT_PACKET   0x1
13893 +#define  WUF_COUNT_PACKETS     0x2
13894 +#define  WUF_CAPTURE_PACKETS   0x3
13895 +#define UF_FUNCTION_SUSPEND    0
13896 +#define UF_U1_ENABLE           48
13897 +#define UF_U2_ENABLE           49
13898 +#define UF_LTM_ENABLE          50
13899 +
13900 +/* Class requests from the USB 2.0 hub spec, table 11-15 */
13901 +#define UCR_CLEAR_HUB_FEATURE          (0x2000 | UR_CLEAR_FEATURE)
13902 +#define UCR_CLEAR_PORT_FEATURE         (0x2300 | UR_CLEAR_FEATURE)
13903 +#define UCR_GET_HUB_DESCRIPTOR         (0xa000 | UR_GET_DESCRIPTOR)
13904 +#define UCR_GET_HUB_STATUS             (0xa000 | UR_GET_STATUS)
13905 +#define UCR_GET_PORT_STATUS            (0xa300 | UR_GET_STATUS)
13906 +#define UCR_SET_HUB_FEATURE            (0x2000 | UR_SET_FEATURE)
13907 +#define UCR_SET_PORT_FEATURE           (0x2300 | UR_SET_FEATURE)
13908 +#define UCR_SET_AND_TEST_PORT_FEATURE  (0xa300 | UR_SET_AND_TEST_FEATURE)
13909 +
13910 +#ifdef _MSC_VER
13911 +#include <pshpack1.h>
13912 +#endif
13913 +
13914 +typedef struct {
13915 +       uByte           bLength;
13916 +       uByte           bDescriptorType;
13917 +       uByte           bDescriptorSubtype;
13918 +} UPACKED usb_descriptor_t;
13919 +
13920 +typedef struct {
13921 +       uByte           bLength;
13922 +       uByte           bDescriptorType;
13923 +} UPACKED usb_descriptor_header_t;
13924 +
13925 +typedef struct {
13926 +       uByte           bLength;
13927 +       uByte           bDescriptorType;
13928 +       uWord           bcdUSB;
13929 +#define UD_USB_2_0             0x0200
13930 +#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
13931 +       uByte           bDeviceClass;
13932 +       uByte           bDeviceSubClass;
13933 +       uByte           bDeviceProtocol;
13934 +       uByte           bMaxPacketSize;
13935 +       /* The fields below are not part of the initial descriptor. */
13936 +       uWord           idVendor;
13937 +       uWord           idProduct;
13938 +       uWord           bcdDevice;
13939 +       uByte           iManufacturer;
13940 +       uByte           iProduct;
13941 +       uByte           iSerialNumber;
13942 +       uByte           bNumConfigurations;
13943 +} UPACKED usb_device_descriptor_t;
13944 +#define USB_DEVICE_DESCRIPTOR_SIZE 18
13945 +
13946 +typedef struct {
13947 +       uByte           bLength;
13948 +       uByte           bDescriptorType;
13949 +       uWord           wTotalLength;
13950 +       uByte           bNumInterface;
13951 +       uByte           bConfigurationValue;
13952 +       uByte           iConfiguration;
13953 +#define UC_ATT_ONE             (1 << 7)        /* must be set */
13954 +#define UC_ATT_SELFPOWER       (1 << 6)        /* self powered */
13955 +#define UC_ATT_WAKEUP          (1 << 5)        /* can wakeup */
13956 +#define UC_ATT_BATTERY         (1 << 4)        /* battery powered */
13957 +       uByte           bmAttributes;
13958 +#define UC_BUS_POWERED         0x80
13959 +#define UC_SELF_POWERED                0x40
13960 +#define UC_REMOTE_WAKEUP       0x20
13961 +       uByte           bMaxPower; /* max current in 2 mA units */
13962 +#define UC_POWER_FACTOR 2
13963 +} UPACKED usb_config_descriptor_t;
13964 +#define USB_CONFIG_DESCRIPTOR_SIZE 9
13965 +
13966 +typedef struct {
13967 +       uByte           bLength;
13968 +       uByte           bDescriptorType;
13969 +       uByte           bInterfaceNumber;
13970 +       uByte           bAlternateSetting;
13971 +       uByte           bNumEndpoints;
13972 +       uByte           bInterfaceClass;
13973 +       uByte           bInterfaceSubClass;
13974 +       uByte           bInterfaceProtocol;
13975 +       uByte           iInterface;
13976 +} UPACKED usb_interface_descriptor_t;
13977 +#define USB_INTERFACE_DESCRIPTOR_SIZE 9
13978 +
13979 +typedef struct {
13980 +       uByte           bLength;
13981 +       uByte           bDescriptorType;
13982 +       uByte           bEndpointAddress;
13983 +#define UE_GET_DIR(a)  ((a) & 0x80)
13984 +#define UE_SET_DIR(a,d)        ((a) | (((d)&1) << 7))
13985 +#define UE_DIR_IN      0x80
13986 +#define UE_DIR_OUT     0x00
13987 +#define UE_ADDR                0x0f
13988 +#define UE_GET_ADDR(a) ((a) & UE_ADDR)
13989 +       uByte           bmAttributes;
13990 +#define UE_XFERTYPE    0x03
13991 +#define  UE_CONTROL    0x00
13992 +#define  UE_ISOCHRONOUS        0x01
13993 +#define  UE_BULK       0x02
13994 +#define  UE_INTERRUPT  0x03
13995 +#define UE_GET_XFERTYPE(a)     ((a) & UE_XFERTYPE)
13996 +#define UE_ISO_TYPE    0x0c
13997 +#define  UE_ISO_ASYNC  0x04
13998 +#define  UE_ISO_ADAPT  0x08
13999 +#define  UE_ISO_SYNC   0x0c
14000 +#define UE_GET_ISO_TYPE(a)     ((a) & UE_ISO_TYPE)
14001 +       uWord           wMaxPacketSize;
14002 +       uByte           bInterval;
14003 +} UPACKED usb_endpoint_descriptor_t;
14004 +#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
14005 +
14006 +typedef struct ss_endpoint_companion_descriptor {
14007 +       uByte bLength;
14008 +       uByte bDescriptorType;
14009 +       uByte bMaxBurst;
14010 +#define USSE_GET_MAX_STREAMS(a)                ((a) & 0x1f)
14011 +#define USSE_SET_MAX_STREAMS(a, b)     ((a) | ((b) & 0x1f))
14012 +#define USSE_GET_MAX_PACKET_NUM(a)     ((a) & 0x03)
14013 +#define USSE_SET_MAX_PACKET_NUM(a, b)  ((a) | ((b) & 0x03))
14014 +       uByte bmAttributes;
14015 +       uWord wBytesPerInterval;
14016 +} UPACKED ss_endpoint_companion_descriptor_t;
14017 +#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6
14018 +
14019 +typedef struct {
14020 +       uByte           bLength;
14021 +       uByte           bDescriptorType;
14022 +       uWord           bString[127];
14023 +} UPACKED usb_string_descriptor_t;
14024 +#define USB_MAX_STRING_LEN 128
14025 +#define USB_LANGUAGE_TABLE 0   /* # of the string language id table */
14026 +
14027 +/* Hub specific request */
14028 +#define UR_GET_BUS_STATE       0x02
14029 +#define UR_CLEAR_TT_BUFFER     0x08
14030 +#define UR_RESET_TT            0x09
14031 +#define UR_GET_TT_STATE                0x0a
14032 +#define UR_STOP_TT             0x0b
14033 +
14034 +/* Hub features */
14035 +#define UHF_C_HUB_LOCAL_POWER  0
14036 +#define UHF_C_HUB_OVER_CURRENT 1
14037 +#define UHF_PORT_CONNECTION    0
14038 +#define UHF_PORT_ENABLE                1
14039 +#define UHF_PORT_SUSPEND       2
14040 +#define UHF_PORT_OVER_CURRENT  3
14041 +#define UHF_PORT_RESET         4
14042 +#define UHF_PORT_L1            5
14043 +#define UHF_PORT_POWER         8
14044 +#define UHF_PORT_LOW_SPEED     9
14045 +#define UHF_PORT_HIGH_SPEED    10
14046 +#define UHF_C_PORT_CONNECTION  16
14047 +#define UHF_C_PORT_ENABLE      17
14048 +#define UHF_C_PORT_SUSPEND     18
14049 +#define UHF_C_PORT_OVER_CURRENT        19
14050 +#define UHF_C_PORT_RESET       20
14051 +#define UHF_C_PORT_L1          23
14052 +#define UHF_PORT_TEST          21
14053 +#define UHF_PORT_INDICATOR     22
14054 +
14055 +typedef struct {
14056 +       uByte           bDescLength;
14057 +       uByte           bDescriptorType;
14058 +       uByte           bNbrPorts;
14059 +       uWord           wHubCharacteristics;
14060 +#define UHD_PWR                        0x0003
14061 +#define  UHD_PWR_GANGED                0x0000
14062 +#define  UHD_PWR_INDIVIDUAL    0x0001
14063 +#define  UHD_PWR_NO_SWITCH     0x0002
14064 +#define UHD_COMPOUND           0x0004
14065 +#define UHD_OC                 0x0018
14066 +#define  UHD_OC_GLOBAL         0x0000
14067 +#define  UHD_OC_INDIVIDUAL     0x0008
14068 +#define  UHD_OC_NONE           0x0010
14069 +#define UHD_TT_THINK           0x0060
14070 +#define  UHD_TT_THINK_8                0x0000
14071 +#define  UHD_TT_THINK_16       0x0020
14072 +#define  UHD_TT_THINK_24       0x0040
14073 +#define  UHD_TT_THINK_32       0x0060
14074 +#define UHD_PORT_IND           0x0080
14075 +       uByte           bPwrOn2PwrGood; /* delay in 2 ms units */
14076 +#define UHD_PWRON_FACTOR 2
14077 +       uByte           bHubContrCurrent;
14078 +       uByte           DeviceRemovable[32]; /* max 255 ports */
14079 +#define UHD_NOT_REMOV(desc, i) \
14080 +    (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
14081 +       /* deprecated */ uByte          PortPowerCtrlMask[1];
14082 +} UPACKED usb_hub_descriptor_t;
14083 +#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
14084 +
14085 +typedef struct {
14086 +       uByte           bLength;
14087 +       uByte           bDescriptorType;
14088 +       uWord           bcdUSB;
14089 +       uByte           bDeviceClass;
14090 +       uByte           bDeviceSubClass;
14091 +       uByte           bDeviceProtocol;
14092 +       uByte           bMaxPacketSize0;
14093 +       uByte           bNumConfigurations;
14094 +       uByte           bReserved;
14095 +} UPACKED usb_device_qualifier_t;
14096 +#define USB_DEVICE_QUALIFIER_SIZE 10
14097 +
14098 +typedef struct {
14099 +       uByte           bLength;
14100 +       uByte           bDescriptorType;
14101 +       uByte           bmAttributes;
14102 +#define UOTG_SRP       0x01
14103 +#define UOTG_HNP       0x02
14104 +} UPACKED usb_otg_descriptor_t;
14105 +
14106 +/* OTG feature selectors */
14107 +#define UOTG_B_HNP_ENABLE      3
14108 +#define UOTG_A_HNP_SUPPORT     4
14109 +#define UOTG_A_ALT_HNP_SUPPORT 5
14110 +
14111 +typedef struct {
14112 +       uWord           wStatus;
14113 +/* Device status flags */
14114 +#define UDS_SELF_POWERED               0x0001
14115 +#define UDS_REMOTE_WAKEUP              0x0002
14116 +/* Endpoint status flags */
14117 +#define UES_HALT                       0x0001
14118 +} UPACKED usb_status_t;
14119 +
14120 +typedef struct {
14121 +       uWord           wHubStatus;
14122 +#define UHS_LOCAL_POWER                        0x0001
14123 +#define UHS_OVER_CURRENT               0x0002
14124 +       uWord           wHubChange;
14125 +} UPACKED usb_hub_status_t;
14126 +
14127 +typedef struct {
14128 +       uWord           wPortStatus;
14129 +#define UPS_CURRENT_CONNECT_STATUS     0x0001
14130 +#define UPS_PORT_ENABLED               0x0002
14131 +#define UPS_SUSPEND                    0x0004
14132 +#define UPS_OVERCURRENT_INDICATOR      0x0008
14133 +#define UPS_RESET                      0x0010
14134 +#define UPS_PORT_POWER                 0x0100
14135 +#define UPS_LOW_SPEED                  0x0200
14136 +#define UPS_HIGH_SPEED                 0x0400
14137 +#define UPS_PORT_TEST                  0x0800
14138 +#define UPS_PORT_INDICATOR             0x1000
14139 +       uWord           wPortChange;
14140 +#define UPS_C_CONNECT_STATUS           0x0001
14141 +#define UPS_C_PORT_ENABLED             0x0002
14142 +#define UPS_C_SUSPEND                  0x0004
14143 +#define UPS_C_OVERCURRENT_INDICATOR    0x0008
14144 +#define UPS_C_PORT_RESET               0x0010
14145 +} UPACKED usb_port_status_t;
14146 +
14147 +#ifdef _MSC_VER
14148 +#include <poppack.h>
14149 +#endif
14150 +
14151 +/* Device class codes */
14152 +#define UDCLASS_IN_INTERFACE   0x00
14153 +#define UDCLASS_COMM           0x02
14154 +#define UDCLASS_HUB            0x09
14155 +#define  UDSUBCLASS_HUB                0x00
14156 +#define  UDPROTO_FSHUB         0x00
14157 +#define  UDPROTO_HSHUBSTT      0x01
14158 +#define  UDPROTO_HSHUBMTT      0x02
14159 +#define UDCLASS_DIAGNOSTIC     0xdc
14160 +#define UDCLASS_WIRELESS       0xe0
14161 +#define  UDSUBCLASS_RF         0x01
14162 +#define   UDPROTO_BLUETOOTH    0x01
14163 +#define UDCLASS_VENDOR         0xff
14164 +
14165 +/* Interface class codes */
14166 +#define UICLASS_UNSPEC         0x00
14167 +
14168 +#define UICLASS_AUDIO          0x01
14169 +#define  UISUBCLASS_AUDIOCONTROL       1
14170 +#define  UISUBCLASS_AUDIOSTREAM                2
14171 +#define  UISUBCLASS_MIDISTREAM         3
14172 +
14173 +#define UICLASS_CDC            0x02 /* communication */
14174 +#define  UISUBCLASS_DIRECT_LINE_CONTROL_MODEL  1
14175 +#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL     2
14176 +#define  UISUBCLASS_TELEPHONE_CONTROL_MODEL    3
14177 +#define  UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4
14178 +#define  UISUBCLASS_CAPI_CONTROLMODEL          5
14179 +#define  UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
14180 +#define  UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
14181 +#define   UIPROTO_CDC_AT                       1
14182 +
14183 +#define UICLASS_HID            0x03
14184 +#define  UISUBCLASS_BOOT       1
14185 +#define  UIPROTO_BOOT_KEYBOARD 1
14186 +
14187 +#define UICLASS_PHYSICAL       0x05
14188 +
14189 +#define UICLASS_IMAGE          0x06
14190 +
14191 +#define UICLASS_PRINTER                0x07
14192 +#define  UISUBCLASS_PRINTER    1
14193 +#define  UIPROTO_PRINTER_UNI   1
14194 +#define  UIPROTO_PRINTER_BI    2
14195 +#define  UIPROTO_PRINTER_1284  3
14196 +
14197 +#define UICLASS_MASS           0x08
14198 +#define  UISUBCLASS_RBC                1
14199 +#define  UISUBCLASS_SFF8020I   2
14200 +#define  UISUBCLASS_QIC157     3
14201 +#define  UISUBCLASS_UFI                4
14202 +#define  UISUBCLASS_SFF8070I   5
14203 +#define  UISUBCLASS_SCSI       6
14204 +#define  UIPROTO_MASS_CBI_I    0
14205 +#define  UIPROTO_MASS_CBI      1
14206 +#define  UIPROTO_MASS_BBB_OLD  2       /* Not in the spec anymore */
14207 +#define  UIPROTO_MASS_BBB      80      /* 'P' for the Iomega Zip drive */
14208 +
14209 +#define UICLASS_HUB            0x09
14210 +#define  UISUBCLASS_HUB                0
14211 +#define  UIPROTO_FSHUB         0
14212 +#define  UIPROTO_HSHUBSTT      0 /* Yes, same as previous */
14213 +#define  UIPROTO_HSHUBMTT      1
14214 +
14215 +#define UICLASS_CDC_DATA       0x0a
14216 +#define  UISUBCLASS_DATA               0
14217 +#define   UIPROTO_DATA_ISDNBRI         0x30    /* Physical iface */
14218 +#define   UIPROTO_DATA_HDLC            0x31    /* HDLC */
14219 +#define   UIPROTO_DATA_TRANSPARENT     0x32    /* Transparent */
14220 +#define   UIPROTO_DATA_Q921M           0x50    /* Management for Q921 */
14221 +#define   UIPROTO_DATA_Q921            0x51    /* Data for Q921 */
14222 +#define   UIPROTO_DATA_Q921TM          0x52    /* TEI multiplexer for Q921 */
14223 +#define   UIPROTO_DATA_V42BIS          0x90    /* Data compression */
14224 +#define   UIPROTO_DATA_Q931            0x91    /* Euro-ISDN */
14225 +#define   UIPROTO_DATA_V120            0x92    /* V.24 rate adaption */
14226 +#define   UIPROTO_DATA_CAPI            0x93    /* CAPI 2.0 commands */
14227 +#define   UIPROTO_DATA_HOST_BASED      0xfd    /* Host based driver */
14228 +#define   UIPROTO_DATA_PUF             0xfe    /* see Prot. Unit Func. Desc.*/
14229 +#define   UIPROTO_DATA_VENDOR          0xff    /* Vendor specific */
14230 +
14231 +#define UICLASS_SMARTCARD      0x0b
14232 +
14233 +/*#define UICLASS_FIRM_UPD     0x0c*/
14234 +
14235 +#define UICLASS_SECURITY       0x0d
14236 +
14237 +#define UICLASS_DIAGNOSTIC     0xdc
14238 +
14239 +#define UICLASS_WIRELESS       0xe0
14240 +#define  UISUBCLASS_RF                 0x01
14241 +#define   UIPROTO_BLUETOOTH            0x01
14242 +
14243 +#define UICLASS_APPL_SPEC      0xfe
14244 +#define  UISUBCLASS_FIRMWARE_DOWNLOAD  1
14245 +#define  UISUBCLASS_IRDA               2
14246 +#define  UIPROTO_IRDA                  0
14247 +
14248 +#define UICLASS_VENDOR         0xff
14249 +
14250 +#define USB_HUB_MAX_DEPTH 5
14251 +
14252 +/*
14253 + * Minimum time a device needs to be powered down to go through
14254 + * a power cycle.  XXX Are these time in the spec?
14255 + */
14256 +#define USB_POWER_DOWN_TIME    200 /* ms */
14257 +#define USB_PORT_POWER_DOWN_TIME       100 /* ms */
14258 +
14259 +#if 0
14260 +/* These are the values from the spec. */
14261 +#define USB_PORT_RESET_DELAY   10  /* ms */
14262 +#define USB_PORT_ROOT_RESET_DELAY 50  /* ms */
14263 +#define USB_PORT_RESET_RECOVERY        10  /* ms */
14264 +#define USB_PORT_POWERUP_DELAY 100 /* ms */
14265 +#define USB_SET_ADDRESS_SETTLE 2   /* ms */
14266 +#define USB_RESUME_DELAY       (20*5)  /* ms */
14267 +#define USB_RESUME_WAIT                10  /* ms */
14268 +#define USB_RESUME_RECOVERY    10  /* ms */
14269 +#define USB_EXTRA_POWER_UP_TIME        0   /* ms */
14270 +#else
14271 +/* Allow for marginal (i.e. non-conforming) devices. */
14272 +#define USB_PORT_RESET_DELAY   50  /* ms */
14273 +#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */
14274 +#define USB_PORT_RESET_RECOVERY        250  /* ms */
14275 +#define USB_PORT_POWERUP_DELAY 300 /* ms */
14276 +#define USB_SET_ADDRESS_SETTLE 10  /* ms */
14277 +#define USB_RESUME_DELAY       (50*5)  /* ms */
14278 +#define USB_RESUME_WAIT                50  /* ms */
14279 +#define USB_RESUME_RECOVERY    50  /* ms */
14280 +#define USB_EXTRA_POWER_UP_TIME        20  /* ms */
14281 +#endif
14282 +
14283 +#define USB_MIN_POWER          100 /* mA */
14284 +#define USB_MAX_POWER          500 /* mA */
14285 +
14286 +#define USB_BUS_RESET_DELAY    100 /* ms XXX?*/
14287 +
14288 +#define USB_UNCONFIG_NO 0
14289 +#define USB_UNCONFIG_INDEX (-1)
14290 +
14291 +/*** ioctl() related stuff ***/
14292 +
14293 +struct usb_ctl_request {
14294 +       int     ucr_addr;
14295 +       usb_device_request_t ucr_request;
14296 +       void    *ucr_data;
14297 +       int     ucr_flags;
14298 +#define USBD_SHORT_XFER_OK     0x04    /* allow short reads */
14299 +       int     ucr_actlen;             /* actual length transferred */
14300 +};
14301 +
14302 +struct usb_alt_interface {
14303 +       int     uai_config_index;
14304 +       int     uai_interface_index;
14305 +       int     uai_alt_no;
14306 +};
14307 +
14308 +#define USB_CURRENT_CONFIG_INDEX (-1)
14309 +#define USB_CURRENT_ALT_INDEX (-1)
14310 +
14311 +struct usb_config_desc {
14312 +       int     ucd_config_index;
14313 +       usb_config_descriptor_t ucd_desc;
14314 +};
14315 +
14316 +struct usb_interface_desc {
14317 +       int     uid_config_index;
14318 +       int     uid_interface_index;
14319 +       int     uid_alt_index;
14320 +       usb_interface_descriptor_t uid_desc;
14321 +};
14322 +
14323 +struct usb_endpoint_desc {
14324 +       int     ued_config_index;
14325 +       int     ued_interface_index;
14326 +       int     ued_alt_index;
14327 +       int     ued_endpoint_index;
14328 +       usb_endpoint_descriptor_t ued_desc;
14329 +};
14330 +
14331 +struct usb_full_desc {
14332 +       int     ufd_config_index;
14333 +       u_int   ufd_size;
14334 +       u_char  *ufd_data;
14335 +};
14336 +
14337 +struct usb_string_desc {
14338 +       int     usd_string_index;
14339 +       int     usd_language_id;
14340 +       usb_string_descriptor_t usd_desc;
14341 +};
14342 +
14343 +struct usb_ctl_report_desc {
14344 +       int     ucrd_size;
14345 +       u_char  ucrd_data[1024];        /* filled data size will vary */
14346 +};
14347 +
14348 +typedef struct { u_int32_t cookie; } usb_event_cookie_t;
14349 +
14350 +#define USB_MAX_DEVNAMES 4
14351 +#define USB_MAX_DEVNAMELEN 16
14352 +struct usb_device_info {
14353 +       u_int8_t        udi_bus;
14354 +       u_int8_t        udi_addr;       /* device address */
14355 +       usb_event_cookie_t udi_cookie;
14356 +       char            udi_product[USB_MAX_STRING_LEN];
14357 +       char            udi_vendor[USB_MAX_STRING_LEN];
14358 +       char            udi_release[8];
14359 +       u_int16_t       udi_productNo;
14360 +       u_int16_t       udi_vendorNo;
14361 +       u_int16_t       udi_releaseNo;
14362 +       u_int8_t        udi_class;
14363 +       u_int8_t        udi_subclass;
14364 +       u_int8_t        udi_protocol;
14365 +       u_int8_t        udi_config;
14366 +       u_int8_t        udi_speed;
14367 +#define USB_SPEED_UNKNOWN      0
14368 +#define USB_SPEED_LOW          1
14369 +#define USB_SPEED_FULL         2
14370 +#define USB_SPEED_HIGH         3
14371 +#define USB_SPEED_VARIABLE     4
14372 +#define USB_SPEED_SUPER                5
14373 +       int             udi_power;      /* power consumption in mA, 0 if selfpowered */
14374 +       int             udi_nports;
14375 +       char            udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
14376 +       u_int8_t        udi_ports[16];/* hub only: addresses of devices on ports */
14377 +#define USB_PORT_ENABLED 0xff
14378 +#define USB_PORT_SUSPENDED 0xfe
14379 +#define USB_PORT_POWERED 0xfd
14380 +#define USB_PORT_DISABLED 0xfc
14381 +};
14382 +
14383 +struct usb_ctl_report {
14384 +       int     ucr_report;
14385 +       u_char  ucr_data[1024]; /* filled data size will vary */
14386 +};
14387 +
14388 +struct usb_device_stats {
14389 +       u_long  uds_requests[4];        /* indexed by transfer type UE_* */
14390 +};
14391 +
14392 +#define WUSB_MIN_IE                    0x80
14393 +#define WUSB_WCTA_IE                   0x80
14394 +#define WUSB_WCONNECTACK_IE            0x81
14395 +#define WUSB_WHOSTINFO_IE              0x82
14396 +#define  WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
14397 +#define   WUHI_CA_RECONN               0x00
14398 +#define   WUHI_CA_LIMITED              0x01
14399 +#define   WUHI_CA_ALL                  0x03
14400 +#define  WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
14401 +#define WUSB_WCHCHANGEANNOUNCE_IE      0x83
14402 +#define WUSB_WDEV_DISCONNECT_IE                0x84
14403 +#define WUSB_WHOST_DISCONNECT_IE       0x85
14404 +#define WUSB_WRELEASE_CHANNEL_IE       0x86
14405 +#define WUSB_WWORK_IE                  0x87
14406 +#define WUSB_WCHANNEL_STOP_IE          0x88
14407 +#define WUSB_WDEV_KEEPALIVE_IE         0x89
14408 +#define WUSB_WISOCH_DISCARD_IE         0x8A
14409 +#define WUSB_WRESETDEVICE_IE           0x8B
14410 +#define WUSB_WXMIT_PACKET_ADJUST_IE    0x8C
14411 +#define WUSB_MAX_IE                    0x8C
14412 +
14413 +/* Device Notification Types */
14414 +
14415 +#define WUSB_DN_MIN                    0x01
14416 +#define WUSB_DN_CONNECT                        0x01
14417 +# define WUSB_DA_OLDCONN       0x00
14418 +# define WUSB_DA_NEWCONN       0x01
14419 +# define WUSB_DA_SELF_BEACON   0x02
14420 +# define WUSB_DA_DIR_BEACON    0x04
14421 +# define WUSB_DA_NO_BEACON     0x06
14422 +#define WUSB_DN_DISCONNECT             0x02
14423 +#define WUSB_DN_EPRDY                  0x03
14424 +#define WUSB_DN_MASAVAILCHANGED                0x04
14425 +#define WUSB_DN_REMOTEWAKEUP           0x05
14426 +#define WUSB_DN_SLEEP                  0x06
14427 +#define WUSB_DN_ALIVE                  0x07
14428 +#define WUSB_DN_MAX                    0x07
14429 +
14430 +#ifdef _MSC_VER
14431 +#include <pshpack1.h>
14432 +#endif
14433 +
14434 +/* WUSB Handshake Data.  Used during the SET/GET HANDSHAKE requests */
14435 +typedef struct wusb_hndshk_data {
14436 +       uByte bMessageNumber;
14437 +       uByte bStatus;
14438 +       uByte tTKID[3];
14439 +       uByte bReserved;
14440 +       uByte CDID[16];
14441 +       uByte Nonce[16];
14442 +       uByte MIC[8];
14443 +} UPACKED wusb_hndshk_data_t;
14444 +#define WUSB_HANDSHAKE_LEN_FOR_MIC     38
14445 +
14446 +/* WUSB Connection Context */
14447 +typedef struct wusb_conn_context {
14448 +       uByte CHID [16];
14449 +       uByte CDID [16];
14450 +       uByte CK [16];
14451 +} UPACKED wusb_conn_context_t;
14452 +
14453 +/* WUSB Security Descriptor */
14454 +typedef struct wusb_security_desc {
14455 +       uByte bLength;
14456 +       uByte bDescriptorType;
14457 +       uWord wTotalLength;
14458 +       uByte bNumEncryptionTypes;
14459 +} UPACKED wusb_security_desc_t;
14460 +
14461 +/* WUSB Encryption Type Descriptor */
14462 +typedef struct wusb_encrypt_type_desc {
14463 +       uByte bLength;
14464 +       uByte bDescriptorType;
14465 +
14466 +       uByte bEncryptionType;
14467 +#define WUETD_UNSECURE         0
14468 +#define WUETD_WIRED            1
14469 +#define WUETD_CCM_1            2
14470 +#define WUETD_RSA_1            3
14471 +
14472 +       uByte bEncryptionValue;
14473 +       uByte bAuthKeyIndex;
14474 +} UPACKED wusb_encrypt_type_desc_t;
14475 +
14476 +/* WUSB Key Descriptor */
14477 +typedef struct wusb_key_desc {
14478 +       uByte bLength;
14479 +       uByte bDescriptorType;
14480 +       uByte tTKID[3];
14481 +       uByte bReserved;
14482 +       uByte KeyData[1];       /* variable length */
14483 +} UPACKED wusb_key_desc_t;
14484 +
14485 +/* WUSB BOS Descriptor (Binary device Object Store) */
14486 +typedef struct wusb_bos_desc {
14487 +       uByte bLength;
14488 +       uByte bDescriptorType;
14489 +       uWord wTotalLength;
14490 +       uByte bNumDeviceCaps;
14491 +} UPACKED wusb_bos_desc_t;
14492 +
14493 +#define USB_DEVICE_CAPABILITY_20_EXTENSION     0x02
14494 +typedef struct usb_dev_cap_20_ext_desc {
14495 +       uByte bLength;
14496 +       uByte bDescriptorType;
14497 +       uByte bDevCapabilityType;
14498 +#define USB_20_EXT_LPM                         0x02
14499 +       uDWord bmAttributes;
14500 +} UPACKED usb_dev_cap_20_ext_desc_t;
14501 +
14502 +#define USB_DEVICE_CAPABILITY_SS_USB           0x03
14503 +typedef struct usb_dev_cap_ss_usb {
14504 +       uByte bLength;
14505 +       uByte bDescriptorType;
14506 +       uByte bDevCapabilityType;
14507 +#define USB_DC_SS_USB_LTM_CAPABLE              0x02
14508 +       uByte bmAttributes;
14509 +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW                0x01
14510 +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL       0x02
14511 +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH       0x04
14512 +#define USB_DC_SS_USB_SPEED_SUPPORT_SS         0x08
14513 +       uWord wSpeedsSupported;
14514 +       uByte bFunctionalitySupport;
14515 +       uByte bU1DevExitLat;
14516 +       uWord wU2DevExitLat;
14517 +} UPACKED usb_dev_cap_ss_usb_t;
14518 +
14519 +#define USB_DEVICE_CAPABILITY_CONTAINER_ID     0x04
14520 +typedef struct usb_dev_cap_container_id {
14521 +       uByte bLength;
14522 +       uByte bDescriptorType;
14523 +       uByte bDevCapabilityType;
14524 +       uByte bReserved;
14525 +       uByte containerID[16];
14526 +} UPACKED usb_dev_cap_container_id_t;
14527 +
14528 +/* Device Capability Type Codes */
14529 +#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
14530 +
14531 +/* Device Capability Descriptor */
14532 +typedef struct wusb_dev_cap_desc {
14533 +       uByte bLength;
14534 +       uByte bDescriptorType;
14535 +       uByte bDevCapabilityType;
14536 +       uByte caps[1];  /* Variable length */
14537 +} UPACKED wusb_dev_cap_desc_t;
14538 +
14539 +/* Device Capability Descriptor */
14540 +typedef struct wusb_dev_cap_uwb_desc {
14541 +       uByte bLength;
14542 +       uByte bDescriptorType;
14543 +       uByte bDevCapabilityType;
14544 +       uByte bmAttributes;
14545 +       uWord wPHYRates;        /* Bitmap */
14546 +       uByte bmTFITXPowerInfo;
14547 +       uByte bmFFITXPowerInfo;
14548 +       uWord bmBandGroup;
14549 +       uByte bReserved;
14550 +} UPACKED wusb_dev_cap_uwb_desc_t;
14551 +
14552 +/* Wireless USB Endpoint Companion Descriptor */
14553 +typedef struct wusb_endpoint_companion_desc {
14554 +       uByte bLength;
14555 +       uByte bDescriptorType;
14556 +       uByte bMaxBurst;
14557 +       uByte bMaxSequence;
14558 +       uWord wMaxStreamDelay;
14559 +       uWord wOverTheAirPacketSize;
14560 +       uByte bOverTheAirInterval;
14561 +       uByte bmCompAttributes;
14562 +} UPACKED wusb_endpoint_companion_desc_t;
14563 +
14564 +/* Wireless USB Numeric Association M1 Data Structure */
14565 +typedef struct wusb_m1_data {
14566 +       uByte version;
14567 +       uWord langId;
14568 +       uByte deviceFriendlyNameLength;
14569 +       uByte sha_256_m3[32];
14570 +       uByte deviceFriendlyName[256];
14571 +} UPACKED wusb_m1_data_t;
14572 +
14573 +typedef struct wusb_m2_data {
14574 +       uByte version;
14575 +       uWord langId;
14576 +       uByte hostFriendlyNameLength;
14577 +       uByte pkh[384];
14578 +       uByte hostFriendlyName[256];
14579 +} UPACKED wusb_m2_data_t;
14580 +
14581 +typedef struct wusb_m3_data {
14582 +       uByte pkd[384];
14583 +       uByte nd;
14584 +} UPACKED wusb_m3_data_t;
14585 +
14586 +typedef struct wusb_m4_data {
14587 +       uDWord _attributeTypeIdAndLength_1;
14588 +       uWord  associationTypeId;
14589 +
14590 +       uDWord _attributeTypeIdAndLength_2;
14591 +       uWord  associationSubTypeId;
14592 +
14593 +       uDWord _attributeTypeIdAndLength_3;
14594 +       uDWord length;
14595 +
14596 +       uDWord _attributeTypeIdAndLength_4;
14597 +       uDWord associationStatus;
14598 +
14599 +       uDWord _attributeTypeIdAndLength_5;
14600 +       uByte  chid[16];
14601 +
14602 +       uDWord _attributeTypeIdAndLength_6;
14603 +       uByte  cdid[16];
14604 +
14605 +       uDWord _attributeTypeIdAndLength_7;
14606 +       uByte  bandGroups[2];
14607 +} UPACKED wusb_m4_data_t;
14608 +
14609 +#ifdef _MSC_VER
14610 +#include <poppack.h>
14611 +#endif
14612 +
14613 +#ifdef __cplusplus
14614 +}
14615 +#endif
14616 +
14617 +#endif /* _USB_H_ */
14618 diff --git a/drivers/usb/host/dwc_otg/Makefile b/drivers/usb/host/dwc_otg/Makefile
14619 new file mode 100644
14620 index 0000000..c4c6e4e
14621 --- /dev/null
14622 +++ b/drivers/usb/host/dwc_otg/Makefile
14623 @@ -0,0 +1,80 @@
14624 +#
14625 +# Makefile for DWC_otg Highspeed USB controller driver
14626 +#
14627 +
14628 +ifneq ($(KERNELRELEASE),)
14629 +
14630 +# Use the BUS_INTERFACE variable to compile the software for either 
14631 +# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus.
14632 +ifeq ($(BUS_INTERFACE),)
14633 +#      BUS_INTERFACE = -DPCI_INTERFACE
14634 +#      BUS_INTERFACE = -DLM_INTERFACE
14635 +        BUS_INTERFACE = -DPLATFORM_INTERFACE
14636 +endif
14637 +
14638 +#EXTRA_CFLAGS  += -DDEBUG
14639 +#EXTRA_CFLAGS  += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs
14640 +
14641 +# Use one of the following flags to compile the software in host-only or
14642 +# device-only mode.
14643 +#EXTRA_CFLAGS        += -DDWC_HOST_ONLY
14644 +#EXTRA_CFLAGS        += -DDWC_DEVICE_ONLY
14645 +
14646 +EXTRA_CFLAGS   += -Dlinux -DDWC_HS_ELECT_TST
14647 +#EXTRA_CFLAGS  += -DDWC_EN_ISOC
14648 +EXTRA_CFLAGS           += -I$(obj)/../dwc_common_port
14649 +#EXTRA_CFLAGS          += -I$(PORTLIB)
14650 +EXTRA_CFLAGS           += -DDWC_LINUX
14651 +EXTRA_CFLAGS           += $(CFI)
14652 +EXTRA_CFLAGS   += $(BUS_INTERFACE)
14653 +#EXTRA_CFLAGS  += -DDWC_DEV_SRPCAP
14654 +
14655 +obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
14656 +
14657 +dwc_otg-objs   := dwc_otg_driver.o dwc_otg_attr.o 
14658 +dwc_otg-objs   += dwc_otg_cil.o dwc_otg_cil_intr.o 
14659 +dwc_otg-objs   += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o 
14660 +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
14661 +dwc_otg-objs   += dwc_otg_adp.o
14662 +ifneq ($(CFI),)
14663 +dwc_otg-objs   += dwc_otg_cfi.o
14664 +endif
14665 +
14666 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
14667 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
14668 +
14669 +ifneq ($(kernrel3),2.6.20)
14670 +EXTRA_CFLAGS += $(CPPFLAGS)
14671 +endif
14672 +
14673 +else
14674 +
14675 +PWD            := $(shell pwd)
14676 +PORTLIB                := $(PWD)/../dwc_common_port
14677 +
14678 +# Command paths
14679 +CTAGS          := $(CTAGS)
14680 +DOXYGEN                := $(DOXYGEN)
14681 +
14682 +default: portlib
14683 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
14684 +
14685 +install: default
14686 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install
14687 +       $(MAKE) -C$(KDIR) M=$(PWD) modules_install      
14688 +
14689 +portlib:
14690 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
14691 +       cp $(PORTLIB)/Module.symvers $(PWD)/
14692 +
14693 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
14694 +       $(DOXYGEN) doc/doxygen.cfg
14695 +
14696 +tags:  $(wildcard *.[hc])
14697 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
14698 +
14699 +
14700 +clean:
14701 +       rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
14702 +
14703 +endif
14704 diff --git a/drivers/usb/host/dwc_otg/doc/doxygen.cfg b/drivers/usb/host/dwc_otg/doc/doxygen.cfg
14705 new file mode 100644
14706 index 0000000..537c676
14707 --- /dev/null
14708 +++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg
14709 @@ -0,0 +1,224 @@
14710 +# Doxyfile 1.3.9.1
14711 +
14712 +#---------------------------------------------------------------------------
14713 +# Project related configuration options
14714 +#---------------------------------------------------------------------------
14715 +PROJECT_NAME           = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver"
14716 +PROJECT_NUMBER         = v3.00a
14717 +OUTPUT_DIRECTORY       = ./doc/
14718 +CREATE_SUBDIRS         = NO
14719 +OUTPUT_LANGUAGE        = English
14720 +BRIEF_MEMBER_DESC      = YES
14721 +REPEAT_BRIEF           = YES
14722 +ABBREVIATE_BRIEF       = "The $name class" \
14723 +                         "The $name widget" \
14724 +                         "The $name file" \
14725 +                         is \
14726 +                         provides \
14727 +                         specifies \
14728 +                         contains \
14729 +                         represents \
14730 +                         a \
14731 +                         an \
14732 +                         the
14733 +ALWAYS_DETAILED_SEC    = NO
14734 +INLINE_INHERITED_MEMB  = NO
14735 +FULL_PATH_NAMES        = NO
14736 +STRIP_FROM_PATH        = 
14737 +STRIP_FROM_INC_PATH    = 
14738 +SHORT_NAMES            = NO
14739 +JAVADOC_AUTOBRIEF      = YES
14740 +MULTILINE_CPP_IS_BRIEF = NO
14741 +INHERIT_DOCS           = YES
14742 +DISTRIBUTE_GROUP_DOC   = NO
14743 +TAB_SIZE               = 8
14744 +ALIASES                = 
14745 +OPTIMIZE_OUTPUT_FOR_C  = YES
14746 +OPTIMIZE_OUTPUT_JAVA   = NO
14747 +SUBGROUPING            = YES
14748 +#---------------------------------------------------------------------------
14749 +# Build related configuration options
14750 +#---------------------------------------------------------------------------
14751 +EXTRACT_ALL            = NO
14752 +EXTRACT_PRIVATE        = YES
14753 +EXTRACT_STATIC         = YES
14754 +EXTRACT_LOCAL_CLASSES  = YES
14755 +EXTRACT_LOCAL_METHODS  = NO
14756 +HIDE_UNDOC_MEMBERS     = NO
14757 +HIDE_UNDOC_CLASSES     = NO
14758 +HIDE_FRIEND_COMPOUNDS  = NO
14759 +HIDE_IN_BODY_DOCS      = NO
14760 +INTERNAL_DOCS          = NO
14761 +CASE_SENSE_NAMES       = NO
14762 +HIDE_SCOPE_NAMES       = NO
14763 +SHOW_INCLUDE_FILES     = YES
14764 +INLINE_INFO            = YES
14765 +SORT_MEMBER_DOCS       = NO
14766 +SORT_BRIEF_DOCS        = NO
14767 +SORT_BY_SCOPE_NAME     = NO
14768 +GENERATE_TODOLIST      = YES
14769 +GENERATE_TESTLIST      = YES
14770 +GENERATE_BUGLIST       = YES
14771 +GENERATE_DEPRECATEDLIST= YES
14772 +ENABLED_SECTIONS       = 
14773 +MAX_INITIALIZER_LINES  = 30
14774 +SHOW_USED_FILES        = YES
14775 +SHOW_DIRECTORIES       = YES
14776 +#---------------------------------------------------------------------------
14777 +# configuration options related to warning and progress messages
14778 +#---------------------------------------------------------------------------
14779 +QUIET                  = YES
14780 +WARNINGS               = YES
14781 +WARN_IF_UNDOCUMENTED   = NO
14782 +WARN_IF_DOC_ERROR      = YES
14783 +WARN_FORMAT            = "$file:$line: $text"
14784 +WARN_LOGFILE           = 
14785 +#---------------------------------------------------------------------------
14786 +# configuration options related to the input files
14787 +#---------------------------------------------------------------------------
14788 +INPUT                  = .
14789 +FILE_PATTERNS          = *.c \
14790 +                         *.h \
14791 +                         ./linux/*.c \
14792 +                         ./linux/*.h
14793 +RECURSIVE              = NO
14794 +EXCLUDE                = ./test/ \
14795 +                         ./dwc_otg/.AppleDouble/
14796 +EXCLUDE_SYMLINKS       = YES
14797 +EXCLUDE_PATTERNS       = *.mod.*
14798 +EXAMPLE_PATH           = 
14799 +EXAMPLE_PATTERNS       = *
14800 +EXAMPLE_RECURSIVE      = NO
14801 +IMAGE_PATH             = 
14802 +INPUT_FILTER           = 
14803 +FILTER_PATTERNS        = 
14804 +FILTER_SOURCE_FILES    = NO
14805 +#---------------------------------------------------------------------------
14806 +# configuration options related to source browsing
14807 +#---------------------------------------------------------------------------
14808 +SOURCE_BROWSER         = YES
14809 +INLINE_SOURCES         = NO
14810 +STRIP_CODE_COMMENTS    = YES
14811 +REFERENCED_BY_RELATION = NO
14812 +REFERENCES_RELATION    = NO
14813 +VERBATIM_HEADERS       = NO
14814 +#---------------------------------------------------------------------------
14815 +# configuration options related to the alphabetical class index
14816 +#---------------------------------------------------------------------------
14817 +ALPHABETICAL_INDEX     = NO
14818 +COLS_IN_ALPHA_INDEX    = 5
14819 +IGNORE_PREFIX          = 
14820 +#---------------------------------------------------------------------------
14821 +# configuration options related to the HTML output
14822 +#---------------------------------------------------------------------------
14823 +GENERATE_HTML          = YES
14824 +HTML_OUTPUT            = html
14825 +HTML_FILE_EXTENSION    = .html
14826 +HTML_HEADER            = 
14827 +HTML_FOOTER            = 
14828 +HTML_STYLESHEET        = 
14829 +HTML_ALIGN_MEMBERS     = YES
14830 +GENERATE_HTMLHELP      = NO
14831 +CHM_FILE               = 
14832 +HHC_LOCATION           = 
14833 +GENERATE_CHI           = NO
14834 +BINARY_TOC             = NO
14835 +TOC_EXPAND             = NO
14836 +DISABLE_INDEX          = NO
14837 +ENUM_VALUES_PER_LINE   = 4
14838 +GENERATE_TREEVIEW      = YES
14839 +TREEVIEW_WIDTH         = 250
14840 +#---------------------------------------------------------------------------
14841 +# configuration options related to the LaTeX output
14842 +#---------------------------------------------------------------------------
14843 +GENERATE_LATEX         = NO
14844 +LATEX_OUTPUT           = latex
14845 +LATEX_CMD_NAME         = latex
14846 +MAKEINDEX_CMD_NAME     = makeindex
14847 +COMPACT_LATEX          = NO
14848 +PAPER_TYPE             = a4wide
14849 +EXTRA_PACKAGES         = 
14850 +LATEX_HEADER           = 
14851 +PDF_HYPERLINKS         = NO
14852 +USE_PDFLATEX           = NO
14853 +LATEX_BATCHMODE        = NO
14854 +LATEX_HIDE_INDICES     = NO
14855 +#---------------------------------------------------------------------------
14856 +# configuration options related to the RTF output
14857 +#---------------------------------------------------------------------------
14858 +GENERATE_RTF           = NO
14859 +RTF_OUTPUT             = rtf
14860 +COMPACT_RTF            = NO
14861 +RTF_HYPERLINKS         = NO
14862 +RTF_STYLESHEET_FILE    = 
14863 +RTF_EXTENSIONS_FILE    = 
14864 +#---------------------------------------------------------------------------
14865 +# configuration options related to the man page output
14866 +#---------------------------------------------------------------------------
14867 +GENERATE_MAN           = NO
14868 +MAN_OUTPUT             = man
14869 +MAN_EXTENSION          = .3
14870 +MAN_LINKS              = NO
14871 +#---------------------------------------------------------------------------
14872 +# configuration options related to the XML output
14873 +#---------------------------------------------------------------------------
14874 +GENERATE_XML           = NO
14875 +XML_OUTPUT             = xml
14876 +XML_SCHEMA             = 
14877 +XML_DTD                = 
14878 +XML_PROGRAMLISTING     = YES
14879 +#---------------------------------------------------------------------------
14880 +# configuration options for the AutoGen Definitions output
14881 +#---------------------------------------------------------------------------
14882 +GENERATE_AUTOGEN_DEF   = NO
14883 +#---------------------------------------------------------------------------
14884 +# configuration options related to the Perl module output
14885 +#---------------------------------------------------------------------------
14886 +GENERATE_PERLMOD       = NO
14887 +PERLMOD_LATEX          = NO
14888 +PERLMOD_PRETTY         = YES
14889 +PERLMOD_MAKEVAR_PREFIX = 
14890 +#---------------------------------------------------------------------------
14891 +# Configuration options related to the preprocessor   
14892 +#---------------------------------------------------------------------------
14893 +ENABLE_PREPROCESSING   = YES
14894 +MACRO_EXPANSION        = YES
14895 +EXPAND_ONLY_PREDEF     = YES
14896 +SEARCH_INCLUDES        = YES
14897 +INCLUDE_PATH           = 
14898 +INCLUDE_FILE_PATTERNS  = 
14899 +PREDEFINED             = DEVICE_ATTR DWC_EN_ISOC
14900 +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
14901 +SKIP_FUNCTION_MACROS   = NO
14902 +#---------------------------------------------------------------------------
14903 +# Configuration::additions related to external references   
14904 +#---------------------------------------------------------------------------
14905 +TAGFILES               = 
14906 +GENERATE_TAGFILE       = 
14907 +ALLEXTERNALS           = NO
14908 +EXTERNAL_GROUPS        = YES
14909 +PERL_PATH              = /usr/bin/perl
14910 +#---------------------------------------------------------------------------
14911 +# Configuration options related to the dot tool   
14912 +#---------------------------------------------------------------------------
14913 +CLASS_DIAGRAMS         = YES
14914 +HIDE_UNDOC_RELATIONS   = YES
14915 +HAVE_DOT               = NO
14916 +CLASS_GRAPH            = YES
14917 +COLLABORATION_GRAPH    = YES
14918 +UML_LOOK               = NO
14919 +TEMPLATE_RELATIONS     = NO
14920 +INCLUDE_GRAPH          = YES
14921 +INCLUDED_BY_GRAPH      = YES
14922 +CALL_GRAPH             = NO
14923 +GRAPHICAL_HIERARCHY    = YES
14924 +DOT_IMAGE_FORMAT       = png
14925 +DOT_PATH               = 
14926 +DOTFILE_DIRS           = 
14927 +MAX_DOT_GRAPH_DEPTH    = 1000
14928 +GENERATE_LEGEND        = YES
14929 +DOT_CLEANUP            = YES
14930 +#---------------------------------------------------------------------------
14931 +# Configuration::additions related to the search engine   
14932 +#---------------------------------------------------------------------------
14933 +SEARCHENGINE           = NO
14934 diff --git a/drivers/usb/host/dwc_otg/dummy_audio.c b/drivers/usb/host/dwc_otg/dummy_audio.c
14935 new file mode 100644
14936 index 0000000..530ac8b
14937 --- /dev/null
14938 +++ b/drivers/usb/host/dwc_otg/dummy_audio.c
14939 @@ -0,0 +1,1575 @@
14940 +/*
14941 + * zero.c -- Gadget Zero, for USB development
14942 + *
14943 + * Copyright (C) 2003-2004 David Brownell
14944 + * All rights reserved.
14945 + *
14946 + * Redistribution and use in source and binary forms, with or without
14947 + * modification, are permitted provided that the following conditions
14948 + * are met:
14949 + * 1. Redistributions of source code must retain the above copyright
14950 + *    notice, this list of conditions, and the following disclaimer,
14951 + *    without modification.
14952 + * 2. Redistributions in binary form must reproduce the above copyright
14953 + *    notice, this list of conditions and the following disclaimer in the
14954 + *    documentation and/or other materials provided with the distribution.
14955 + * 3. The names of the above-listed copyright holders may not be used
14956 + *    to endorse or promote products derived from this software without
14957 + *    specific prior written permission.
14958 + *
14959 + * ALTERNATIVELY, this software may be distributed under the terms of the
14960 + * GNU General Public License ("GPL") as published by the Free Software
14961 + * Foundation, either version 2 of that License or (at your option) any
14962 + * later version.
14963 + *
14964 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
14965 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14966 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
14967 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14968 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14969 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14970 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14971 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14972 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14973 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14974 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14975 + */
14976 +
14977 +
14978 +/*
14979 + * Gadget Zero only needs two bulk endpoints, and is an example of how you
14980 + * can write a hardware-agnostic gadget driver running inside a USB device.
14981 + *
14982 + * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
14983 + * affect most of the driver.
14984 + *
14985 + * Use it with the Linux host/master side "usbtest" driver to get a basic
14986 + * functional test of your device-side usb stack, or with "usb-skeleton".
14987 + *
14988 + * It supports two similar configurations.  One sinks whatever the usb host
14989 + * writes, and in return sources zeroes.  The other loops whatever the host
14990 + * writes back, so the host can read it.  Module options include:
14991 + *
14992 + *   buflen=N          default N=4096, buffer size used
14993 + *   qlen=N            default N=32, how many buffers in the loopback queue
14994 + *   loopdefault       default false, list loopback config first
14995 + *
14996 + * Many drivers will only have one configuration, letting them be much
14997 + * simpler if they also don't support high speed operation (like this
14998 + * driver does).
14999 + */
15000 +
15001 +#include <linux/config.h>
15002 +#include <linux/module.h>
15003 +#include <linux/kernel.h>
15004 +#include <linux/delay.h>
15005 +#include <linux/ioport.h>
15006 +#include <linux/sched.h>
15007 +#include <linux/slab.h>
15008 +#include <linux/smp_lock.h>
15009 +#include <linux/errno.h>
15010 +#include <linux/init.h>
15011 +#include <linux/timer.h>
15012 +#include <linux/list.h>
15013 +#include <linux/interrupt.h>
15014 +#include <linux/uts.h>
15015 +#include <linux/version.h>
15016 +#include <linux/device.h>
15017 +#include <linux/moduleparam.h>
15018 +#include <linux/proc_fs.h>
15019 +
15020 +#include <asm/byteorder.h>
15021 +#include <asm/io.h>
15022 +#include <asm/irq.h>
15023 +#include <asm/system.h>
15024 +#include <asm/unaligned.h>
15025 +
15026 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
15027 +# include <linux/usb/ch9.h>
15028 +#else
15029 +# include <linux/usb_ch9.h>
15030 +#endif
15031 +
15032 +#include <linux/usb_gadget.h>
15033 +
15034 +
15035 +/*-------------------------------------------------------------------------*/
15036 +/*-------------------------------------------------------------------------*/
15037 +
15038 +
15039 +static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
15040 +{
15041 +       int     count = 0;
15042 +       u8      c;
15043 +       u16     uchar;
15044 +
15045 +       /* this insists on correct encodings, though not minimal ones.
15046 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
15047 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
15048 +        */
15049 +       while (len != 0 && (c = (u8) *s++) != 0) {
15050 +               if (unlikely(c & 0x80)) {
15051 +                       // 2-byte sequence:
15052 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
15053 +                       if ((c & 0xe0) == 0xc0) {
15054 +                               uchar = (c & 0x1f) << 6;
15055 +
15056 +                               c = (u8) *s++;
15057 +                               if ((c & 0xc0) != 0xc0)
15058 +                                       goto fail;
15059 +                               c &= 0x3f;
15060 +                               uchar |= c;
15061 +
15062 +                       // 3-byte sequence (most CJKV characters):
15063 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
15064 +                       } else if ((c & 0xf0) == 0xe0) {
15065 +                               uchar = (c & 0x0f) << 12;
15066 +
15067 +                               c = (u8) *s++;
15068 +                               if ((c & 0xc0) != 0xc0)
15069 +                                       goto fail;
15070 +                               c &= 0x3f;
15071 +                               uchar |= c << 6;
15072 +
15073 +                               c = (u8) *s++;
15074 +                               if ((c & 0xc0) != 0xc0)
15075 +                                       goto fail;
15076 +                               c &= 0x3f;
15077 +                               uchar |= c;
15078 +
15079 +                               /* no bogus surrogates */
15080 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
15081 +                                       goto fail;
15082 +
15083 +                       // 4-byte sequence (surrogate pairs, currently rare):
15084 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
15085 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
15086 +                       // (uuuuu = wwww + 1)
15087 +                       // FIXME accept the surrogate code points (only)
15088 +
15089 +                       } else
15090 +                               goto fail;
15091 +               } else
15092 +                       uchar = c;
15093 +               put_unaligned (cpu_to_le16 (uchar), cp++);
15094 +               count++;
15095 +               len--;
15096 +       }
15097 +       return count;
15098 +fail:
15099 +       return -1;
15100 +}
15101 +
15102 +
15103 +/**
15104 + * usb_gadget_get_string - fill out a string descriptor 
15105 + * @table: of c strings encoded using UTF-8
15106 + * @id: string id, from low byte of wValue in get string descriptor
15107 + * @buf: at least 256 bytes
15108 + *
15109 + * Finds the UTF-8 string matching the ID, and converts it into a
15110 + * string descriptor in utf16-le.
15111 + * Returns length of descriptor (always even) or negative errno
15112 + *
15113 + * If your driver needs stings in multiple languages, you'll probably
15114 + * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
15115 + * using this routine after choosing which set of UTF-8 strings to use.
15116 + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
15117 + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
15118 + * characters (which are also widely used in C strings).
15119 + */
15120 +int
15121 +usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
15122 +{
15123 +       struct usb_string       *s;
15124 +       int                     len;
15125 +
15126 +       /* descriptor 0 has the language id */
15127 +       if (id == 0) {
15128 +               buf [0] = 4;
15129 +               buf [1] = USB_DT_STRING;
15130 +               buf [2] = (u8) table->language;
15131 +               buf [3] = (u8) (table->language >> 8);
15132 +               return 4;
15133 +       }
15134 +       for (s = table->strings; s && s->s; s++)
15135 +               if (s->id == id)
15136 +                       break;
15137 +
15138 +       /* unrecognized: stall. */
15139 +       if (!s || !s->s)
15140 +               return -EINVAL;
15141 +
15142 +       /* string descriptors have length, tag, then UTF16-LE text */
15143 +       len = min ((size_t) 126, strlen (s->s));
15144 +       memset (buf + 2, 0, 2 * len);   /* zero all the bytes */
15145 +       len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
15146 +       if (len < 0)
15147 +               return -EINVAL;
15148 +       buf [0] = (len + 1) * 2;
15149 +       buf [1] = USB_DT_STRING;
15150 +       return buf [0];
15151 +}
15152 +
15153 +
15154 +/*-------------------------------------------------------------------------*/
15155 +/*-------------------------------------------------------------------------*/
15156 +
15157 +
15158 +/**
15159 + * usb_descriptor_fillbuf - fill buffer with descriptors
15160 + * @buf: Buffer to be filled
15161 + * @buflen: Size of buf
15162 + * @src: Array of descriptor pointers, terminated by null pointer.
15163 + *
15164 + * Copies descriptors into the buffer, returning the length or a
15165 + * negative error code if they can't all be copied.  Useful when
15166 + * assembling descriptors for an associated set of interfaces used
15167 + * as part of configuring a composite device; or in other cases where
15168 + * sets of descriptors need to be marshaled.
15169 + */
15170 +int
15171 +usb_descriptor_fillbuf(void *buf, unsigned buflen,
15172 +               const struct usb_descriptor_header **src)
15173 +{
15174 +       u8      *dest = buf;
15175 +
15176 +       if (!src)
15177 +               return -EINVAL;
15178 +
15179 +       /* fill buffer from src[] until null descriptor ptr */
15180 +       for (; 0 != *src; src++) {
15181 +               unsigned                len = (*src)->bLength;
15182 +
15183 +               if (len > buflen)
15184 +                       return -EINVAL;
15185 +               memcpy(dest, *src, len);
15186 +               buflen -= len;
15187 +               dest += len;
15188 +       }
15189 +       return dest - (u8 *)buf;
15190 +}
15191 +
15192 +
15193 +/**
15194 + * usb_gadget_config_buf - builts a complete configuration descriptor
15195 + * @config: Header for the descriptor, including characteristics such
15196 + *     as power requirements and number of interfaces.
15197 + * @desc: Null-terminated vector of pointers to the descriptors (interface,
15198 + *     endpoint, etc) defining all functions in this device configuration.
15199 + * @buf: Buffer for the resulting configuration descriptor.
15200 + * @length: Length of buffer.  If this is not big enough to hold the
15201 + *     entire configuration descriptor, an error code will be returned.
15202 + *
15203 + * This copies descriptors into the response buffer, building a descriptor
15204 + * for that configuration.  It returns the buffer length or a negative
15205 + * status code.  The config.wTotalLength field is set to match the length
15206 + * of the result, but other descriptor fields (including power usage and
15207 + * interface count) must be set by the caller.
15208 + *
15209 + * Gadget drivers could use this when constructing a config descriptor
15210 + * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
15211 + * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
15212 + */
15213 +int usb_gadget_config_buf(
15214 +       const struct usb_config_descriptor      *config,
15215 +       void                                    *buf,
15216 +       unsigned                                length,
15217 +       const struct usb_descriptor_header      **desc
15218 +)
15219 +{
15220 +       struct usb_config_descriptor            *cp = buf;
15221 +       int                                     len;
15222 +
15223 +       /* config descriptor first */
15224 +       if (length < USB_DT_CONFIG_SIZE || !desc)
15225 +               return -EINVAL;
15226 +       *cp = *config; 
15227 +
15228 +       /* then interface/endpoint/class/vendor/... */
15229 +       len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
15230 +                       length - USB_DT_CONFIG_SIZE, desc);
15231 +       if (len < 0)
15232 +               return len;
15233 +       len += USB_DT_CONFIG_SIZE;
15234 +       if (len > 0xffff)
15235 +               return -EINVAL;
15236 +
15237 +       /* patch up the config descriptor */
15238 +       cp->bLength = USB_DT_CONFIG_SIZE;
15239 +       cp->bDescriptorType = USB_DT_CONFIG;
15240 +       cp->wTotalLength = cpu_to_le16(len);
15241 +       cp->bmAttributes |= USB_CONFIG_ATT_ONE;
15242 +       return len;
15243 +}
15244 +
15245 +/*-------------------------------------------------------------------------*/
15246 +/*-------------------------------------------------------------------------*/
15247 +
15248 +
15249 +#define RBUF_LEN (1024*1024)
15250 +static int rbuf_start;
15251 +static int rbuf_len;
15252 +static __u8 rbuf[RBUF_LEN];
15253 +
15254 +/*-------------------------------------------------------------------------*/
15255 +
15256 +#define DRIVER_VERSION         "St Patrick's Day 2004"
15257 +
15258 +static const char shortname [] = "zero";
15259 +static const char longname [] = "YAMAHA YST-MS35D USB Speaker  ";
15260 +
15261 +static const char source_sink [] = "source and sink data";
15262 +static const char loopback [] = "loop input to output";
15263 +
15264 +/*-------------------------------------------------------------------------*/
15265 +
15266 +/*
15267 + * driver assumes self-powered hardware, and
15268 + * has no way for users to trigger remote wakeup.
15269 + *
15270 + * this version autoconfigures as much as possible,
15271 + * which is reasonable for most "bulk-only" drivers.
15272 + */
15273 +static const char *EP_IN_NAME;         /* source */
15274 +static const char *EP_OUT_NAME;                /* sink */
15275 +
15276 +/*-------------------------------------------------------------------------*/
15277 +
15278 +/* big enough to hold our biggest descriptor */
15279 +#define USB_BUFSIZ     512
15280 +
15281 +struct zero_dev {
15282 +       spinlock_t              lock;
15283 +       struct usb_gadget       *gadget;
15284 +       struct usb_request      *req;           /* for control responses */
15285 +
15286 +       /* when configured, we have one of two configs:
15287 +        * - source data (in to host) and sink it (out from host)
15288 +        * - or loop it back (out from host back in to host)
15289 +        */
15290 +       u8                      config;
15291 +       struct usb_ep           *in_ep, *out_ep;
15292 +
15293 +       /* autoresume timer */
15294 +       struct timer_list       resume;
15295 +};
15296 +
15297 +#define xprintk(d,level,fmt,args...) \
15298 +       dev_printk(level , &(d)->gadget->dev , fmt , ## args)
15299 +
15300 +#ifdef DEBUG
15301 +#define DBG(dev,fmt,args...) \
15302 +       xprintk(dev , KERN_DEBUG , fmt , ## args)
15303 +#else
15304 +#define DBG(dev,fmt,args...) \
15305 +       do { } while (0)
15306 +#endif /* DEBUG */
15307 +
15308 +#ifdef VERBOSE
15309 +#define VDBG   DBG
15310 +#else
15311 +#define VDBG(dev,fmt,args...) \
15312 +       do { } while (0)
15313 +#endif /* VERBOSE */
15314 +
15315 +#define ERROR(dev,fmt,args...) \
15316 +       xprintk(dev , KERN_ERR , fmt , ## args)
15317 +#define WARN(dev,fmt,args...) \
15318 +       xprintk(dev , KERN_WARNING , fmt , ## args)
15319 +#define INFO(dev,fmt,args...) \
15320 +       xprintk(dev , KERN_INFO , fmt , ## args)
15321 +
15322 +/*-------------------------------------------------------------------------*/
15323 +
15324 +static unsigned buflen = 4096;
15325 +static unsigned qlen = 32;
15326 +static unsigned pattern = 0;
15327 +
15328 +module_param (buflen, uint, S_IRUGO|S_IWUSR);
15329 +module_param (qlen, uint, S_IRUGO|S_IWUSR);
15330 +module_param (pattern, uint, S_IRUGO|S_IWUSR);
15331 +
15332 +/*
15333 + * if it's nonzero, autoresume says how many seconds to wait
15334 + * before trying to wake up the host after suspend.
15335 + */
15336 +static unsigned autoresume = 0;
15337 +module_param (autoresume, uint, 0);
15338 +
15339 +/*
15340 + * Normally the "loopback" configuration is second (index 1) so
15341 + * it's not the default.  Here's where to change that order, to
15342 + * work better with hosts where config changes are problematic.
15343 + * Or controllers (like superh) that only support one config.
15344 + */
15345 +static int loopdefault = 0;
15346 +
15347 +module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
15348 +
15349 +/*-------------------------------------------------------------------------*/
15350 +
15351 +/* Thanks to NetChip Technologies for donating this product ID.
15352 + *
15353 + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
15354 + * Instead:  allocate your own, using normal USB-IF procedures.
15355 + */
15356 +#ifndef        CONFIG_USB_ZERO_HNPTEST
15357 +#define DRIVER_VENDOR_NUM      0x0525          /* NetChip */
15358 +#define DRIVER_PRODUCT_NUM     0xa4a0          /* Linux-USB "Gadget Zero" */
15359 +#else
15360 +#define DRIVER_VENDOR_NUM      0x1a0a          /* OTG test device IDs */
15361 +#define DRIVER_PRODUCT_NUM     0xbadd
15362 +#endif
15363 +
15364 +/*-------------------------------------------------------------------------*/
15365 +
15366 +/*
15367 + * DESCRIPTORS ... most are static, but strings and (full)
15368 + * configuration descriptors are built on demand.
15369 + */
15370 +
15371 +/*
15372 +#define STRING_MANUFACTURER            25
15373 +#define STRING_PRODUCT                 42
15374 +#define STRING_SERIAL                  101
15375 +*/
15376 +#define STRING_MANUFACTURER            1
15377 +#define STRING_PRODUCT                 2
15378 +#define STRING_SERIAL                  3
15379 +
15380 +#define STRING_SOURCE_SINK             250
15381 +#define STRING_LOOPBACK                        251
15382 +
15383 +/*
15384 + * This device advertises two configurations; these numbers work
15385 + * on a pxa250 as well as more flexible hardware.
15386 + */
15387 +#define        CONFIG_SOURCE_SINK      3
15388 +#define        CONFIG_LOOPBACK         2
15389 +
15390 +/*
15391 +static struct usb_device_descriptor
15392 +device_desc = {
15393 +       .bLength =              sizeof device_desc,
15394 +       .bDescriptorType =      USB_DT_DEVICE,
15395 +
15396 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
15397 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
15398 +
15399 +       .idVendor =             __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
15400 +       .idProduct =            __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
15401 +       .iManufacturer =        STRING_MANUFACTURER,
15402 +       .iProduct =             STRING_PRODUCT,
15403 +       .iSerialNumber =        STRING_SERIAL,
15404 +       .bNumConfigurations =   2,
15405 +};
15406 +*/
15407 +static struct usb_device_descriptor
15408 +device_desc = {
15409 +       .bLength =              sizeof device_desc,
15410 +       .bDescriptorType =      USB_DT_DEVICE,
15411 +       .bcdUSB =               __constant_cpu_to_le16 (0x0100),
15412 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
15413 +       .bDeviceSubClass =      0,
15414 +       .bDeviceProtocol =      0,
15415 +       .bMaxPacketSize0 =      64,
15416 +       .bcdDevice =            __constant_cpu_to_le16 (0x0100),
15417 +       .idVendor =             __constant_cpu_to_le16 (0x0499),
15418 +       .idProduct =            __constant_cpu_to_le16 (0x3002),
15419 +       .iManufacturer =        STRING_MANUFACTURER,
15420 +       .iProduct =             STRING_PRODUCT,
15421 +       .iSerialNumber =        STRING_SERIAL,
15422 +       .bNumConfigurations =   1,
15423 +};
15424 +
15425 +static struct usb_config_descriptor
15426 +z_config = {
15427 +       .bLength =              sizeof z_config,
15428 +       .bDescriptorType =      USB_DT_CONFIG,
15429 +
15430 +       /* compute wTotalLength on the fly */
15431 +       .bNumInterfaces =       2,
15432 +       .bConfigurationValue =  1,
15433 +       .iConfiguration =       0,
15434 +       .bmAttributes =         0x40,
15435 +       .bMaxPower =            0,      /* self-powered */
15436 +};
15437 +
15438 +
15439 +static struct usb_otg_descriptor
15440 +otg_descriptor = {
15441 +       .bLength =              sizeof otg_descriptor,
15442 +       .bDescriptorType =      USB_DT_OTG,
15443 +
15444 +       .bmAttributes =         USB_OTG_SRP,
15445 +};
15446 +
15447 +/* one interface in each configuration */
15448 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15449 +
15450 +/*
15451 + * usb 2.0 devices need to expose both high speed and full speed
15452 + * descriptors, unless they only run at full speed.
15453 + *
15454 + * that means alternate endpoint descriptors (bigger packets)
15455 + * and a "device qualifier" ... plus more construction options
15456 + * for the config descriptor.
15457 + */
15458 +
15459 +static struct usb_qualifier_descriptor
15460 +dev_qualifier = {
15461 +       .bLength =              sizeof dev_qualifier,
15462 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
15463 +
15464 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
15465 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
15466 +
15467 +       .bNumConfigurations =   2,
15468 +};
15469 +
15470 +
15471 +struct usb_cs_as_general_descriptor {
15472 +       __u8  bLength;
15473 +       __u8  bDescriptorType;
15474 +
15475 +       __u8  bDescriptorSubType;
15476 +       __u8  bTerminalLink;
15477 +       __u8  bDelay;
15478 +       __u16  wFormatTag;
15479 +} __attribute__ ((packed));
15480 +
15481 +struct usb_cs_as_format_descriptor {
15482 +       __u8  bLength;
15483 +       __u8  bDescriptorType;
15484 +
15485 +       __u8  bDescriptorSubType;
15486 +       __u8  bFormatType;
15487 +       __u8  bNrChannels;
15488 +       __u8  bSubframeSize;
15489 +       __u8  bBitResolution;
15490 +       __u8  bSamfreqType;
15491 +       __u8  tLowerSamFreq[3];
15492 +       __u8  tUpperSamFreq[3];
15493 +} __attribute__ ((packed));
15494 +
15495 +static const struct usb_interface_descriptor
15496 +z_audio_control_if_desc = {
15497 +       .bLength =              sizeof z_audio_control_if_desc,
15498 +       .bDescriptorType =      USB_DT_INTERFACE,
15499 +       .bInterfaceNumber = 0,
15500 +       .bAlternateSetting = 0,
15501 +       .bNumEndpoints = 0,
15502 +       .bInterfaceClass = USB_CLASS_AUDIO,
15503 +       .bInterfaceSubClass = 0x1,
15504 +       .bInterfaceProtocol = 0,
15505 +       .iInterface = 0,
15506 +};
15507 +
15508 +static const struct usb_interface_descriptor
15509 +z_audio_if_desc = {
15510 +       .bLength =              sizeof z_audio_if_desc,
15511 +       .bDescriptorType =      USB_DT_INTERFACE,
15512 +       .bInterfaceNumber = 1,
15513 +       .bAlternateSetting = 0,
15514 +       .bNumEndpoints = 0,
15515 +       .bInterfaceClass = USB_CLASS_AUDIO,
15516 +       .bInterfaceSubClass = 0x2,
15517 +       .bInterfaceProtocol = 0,
15518 +       .iInterface = 0,
15519 +};
15520 +
15521 +static const struct usb_interface_descriptor
15522 +z_audio_if_desc2 = {
15523 +       .bLength =              sizeof z_audio_if_desc,
15524 +       .bDescriptorType =      USB_DT_INTERFACE,
15525 +       .bInterfaceNumber = 1,
15526 +       .bAlternateSetting = 1,
15527 +       .bNumEndpoints = 1,
15528 +       .bInterfaceClass = USB_CLASS_AUDIO,
15529 +       .bInterfaceSubClass = 0x2,
15530 +       .bInterfaceProtocol = 0,
15531 +       .iInterface = 0,
15532 +};
15533 +
15534 +static const struct usb_cs_as_general_descriptor
15535 +z_audio_cs_as_if_desc = {
15536 +       .bLength = 7,
15537 +       .bDescriptorType = 0x24,
15538 +       
15539 +       .bDescriptorSubType = 0x01,
15540 +       .bTerminalLink = 0x01,
15541 +       .bDelay = 0x0,
15542 +       .wFormatTag = __constant_cpu_to_le16 (0x0001)
15543 +};
15544 +
15545 +
15546 +static const struct usb_cs_as_format_descriptor 
15547 +z_audio_cs_as_format_desc = {
15548 +       .bLength = 0xe,
15549 +       .bDescriptorType = 0x24,
15550 +       
15551 +       .bDescriptorSubType = 2,
15552 +       .bFormatType = 1,
15553 +       .bNrChannels = 1,
15554 +       .bSubframeSize = 1,
15555 +       .bBitResolution = 8,
15556 +       .bSamfreqType = 0,
15557 +       .tLowerSamFreq = {0x7e, 0x13, 0x00},
15558 +       .tUpperSamFreq = {0xe2, 0xd6, 0x00},
15559 +};
15560 +
15561 +static const struct usb_endpoint_descriptor 
15562 +z_iso_ep = {
15563 +       .bLength = 0x09,
15564 +       .bDescriptorType = 0x05,
15565 +       .bEndpointAddress = 0x04,
15566 +       .bmAttributes = 0x09,
15567 +       .wMaxPacketSize = 0x0038,
15568 +       .bInterval = 0x01,
15569 +       .bRefresh = 0x00,
15570 +       .bSynchAddress = 0x00,  
15571 +};
15572 +
15573 +static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15574 +
15575 +// 9 bytes
15576 +static char z_ac_interface_header_desc[] = 
15577 +{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };
15578 +
15579 +// 12 bytes
15580 +static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 
15581 +                    0x03, 0x00, 0x00, 0x00};
15582 +// 13 bytes
15583 +static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00, 
15584 +                    0x02, 0x00, 0x02, 0x00, 0x00};
15585 +// 9 bytes
15586 +static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02, 
15587 +                    0x00};
15588 +
15589 +static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 
15590 +                     0x00};
15591 +
15592 +static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15593 +
15594 +static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00, 
15595 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15596 +
15597 +static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15598 +                     0x00};
15599 +
15600 +static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15601 +
15602 +static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
15603 +                     0x00};
15604 +
15605 +static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15606 +
15607 +static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,
15608 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15609 +
15610 +static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15611 +                     0x00};
15612 +
15613 +static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15614 +
15615 +static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,
15616 +                      0x00};
15617 +
15618 +static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15619 +
15620 +static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,
15621 +                      0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15622 +
15623 +static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,
15624 +                      0x00};
15625 +
15626 +static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15627 +
15628 +static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00, 
15629 +                      0x00};
15630 +
15631 +static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15632 +
15633 +static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00, 
15634 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15635 +
15636 +static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,
15637 +                      0x00};
15638 +
15639 +static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15640 +
15641 +static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,
15642 +                      0x00};
15643 +
15644 +static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15645 +
15646 +static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00, 
15647 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15648 +
15649 +static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,
15650 +                      0x00};
15651 +
15652 +static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15653 +
15654 +
15655 +
15656 +static const struct usb_descriptor_header *z_function [] = {
15657 +       (struct usb_descriptor_header *) &z_audio_control_if_desc,
15658 +       (struct usb_descriptor_header *) &z_ac_interface_header_desc,
15659 +       (struct usb_descriptor_header *) &z_0,
15660 +       (struct usb_descriptor_header *) &z_1,
15661 +       (struct usb_descriptor_header *) &z_2,
15662 +       (struct usb_descriptor_header *) &z_audio_if_desc,
15663 +       (struct usb_descriptor_header *) &z_audio_if_desc2,
15664 +       (struct usb_descriptor_header *) &z_audio_cs_as_if_desc,
15665 +       (struct usb_descriptor_header *) &z_audio_cs_as_format_desc,
15666 +       (struct usb_descriptor_header *) &z_iso_ep,
15667 +       (struct usb_descriptor_header *) &z_iso_ep2,
15668 +       (struct usb_descriptor_header *) &za_0,
15669 +       (struct usb_descriptor_header *) &za_1,
15670 +       (struct usb_descriptor_header *) &za_2,
15671 +       (struct usb_descriptor_header *) &za_3,
15672 +       (struct usb_descriptor_header *) &za_4,
15673 +       (struct usb_descriptor_header *) &za_5,
15674 +       (struct usb_descriptor_header *) &za_6,
15675 +       (struct usb_descriptor_header *) &za_7,
15676 +       (struct usb_descriptor_header *) &za_8,
15677 +       (struct usb_descriptor_header *) &za_9,
15678 +       (struct usb_descriptor_header *) &za_10,
15679 +       (struct usb_descriptor_header *) &za_11,
15680 +       (struct usb_descriptor_header *) &za_12,
15681 +       (struct usb_descriptor_header *) &za_13,
15682 +       (struct usb_descriptor_header *) &za_14,
15683 +       (struct usb_descriptor_header *) &za_15,
15684 +       (struct usb_descriptor_header *) &za_16,
15685 +       (struct usb_descriptor_header *) &za_17,
15686 +       (struct usb_descriptor_header *) &za_18,
15687 +       (struct usb_descriptor_header *) &za_19,
15688 +       (struct usb_descriptor_header *) &za_20,
15689 +       (struct usb_descriptor_header *) &za_21,
15690 +       (struct usb_descriptor_header *) &za_22,
15691 +       (struct usb_descriptor_header *) &za_23,
15692 +       (struct usb_descriptor_header *) &za_24,
15693 +       NULL,
15694 +};
15695 +
15696 +/* maxpacket and other transfer characteristics vary by speed. */
15697 +#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
15698 +
15699 +#else
15700 +
15701 +/* if there's no high speed support, maxpacket doesn't change. */
15702 +#define ep_desc(g,hs,fs) fs
15703 +
15704 +#endif /* !CONFIG_USB_GADGET_DUALSPEED */
15705 +
15706 +static char                            manufacturer [40];
15707 +//static char                          serial [40];
15708 +static char                            serial [] = "Ser 00 em";
15709 +
15710 +/* static strings, in UTF-8 */
15711 +static struct usb_string               strings [] = {
15712 +       { STRING_MANUFACTURER, manufacturer, },
15713 +       { STRING_PRODUCT, longname, },
15714 +       { STRING_SERIAL, serial, },
15715 +       { STRING_LOOPBACK, loopback, },
15716 +       { STRING_SOURCE_SINK, source_sink, },
15717 +       {  }                    /* end of list */
15718 +};
15719 +
15720 +static struct usb_gadget_strings       stringtab = {
15721 +       .language       = 0x0409,       /* en-us */
15722 +       .strings        = strings,
15723 +};
15724 +
15725 +/*
15726 + * config descriptors are also handcrafted.  these must agree with code
15727 + * that sets configurations, and with code managing interfaces and their
15728 + * altsettings.  other complexity may come from:
15729 + *
15730 + *  - high speed support, including "other speed config" rules
15731 + *  - multiple configurations
15732 + *  - interfaces with alternate settings
15733 + *  - embedded class or vendor-specific descriptors
15734 + *
15735 + * this handles high speed, and has a second config that could as easily
15736 + * have been an alternate interface setting (on most hardware).
15737 + *
15738 + * NOTE:  to demonstrate (and test) more USB capabilities, this driver
15739 + * should include an altsetting to test interrupt transfers, including
15740 + * high bandwidth modes at high speed.  (Maybe work like Intel's test
15741 + * device?)
15742 + */
15743 +static int
15744 +config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)
15745 +{
15746 +       int len;
15747 +       const struct usb_descriptor_header **function;
15748 +       
15749 +       function = z_function;
15750 +       len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);
15751 +       if (len < 0)
15752 +               return len;
15753 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
15754 +       return len;
15755 +}
15756 +
15757 +/*-------------------------------------------------------------------------*/
15758 +
15759 +static struct usb_request *
15760 +alloc_ep_req (struct usb_ep *ep, unsigned length)
15761 +{
15762 +       struct usb_request      *req;
15763 +
15764 +       req = usb_ep_alloc_request (ep, GFP_ATOMIC);
15765 +       if (req) {
15766 +               req->length = length;
15767 +               req->buf = usb_ep_alloc_buffer (ep, length,
15768 +                               &req->dma, GFP_ATOMIC);
15769 +               if (!req->buf) {
15770 +                       usb_ep_free_request (ep, req);
15771 +                       req = NULL;
15772 +               }
15773 +       }
15774 +       return req;
15775 +}
15776 +
15777 +static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
15778 +{
15779 +       if (req->buf)
15780 +               usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
15781 +       usb_ep_free_request (ep, req);
15782 +}
15783 +
15784 +/*-------------------------------------------------------------------------*/
15785 +
15786 +/* optionally require specific source/sink data patterns  */
15787 +
15788 +static int
15789 +check_read_data (
15790 +       struct zero_dev         *dev,
15791 +       struct usb_ep           *ep,
15792 +       struct usb_request      *req
15793 +)
15794 +{
15795 +       unsigned        i;
15796 +       u8              *buf = req->buf;
15797 +
15798 +       for (i = 0; i < req->actual; i++, buf++) {
15799 +               switch (pattern) {
15800 +               /* all-zeroes has no synchronization issues */
15801 +               case 0:
15802 +                       if (*buf == 0)
15803 +                               continue;
15804 +                       break;
15805 +               /* mod63 stays in sync with short-terminated transfers,
15806 +                * or otherwise when host and gadget agree on how large
15807 +                * each usb transfer request should be.  resync is done
15808 +                * with set_interface or set_config.
15809 +                */
15810 +               case 1:
15811 +                       if (*buf == (u8)(i % 63))
15812 +                               continue;
15813 +                       break;
15814 +               }
15815 +               ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
15816 +               usb_ep_set_halt (ep);
15817 +               return -EINVAL;
15818 +       }
15819 +       return 0;
15820 +}
15821 +
15822 +/*-------------------------------------------------------------------------*/
15823 +
15824 +static void zero_reset_config (struct zero_dev *dev)
15825 +{
15826 +       if (dev->config == 0)
15827 +               return;
15828 +
15829 +       DBG (dev, "reset config\n");
15830 +
15831 +       /* just disable endpoints, forcing completion of pending i/o.
15832 +        * all our completion handlers free their requests in this case.
15833 +        */
15834 +       if (dev->in_ep) {
15835 +               usb_ep_disable (dev->in_ep);
15836 +               dev->in_ep = NULL;
15837 +       }
15838 +       if (dev->out_ep) {
15839 +               usb_ep_disable (dev->out_ep);
15840 +               dev->out_ep = NULL;
15841 +       }
15842 +       dev->config = 0;
15843 +       del_timer (&dev->resume);
15844 +}
15845 +
15846 +#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
15847 +
15848 +static void 
15849 +zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)
15850 +{
15851 +       struct zero_dev *dev = ep->driver_data;
15852 +       int             status = req->status;
15853 +       int i, j;
15854 +
15855 +       switch (status) {
15856 +
15857 +       case 0:                         /* normal completion? */
15858 +               //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);
15859 +               for (i=0, j=rbuf_start; i<req->actual; i++) {
15860 +                       //printk ("%02x ", ((__u8*)req->buf)[i]);
15861 +                       rbuf[j] = ((__u8*)req->buf)[i];
15862 +                       j++;
15863 +                       if (j >= RBUF_LEN) j=0;
15864 +               }
15865 +               rbuf_start = j;
15866 +               //printk ("\n\n");
15867 +
15868 +               if (rbuf_len < RBUF_LEN) {
15869 +                       rbuf_len += req->actual;
15870 +                       if (rbuf_len > RBUF_LEN) {
15871 +                               rbuf_len = RBUF_LEN;
15872 +                       }
15873 +               }
15874 +
15875 +               break;
15876 +
15877 +       /* this endpoint is normally active while we're configured */
15878 +       case -ECONNABORTED:             /* hardware forced ep reset */
15879 +       case -ECONNRESET:               /* request dequeued */
15880 +       case -ESHUTDOWN:                /* disconnect from host */
15881 +               VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
15882 +                               req->actual, req->length);
15883 +               if (ep == dev->out_ep)
15884 +                       check_read_data (dev, ep, req);
15885 +               free_ep_req (ep, req);
15886 +               return;
15887 +
15888 +       case -EOVERFLOW:                /* buffer overrun on read means that
15889 +                                        * we didn't provide a big enough
15890 +                                        * buffer.
15891 +                                        */
15892 +       default:
15893 +#if 1
15894 +               DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
15895 +                               status, req->actual, req->length);
15896 +#endif
15897 +       case -EREMOTEIO:                /* short read */
15898 +               break;
15899 +       }
15900 +
15901 +       status = usb_ep_queue (ep, req, GFP_ATOMIC);
15902 +       if (status) {
15903 +               ERROR (dev, "kill %s:  resubmit %d bytes --> %d\n",
15904 +                               ep->name, req->length, status);
15905 +               usb_ep_set_halt (ep);
15906 +               /* FIXME recover later ... somehow */
15907 +       }
15908 +}
15909 +
15910 +static struct usb_request *
15911 +zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)
15912 +{
15913 +       struct usb_request      *req;
15914 +       int                     status;
15915 +
15916 +       req = alloc_ep_req (ep, 512);
15917 +       if (!req)
15918 +               return NULL;
15919 +
15920 +       req->complete = zero_isoc_complete;
15921 +
15922 +       status = usb_ep_queue (ep, req, gfp_flags);
15923 +       if (status) {
15924 +               struct zero_dev *dev = ep->driver_data;
15925 +
15926 +               ERROR (dev, "start %s --> %d\n", ep->name, status);
15927 +               free_ep_req (ep, req);
15928 +               req = NULL;
15929 +       }
15930 +
15931 +       return req;
15932 +}
15933 +
15934 +/* change our operational config.  this code must agree with the code
15935 + * that returns config descriptors, and altsetting code.
15936 + *
15937 + * it's also responsible for power management interactions. some
15938 + * configurations might not work with our current power sources.
15939 + *
15940 + * note that some device controller hardware will constrain what this
15941 + * code can do, perhaps by disallowing more than one configuration or
15942 + * by limiting configuration choices (like the pxa2xx).
15943 + */
15944 +static int
15945 +zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
15946 +{
15947 +       int                     result = 0;
15948 +       struct usb_gadget       *gadget = dev->gadget;
15949 +       const struct usb_endpoint_descriptor    *d;
15950 +       struct usb_ep           *ep;
15951 +
15952 +       if (number == dev->config)
15953 +               return 0;
15954 +
15955 +       zero_reset_config (dev);
15956 +
15957 +       gadget_for_each_ep (ep, gadget) {
15958 +
15959 +               if (strcmp (ep->name, "ep4") == 0) {
15960 +
15961 +                       d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6
15962 +                       result = usb_ep_enable (ep, d);
15963 +
15964 +                       if (result == 0) {
15965 +                               ep->driver_data = dev;
15966 +                               dev->in_ep = ep;
15967 +
15968 +                               if (zero_start_isoc_ep (ep, gfp_flags) != 0) {
15969 +
15970 +                                       dev->in_ep = ep;
15971 +                                       continue;
15972 +                               }
15973 +
15974 +                               usb_ep_disable (ep);
15975 +                               result = -EIO;
15976 +                       }
15977 +               }
15978 +
15979 +       }
15980 +
15981 +       dev->config = number;
15982 +       return result;
15983 +}
15984 +
15985 +/*-------------------------------------------------------------------------*/
15986 +
15987 +static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
15988 +{
15989 +       if (req->status || req->actual != req->length)
15990 +               DBG ((struct zero_dev *) ep->driver_data,
15991 +                               "setup complete --> %d, %d/%d\n",
15992 +                               req->status, req->actual, req->length);
15993 +}
15994 +
15995 +/*
15996 + * The setup() callback implements all the ep0 functionality that's
15997 + * not handled lower down, in hardware or the hardware driver (like
15998 + * device and endpoint feature flags, and their status).  It's all
15999 + * housekeeping for the gadget function we're implementing.  Most of
16000 + * the work is in config-specific setup.
16001 + */
16002 +static int
16003 +zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
16004 +{
16005 +       struct zero_dev         *dev = get_gadget_data (gadget);
16006 +       struct usb_request      *req = dev->req;
16007 +       int                     value = -EOPNOTSUPP;
16008 +
16009 +       /* usually this stores reply data in the pre-allocated ep0 buffer,
16010 +        * but config change events will reconfigure hardware.
16011 +        */
16012 +       req->zero = 0;
16013 +       switch (ctrl->bRequest) {
16014 +
16015 +       case USB_REQ_GET_DESCRIPTOR:
16016 +
16017 +               switch (ctrl->wValue >> 8) {
16018 +
16019 +               case USB_DT_DEVICE:
16020 +                       value = min (ctrl->wLength, (u16) sizeof device_desc);
16021 +                       memcpy (req->buf, &device_desc, value);
16022 +                       break;
16023 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16024 +               case USB_DT_DEVICE_QUALIFIER:
16025 +                       if (!gadget->is_dualspeed)
16026 +                               break;
16027 +                       value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
16028 +                       memcpy (req->buf, &dev_qualifier, value);
16029 +                       break;
16030 +
16031 +               case USB_DT_OTHER_SPEED_CONFIG:
16032 +                       if (!gadget->is_dualspeed)
16033 +                               break;
16034 +                       // FALLTHROUGH
16035 +#endif /* CONFIG_USB_GADGET_DUALSPEED */
16036 +               case USB_DT_CONFIG:
16037 +                       value = config_buf (gadget, req->buf,
16038 +                                       ctrl->wValue >> 8,
16039 +                                       ctrl->wValue & 0xff);
16040 +                       if (value >= 0)
16041 +                               value = min (ctrl->wLength, (u16) value);
16042 +                       break;
16043 +
16044 +               case USB_DT_STRING:
16045 +                       /* wIndex == language code.
16046 +                        * this driver only handles one language, you can
16047 +                        * add string tables for other languages, using
16048 +                        * any UTF-8 characters
16049 +                        */
16050 +                       value = usb_gadget_get_string (&stringtab,
16051 +                                       ctrl->wValue & 0xff, req->buf);
16052 +                       if (value >= 0) {
16053 +                               value = min (ctrl->wLength, (u16) value);
16054 +                       }
16055 +                       break;
16056 +               }
16057 +               break;
16058 +
16059 +       /* currently two configs, two speeds */
16060 +       case USB_REQ_SET_CONFIGURATION:
16061 +               if (ctrl->bRequestType != 0)
16062 +                       goto unknown;
16063 +
16064 +               spin_lock (&dev->lock);
16065 +               value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
16066 +               spin_unlock (&dev->lock);
16067 +               break;
16068 +       case USB_REQ_GET_CONFIGURATION:
16069 +               if (ctrl->bRequestType != USB_DIR_IN)
16070 +                       goto unknown;
16071 +               *(u8 *)req->buf = dev->config;
16072 +               value = min (ctrl->wLength, (u16) 1);
16073 +               break;
16074 +
16075 +       /* until we add altsetting support, or other interfaces,
16076 +        * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
16077 +        * and already killed pending endpoint I/O.
16078 +        */
16079 +       case USB_REQ_SET_INTERFACE:
16080 +
16081 +               if (ctrl->bRequestType != USB_RECIP_INTERFACE)
16082 +                       goto unknown;
16083 +               spin_lock (&dev->lock);
16084 +               if (dev->config) {
16085 +                       u8              config = dev->config;
16086 +
16087 +                       /* resets interface configuration, forgets about
16088 +                        * previous transaction state (queued bufs, etc)
16089 +                        * and re-inits endpoint state (toggle etc)
16090 +                        * no response queued, just zero status == success.
16091 +                        * if we had more than one interface we couldn't
16092 +                        * use this "reset the config" shortcut.
16093 +                        */
16094 +                       zero_reset_config (dev);
16095 +                       zero_set_config (dev, config, GFP_ATOMIC);
16096 +                       value = 0;
16097 +               }
16098 +               spin_unlock (&dev->lock);
16099 +               break;
16100 +       case USB_REQ_GET_INTERFACE:
16101 +               if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {
16102 +                       value = ctrl->wLength;
16103 +                       break;
16104 +               }
16105 +               else {
16106 +                       if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
16107 +                               goto unknown;
16108 +                       if (!dev->config)
16109 +                               break;
16110 +                       if (ctrl->wIndex != 0) {
16111 +                               value = -EDOM;
16112 +                               break;
16113 +                       }
16114 +                       *(u8 *)req->buf = 0;
16115 +                       value = min (ctrl->wLength, (u16) 1);
16116 +               }
16117 +               break;
16118 +
16119 +       /*
16120 +        * These are the same vendor-specific requests supported by
16121 +        * Intel's USB 2.0 compliance test devices.  We exceed that
16122 +        * device spec by allowing multiple-packet requests.
16123 +        */
16124 +       case 0x5b:      /* control WRITE test -- fill the buffer */
16125 +               if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
16126 +                       goto unknown;
16127 +               if (ctrl->wValue || ctrl->wIndex)
16128 +                       break;
16129 +               /* just read that many bytes into the buffer */
16130 +               if (ctrl->wLength > USB_BUFSIZ)
16131 +                       break;
16132 +               value = ctrl->wLength;
16133 +               break;
16134 +       case 0x5c:      /* control READ test -- return the buffer */
16135 +               if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
16136 +                       goto unknown;
16137 +               if (ctrl->wValue || ctrl->wIndex)
16138 +                       break;
16139 +               /* expect those bytes are still in the buffer; send back */
16140 +               if (ctrl->wLength > USB_BUFSIZ
16141 +                               || ctrl->wLength != req->length)
16142 +                       break;
16143 +               value = ctrl->wLength;
16144 +               break;
16145 +
16146 +       case 0x01: // SET_CUR
16147 +       case 0x02:
16148 +       case 0x03:
16149 +       case 0x04:
16150 +       case 0x05:
16151 +               value = ctrl->wLength;
16152 +               break;
16153 +       case 0x81:
16154 +               switch (ctrl->wValue) {
16155 +               case 0x0201:
16156 +               case 0x0202:
16157 +                       ((u8*)req->buf)[0] = 0x00;
16158 +                       ((u8*)req->buf)[1] = 0xe3;
16159 +                       break;
16160 +               case 0x0300:
16161 +               case 0x0500:
16162 +                       ((u8*)req->buf)[0] = 0x00;
16163 +                       break;
16164 +               }
16165 +               //((u8*)req->buf)[0] = 0x81;
16166 +               //((u8*)req->buf)[1] = 0x81;
16167 +               value = ctrl->wLength;
16168 +               break;
16169 +       case 0x82:
16170 +               switch (ctrl->wValue) {
16171 +               case 0x0201:
16172 +               case 0x0202:
16173 +                       ((u8*)req->buf)[0] = 0x00;
16174 +                       ((u8*)req->buf)[1] = 0xc3;
16175 +                       break;
16176 +               case 0x0300:
16177 +               case 0x0500:
16178 +                       ((u8*)req->buf)[0] = 0x00;
16179 +                       break;
16180 +               }
16181 +               //((u8*)req->buf)[0] = 0x82;
16182 +               //((u8*)req->buf)[1] = 0x82;
16183 +               value = ctrl->wLength;
16184 +               break;
16185 +       case 0x83:
16186 +               switch (ctrl->wValue) {
16187 +               case 0x0201:
16188 +               case 0x0202:
16189 +                       ((u8*)req->buf)[0] = 0x00;
16190 +                       ((u8*)req->buf)[1] = 0x00;
16191 +                       break;
16192 +               case 0x0300:
16193 +                       ((u8*)req->buf)[0] = 0x60;
16194 +                       break;
16195 +               case 0x0500:    
16196 +                       ((u8*)req->buf)[0] = 0x18;
16197 +                       break;
16198 +               }
16199 +               //((u8*)req->buf)[0] = 0x83;
16200 +               //((u8*)req->buf)[1] = 0x83;
16201 +               value = ctrl->wLength;
16202 +               break;
16203 +       case 0x84:
16204 +               switch (ctrl->wValue) {
16205 +               case 0x0201:
16206 +               case 0x0202:
16207 +                       ((u8*)req->buf)[0] = 0x00;
16208 +                       ((u8*)req->buf)[1] = 0x01;
16209 +                       break;
16210 +               case 0x0300:
16211 +               case 0x0500:
16212 +                       ((u8*)req->buf)[0] = 0x08;
16213 +                       break;
16214 +               }
16215 +               //((u8*)req->buf)[0] = 0x84;
16216 +               //((u8*)req->buf)[1] = 0x84;
16217 +               value = ctrl->wLength;
16218 +               break;
16219 +       case 0x85:
16220 +               ((u8*)req->buf)[0] = 0x85;
16221 +               ((u8*)req->buf)[1] = 0x85;
16222 +               value = ctrl->wLength;
16223 +               break;
16224 +
16225 +       
16226 +       default:
16227 +unknown:
16228 +               printk("unknown control req%02x.%02x v%04x i%04x l%d\n",
16229 +                       ctrl->bRequestType, ctrl->bRequest,
16230 +                       ctrl->wValue, ctrl->wIndex, ctrl->wLength);
16231 +       }
16232 +
16233 +       /* respond with data transfer before status phase? */
16234 +       if (value >= 0) {
16235 +               req->length = value;
16236 +               req->zero = value < ctrl->wLength
16237 +                               && (value % gadget->ep0->maxpacket) == 0;
16238 +               value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
16239 +               if (value < 0) {
16240 +                       DBG (dev, "ep_queue < 0 --> %d\n", value);
16241 +                       req->status = 0;
16242 +                       zero_setup_complete (gadget->ep0, req);
16243 +               }
16244 +       }
16245 +
16246 +       /* device either stalls (value < 0) or reports success */
16247 +       return value;
16248 +}
16249 +
16250 +static void
16251 +zero_disconnect (struct usb_gadget *gadget)
16252 +{
16253 +       struct zero_dev         *dev = get_gadget_data (gadget);
16254 +       unsigned long           flags;
16255 +
16256 +       spin_lock_irqsave (&dev->lock, flags);
16257 +       zero_reset_config (dev);
16258 +
16259 +       /* a more significant application might have some non-usb
16260 +        * activities to quiesce here, saving resources like power
16261 +        * or pushing the notification up a network stack.
16262 +        */
16263 +       spin_unlock_irqrestore (&dev->lock, flags);
16264 +
16265 +       /* next we may get setup() calls to enumerate new connections;
16266 +        * or an unbind() during shutdown (including removing module).
16267 +        */
16268 +}
16269 +
16270 +static void
16271 +zero_autoresume (unsigned long _dev)
16272 +{
16273 +       struct zero_dev *dev = (struct zero_dev *) _dev;
16274 +       int             status;
16275 +
16276 +       /* normally the host would be woken up for something
16277 +        * more significant than just a timer firing...
16278 +        */
16279 +       if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
16280 +               status = usb_gadget_wakeup (dev->gadget);
16281 +               DBG (dev, "wakeup --> %d\n", status);
16282 +       }
16283 +}
16284 +
16285 +/*-------------------------------------------------------------------------*/
16286 +
16287 +static void
16288 +zero_unbind (struct usb_gadget *gadget)
16289 +{
16290 +       struct zero_dev         *dev = get_gadget_data (gadget);
16291 +
16292 +       DBG (dev, "unbind\n");
16293 +
16294 +       /* we've already been disconnected ... no i/o is active */
16295 +       if (dev->req)
16296 +               free_ep_req (gadget->ep0, dev->req);
16297 +       del_timer_sync (&dev->resume);
16298 +       kfree (dev);
16299 +       set_gadget_data (gadget, NULL);
16300 +}
16301 +
16302 +static int
16303 +zero_bind (struct usb_gadget *gadget)
16304 +{
16305 +       struct zero_dev         *dev;
16306 +       //struct usb_ep         *ep;
16307 +
16308 +       printk("binding\n");
16309 +       /*
16310 +        * DRIVER POLICY CHOICE:  you may want to do this differently.
16311 +        * One thing to avoid is reusing a bcdDevice revision code
16312 +        * with different host-visible configurations or behavior
16313 +        * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
16314 +        */
16315 +       //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
16316 +
16317 +
16318 +       /* ok, we made sense of the hardware ... */
16319 +       dev = kmalloc (sizeof *dev, SLAB_KERNEL);
16320 +       if (!dev)
16321 +               return -ENOMEM;
16322 +       memset (dev, 0, sizeof *dev);
16323 +       spin_lock_init (&dev->lock);
16324 +       dev->gadget = gadget;
16325 +       set_gadget_data (gadget, dev);
16326 +
16327 +       /* preallocate control response and buffer */
16328 +       dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
16329 +       if (!dev->req)
16330 +               goto enomem;
16331 +       dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
16332 +                               &dev->req->dma, GFP_KERNEL);
16333 +       if (!dev->req->buf)
16334 +               goto enomem;
16335 +
16336 +       dev->req->complete = zero_setup_complete;
16337 +
16338 +       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
16339 +
16340 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16341 +       /* assume ep0 uses the same value for both speeds ... */
16342 +       dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
16343 +
16344 +       /* and that all endpoints are dual-speed */
16345 +       //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
16346 +       //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
16347 +#endif
16348 +
16349 +       usb_gadget_set_selfpowered (gadget);
16350 +
16351 +       init_timer (&dev->resume);
16352 +       dev->resume.function = zero_autoresume;
16353 +       dev->resume.data = (unsigned long) dev;
16354 +
16355 +       gadget->ep0->driver_data = dev;
16356 +
16357 +       INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
16358 +       INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
16359 +               EP_OUT_NAME, EP_IN_NAME);
16360 +
16361 +       snprintf (manufacturer, sizeof manufacturer,
16362 +               UTS_SYSNAME " " UTS_RELEASE " with %s",
16363 +               gadget->name);
16364 +
16365 +       return 0;
16366 +
16367 +enomem:
16368 +       zero_unbind (gadget);
16369 +       return -ENOMEM;
16370 +}
16371 +
16372 +/*-------------------------------------------------------------------------*/
16373 +
16374 +static void
16375 +zero_suspend (struct usb_gadget *gadget)
16376 +{
16377 +       struct zero_dev         *dev = get_gadget_data (gadget);
16378 +
16379 +       if (gadget->speed == USB_SPEED_UNKNOWN)
16380 +               return;
16381 +
16382 +       if (autoresume) {
16383 +               mod_timer (&dev->resume, jiffies + (HZ * autoresume));
16384 +               DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
16385 +       } else
16386 +               DBG (dev, "suspend\n");
16387 +}
16388 +
16389 +static void
16390 +zero_resume (struct usb_gadget *gadget)
16391 +{
16392 +       struct zero_dev         *dev = get_gadget_data (gadget);
16393 +
16394 +       DBG (dev, "resume\n");
16395 +       del_timer (&dev->resume);
16396 +}
16397 +
16398 +
16399 +/*-------------------------------------------------------------------------*/
16400 +
16401 +static struct usb_gadget_driver zero_driver = {
16402 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16403 +       .speed          = USB_SPEED_HIGH,
16404 +#else
16405 +       .speed          = USB_SPEED_FULL,
16406 +#endif
16407 +       .function       = (char *) longname,
16408 +       .bind           = zero_bind,
16409 +       .unbind         = zero_unbind,
16410 +
16411 +       .setup          = zero_setup,
16412 +       .disconnect     = zero_disconnect,
16413 +
16414 +       .suspend        = zero_suspend,
16415 +       .resume         = zero_resume,
16416 +
16417 +       .driver         = {
16418 +               .name           = (char *) shortname,
16419 +               // .shutdown = ...
16420 +               // .suspend = ...
16421 +               // .resume = ...
16422 +       },
16423 +};
16424 +
16425 +MODULE_AUTHOR ("David Brownell");
16426 +MODULE_LICENSE ("Dual BSD/GPL");
16427 +
16428 +static struct proc_dir_entry *pdir, *pfile;
16429 +
16430 +static int isoc_read_data (char *page, char **start,
16431 +                          off_t off, int count,
16432 +                          int *eof, void *data)
16433 +{
16434 +       int i;
16435 +       static int c = 0;
16436 +       static int done = 0;
16437 +       static int s = 0;
16438 +
16439 +/*
16440 +       printk ("\ncount: %d\n", count);
16441 +       printk ("rbuf_start: %d\n", rbuf_start);
16442 +       printk ("rbuf_len: %d\n", rbuf_len);
16443 +       printk ("off: %d\n", off);
16444 +       printk ("start: %p\n\n", *start);
16445 +*/
16446 +       if (done) {
16447 +               c = 0;
16448 +               done = 0;
16449 +               *eof = 1;
16450 +               return 0;
16451 +       }
16452 +
16453 +       if (c == 0) {
16454 +               if (rbuf_len == RBUF_LEN)
16455 +                       s = rbuf_start;
16456 +               else s = 0;
16457 +       }
16458 +
16459 +       for (i=0; i<count && c<rbuf_len; i++, c++) {
16460 +               page[i] = rbuf[(c+s) % RBUF_LEN];
16461 +       }
16462 +       *start = page;
16463 +       
16464 +       if (c >= rbuf_len) {
16465 +               *eof = 1;
16466 +               done = 1;
16467 +       }
16468 +
16469 +
16470 +       return i;
16471 +}
16472 +
16473 +static int __init init (void)
16474 +{
16475 +
16476 +       int retval = 0;
16477 +
16478 +       pdir = proc_mkdir("isoc_test", NULL);
16479 +       if(pdir == NULL) {
16480 +               retval = -ENOMEM;
16481 +               printk("Error creating dir\n");
16482 +               goto done;
16483 +       }
16484 +       pdir->owner = THIS_MODULE;
16485 +
16486 +       pfile = create_proc_read_entry("isoc_data",
16487 +                                      0444, pdir,
16488 +                                      isoc_read_data,
16489 +                                      NULL);
16490 +       if (pfile == NULL) {
16491 +               retval = -ENOMEM;
16492 +               printk("Error creating file\n");
16493 +               goto no_file;
16494 +       }
16495 +       pfile->owner = THIS_MODULE;
16496 +
16497 +       return usb_gadget_register_driver (&zero_driver);
16498 +
16499 + no_file:
16500 +       remove_proc_entry("isoc_data", NULL);
16501 + done:
16502 +       return retval;
16503 +}
16504 +module_init (init);
16505 +
16506 +static void __exit cleanup (void)
16507 +{
16508 +
16509 +       usb_gadget_unregister_driver (&zero_driver);
16510 +       
16511 +       remove_proc_entry("isoc_data", pdir);
16512 +       remove_proc_entry("isoc_test", NULL);
16513 +}
16514 +module_exit (cleanup);
16515 diff --git a/drivers/usb/host/dwc_otg/dwc_cfi_common.h b/drivers/usb/host/dwc_otg/dwc_cfi_common.h
16516 new file mode 100644
16517 index 0000000..be56af4
16518 --- /dev/null
16519 +++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h
16520 @@ -0,0 +1,142 @@
16521 +/* ==========================================================================
16522 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16523 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16524 + * otherwise expressly agreed to in writing between Synopsys and you.
16525 + * 
16526 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16527 + * any End User Software License Agreement or Agreement for Licensed Product
16528 + * with Synopsys or any supplement thereto. You are permitted to use and
16529 + * redistribute this Software in source and binary forms, with or without
16530 + * modification, provided that redistributions of source code must retain this
16531 + * notice. You may not view, use, disclose, copy or distribute this file or
16532 + * any information contained herein except pursuant to this license grant from
16533 + * Synopsys. If you do not agree with this notice, including the disclaimer
16534 + * below, then you are not authorized to use the Software.
16535 + * 
16536 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16537 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16538 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16539 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16540 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16541 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16542 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16543 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16544 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16545 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16546 + * DAMAGE.
16547 + * ========================================================================== */
16548 +
16549 +#if !defined(__DWC_CFI_COMMON_H__)
16550 +#define __DWC_CFI_COMMON_H__
16551 +
16552 +//#include <linux/types.h>
16553 +
16554 +/**
16555 + * @file 
16556 + *
16557 + * This file contains the CFI specific common constants, interfaces
16558 + * (functions and macros) and structures for Linux. No PCD specific
16559 + * data structure or definition is to be included in this file.
16560 + *
16561 + */
16562 +
16563 +/** This is a request for all Core Features */
16564 +#define VEN_CORE_GET_FEATURES          0xB1
16565 +
16566 +/** This is a request to get the value of a specific Core Feature */
16567 +#define VEN_CORE_GET_FEATURE           0xB2
16568 +
16569 +/** This command allows the host to set the value of a specific Core Feature */
16570 +#define VEN_CORE_SET_FEATURE           0xB3
16571 +
16572 +/** This command allows the host to set the default values of 
16573 + * either all or any specific Core Feature 
16574 + */
16575 +#define VEN_CORE_RESET_FEATURES                0xB4
16576 +
16577 +/** This command forces the PCD to write the deferred values of a Core Features */
16578 +#define VEN_CORE_ACTIVATE_FEATURES     0xB5
16579 +
16580 +/** This request reads a DWORD value from a register at the specified offset */
16581 +#define VEN_CORE_READ_REGISTER         0xB6
16582 +
16583 +/** This request writes a DWORD value into a register at the specified offset */
16584 +#define VEN_CORE_WRITE_REGISTER                0xB7
16585 +
16586 +/** This structure is the header of the Core Features dataset returned to 
16587 + *  the Host
16588 + */
16589 +struct cfi_all_features_header {
16590 +/** The features header structure length is */
16591 +#define CFI_ALL_FEATURES_HDR_LEN               8
16592 +       /**
16593 +        * The total length of the features dataset returned to the Host 
16594 +        */
16595 +       uint16_t wTotalLen;
16596 +
16597 +       /**
16598 +        * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H).
16599 +        * This field identifies the version of the CFI Specification with which 
16600 +        * the device is compliant.
16601 +        */
16602 +       uint16_t wVersion;
16603 +
16604 +       /** The ID of the Core */
16605 +       uint16_t wCoreID;
16606 +#define CFI_CORE_ID_UDC                1
16607 +#define CFI_CORE_ID_OTG                2
16608 +#define CFI_CORE_ID_WUDEV      3
16609 +
16610 +       /** Number of features returned by VEN_CORE_GET_FEATURES request */
16611 +       uint16_t wNumFeatures;
16612 +} UPACKED;
16613 +
16614 +typedef struct cfi_all_features_header cfi_all_features_header_t;
16615 +
16616 +/** This structure is a header of the Core Feature descriptor dataset returned to 
16617 + *  the Host after the VEN_CORE_GET_FEATURES request
16618 + */
16619 +struct cfi_feature_desc_header {
16620 +#define CFI_FEATURE_DESC_HDR_LEN       8
16621 +
16622 +       /** The feature ID */
16623 +       uint16_t wFeatureID;
16624 +
16625 +       /** Length of this feature descriptor in bytes - including the
16626 +        * length of the feature name string
16627 +        */
16628 +       uint16_t wLength;
16629 +
16630 +       /** The data length of this feature in bytes */
16631 +       uint16_t wDataLength;
16632 +
16633 +       /** 
16634 +        * Attributes of this features 
16635 +        * D0: Access rights
16636 +        * 0 - Read/Write
16637 +        * 1 - Read only
16638 +        */
16639 +       uint8_t bmAttributes;
16640 +#define CFI_FEATURE_ATTR_RO            1
16641 +#define CFI_FEATURE_ATTR_RW            0
16642 +
16643 +       /** Length of the feature name in bytes */
16644 +       uint8_t bNameLen;
16645 +
16646 +       /** The feature name buffer */
16647 +       //uint8_t *name;
16648 +} UPACKED;
16649 +
16650 +typedef struct cfi_feature_desc_header cfi_feature_desc_header_t;
16651 +
16652 +/**
16653 + * This structure describes a NULL terminated string referenced by its id field.
16654 + * It is very similar to usb_string structure but has the id field type set to 16-bit.
16655 + */
16656 +struct cfi_string {
16657 +       uint16_t id;
16658 +       const uint8_t *s;
16659 +};
16660 +typedef struct cfi_string cfi_string_t;
16661 +
16662 +#endif
16663 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.c b/drivers/usb/host/dwc_otg/dwc_otg_adp.c
16664 new file mode 100644
16665 index 0000000..0877472
16666 --- /dev/null
16667 +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.c
16668 @@ -0,0 +1,854 @@
16669 +/* ==========================================================================
16670 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
16671 + * $Revision: #12 $
16672 + * $Date: 2011/10/26 $
16673 + * $Change: 1873028 $
16674 + *
16675 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16676 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16677 + * otherwise expressly agreed to in writing between Synopsys and you.
16678 + *
16679 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16680 + * any End User Software License Agreement or Agreement for Licensed Product
16681 + * with Synopsys or any supplement thereto. You are permitted to use and
16682 + * redistribute this Software in source and binary forms, with or without
16683 + * modification, provided that redistributions of source code must retain this
16684 + * notice. You may not view, use, disclose, copy or distribute this file or
16685 + * any information contained herein except pursuant to this license grant from
16686 + * Synopsys. If you do not agree with this notice, including the disclaimer
16687 + * below, then you are not authorized to use the Software.
16688 + *
16689 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16690 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16691 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16692 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16693 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16694 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16695 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16696 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16697 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16698 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16699 + * DAMAGE.
16700 + * ========================================================================== */
16701 +
16702 +#include "dwc_os.h"
16703 +#include "dwc_otg_regs.h"
16704 +#include "dwc_otg_cil.h"
16705 +#include "dwc_otg_adp.h"
16706 +
16707 +/** @file
16708 + *
16709 + * This file contains the most of the Attach Detect Protocol implementation for
16710 + * the driver to support OTG Rev2.0.
16711 + *
16712 + */
16713 +
16714 +void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)
16715 +{
16716 +       adpctl_data_t adpctl;
16717 +
16718 +       adpctl.d32 = value;
16719 +       adpctl.b.ar = 0x2;
16720 +
16721 +       DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16722 +
16723 +       while (adpctl.b.ar) {
16724 +               adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16725 +       }
16726 +
16727 +}
16728 +
16729 +/**
16730 + * Function is called to read ADP registers
16731 + */
16732 +uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)
16733 +{
16734 +       adpctl_data_t adpctl;
16735 +
16736 +       adpctl.d32 = 0;
16737 +       adpctl.b.ar = 0x1;
16738 +
16739 +       DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16740 +
16741 +       while (adpctl.b.ar) {
16742 +               adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16743 +       }
16744 +
16745 +       return adpctl.d32;
16746 +}
16747 +
16748 +/**
16749 + * Function is called to read ADPCTL register and filter Write-clear bits
16750 + */
16751 +uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)
16752 +{
16753 +       adpctl_data_t adpctl;
16754 +
16755 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16756 +       adpctl.b.adp_tmout_int = 0;
16757 +       adpctl.b.adp_prb_int = 0;
16758 +       adpctl.b.adp_tmout_int = 0;
16759 +               
16760 +       return adpctl.d32;
16761 +}
16762 +
16763 +/**
16764 + * Function is called to write ADP registers
16765 + */
16766 +void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,
16767 +                           uint32_t set)
16768 +{
16769 +       dwc_otg_adp_write_reg(core_if,
16770 +                             (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
16771 +}
16772 +
16773 +static void adp_sense_timeout(void *ptr)
16774 +{
16775 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16776 +       core_if->adp.sense_timer_started = 0;
16777 +       DWC_PRINTF("ADP SENSE TIMEOUT\n");
16778 +       if (core_if->adp_enable) {
16779 +               dwc_otg_adp_sense_stop(core_if);
16780 +               dwc_otg_adp_probe_start(core_if);
16781 +       }
16782 +}
16783 +
16784 +/**
16785 + * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
16786 + */
16787 +static void adp_vbuson_timeout(void *ptr)
16788 +{
16789 +       gpwrdn_data_t gpwrdn;
16790 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16791 +       hprt0_data_t hprt0 = {.d32 = 0 };
16792 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
16793 +       DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
16794 +       if (core_if) {
16795 +               core_if->adp.vbuson_timer_started = 0;
16796 +               /* Turn off vbus */
16797 +               hprt0.b.prtpwr = 1;
16798 +               DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
16799 +               gpwrdn.d32 = 0;
16800 +
16801 +               /* Power off the core */
16802 +               if (core_if->power_down == 2) {
16803 +                       /* Enable Wakeup Logic */
16804 +//                      gpwrdn.b.wkupactiv = 1;
16805 +                       gpwrdn.b.pmuactv = 0;
16806 +                       gpwrdn.b.pwrdnrstn = 1;
16807 +                       gpwrdn.b.pwrdnclmp = 1;
16808 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16809 +                                        gpwrdn.d32);
16810 +
16811 +                       /* Suspend the Phy Clock */
16812 +                       pcgcctl.b.stoppclk = 1;
16813 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
16814 +
16815 +                       /* Switch on VDD */
16816 +//                      gpwrdn.b.wkupactiv = 1;
16817 +                       gpwrdn.b.pmuactv = 1;
16818 +                       gpwrdn.b.pwrdnrstn = 1;
16819 +                       gpwrdn.b.pwrdnclmp = 1;
16820 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16821 +                                        gpwrdn.d32);
16822 +               } else {
16823 +                       /* Enable Power Down Logic */
16824 +                       gpwrdn.b.pmuintsel = 1;
16825 +                       gpwrdn.b.pmuactv = 1;
16826 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16827 +               }
16828 +
16829 +               /* Power off the core */
16830 +               if (core_if->power_down == 2) {
16831 +                       gpwrdn.d32 = 0;
16832 +                       gpwrdn.b.pwrdnswtch = 1;
16833 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
16834 +                                        gpwrdn.d32, 0);
16835 +               }
16836 +
16837 +               /* Unmask SRP detected interrupt from Power Down Logic */
16838 +               gpwrdn.d32 = 0;
16839 +               gpwrdn.b.srp_det_msk = 1;
16840 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16841 +
16842 +               dwc_otg_adp_probe_start(core_if);
16843 +               dwc_otg_dump_global_registers(core_if);
16844 +               dwc_otg_dump_host_registers(core_if);
16845 +       }
16846 +
16847 +}
16848 +
16849 +/**
16850 + * Start the ADP Initial Probe timer to detect if Port Connected interrupt is 
16851 + * not asserted within 1.1 seconds.
16852 + *
16853 + * @param core_if the pointer to core_if strucure.
16854 + */
16855 +void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
16856 +{
16857 +       core_if->adp.vbuson_timer_started = 1;
16858 +       if (core_if->adp.vbuson_timer)
16859 +       {
16860 +               DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
16861 +               /* 1.1 secs + 60ms necessary for cil_hcd_start*/
16862 +               DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
16863 +       } else {
16864 +               DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
16865 +       }
16866 +}
16867 +
16868 +#if 0
16869 +/**
16870 + * Masks all DWC OTG core interrupts
16871 + *
16872 + */
16873 +static void mask_all_interrupts(dwc_otg_core_if_t * core_if)
16874 +{
16875 +       int i;
16876 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
16877 +
16878 +       /* Mask Host Interrupts */
16879 +
16880 +       /* Clear and disable HCINTs */
16881 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
16882 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
16883 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);
16884 +
16885 +       }
16886 +
16887 +       /* Clear and disable HAINT */
16888 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
16889 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
16890 +
16891 +       /* Mask Device Interrupts */
16892 +       if (!core_if->multiproc_int_enable) {
16893 +               /* Clear and disable IN Endpoint interrupts */
16894 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
16895 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
16896 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16897 +                                       diepint, 0xFFFFFFFF);
16898 +               }
16899 +
16900 +               /* Clear and disable OUT Endpoint interrupts */
16901 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
16902 +               for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
16903 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16904 +                                       doepint, 0xFFFFFFFF);
16905 +               }
16906 +
16907 +               /* Clear and disable DAINT */
16908 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
16909 +                               0xFFFFFFFF);
16910 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
16911 +       } else {
16912 +               for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
16913 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16914 +                                       diepeachintmsk[i], 0);
16915 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16916 +                                       diepint, 0xFFFFFFFF);
16917 +               }
16918 +
16919 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
16920 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16921 +                                       doepeachintmsk[i], 0);
16922 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16923 +                                       doepint, 0xFFFFFFFF);
16924 +               }
16925 +
16926 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
16927 +                               0);
16928 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
16929 +                               0xFFFFFFFF);
16930 +
16931 +       }
16932 +
16933 +       /* Disable interrupts */
16934 +       ahbcfg.b.glblintrmsk = 1;
16935 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
16936 +
16937 +       /* Disable all interrupts. */
16938 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
16939 +
16940 +       /* Clear any pending interrupts */
16941 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
16942 +
16943 +       /* Clear any pending OTG Interrupts */
16944 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
16945 +}
16946 +
16947 +/**
16948 + * Unmask Port Connection Detected interrupt
16949 + *
16950 + */
16951 +static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
16952 +{
16953 +       gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
16954 +
16955 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
16956 +}
16957 +#endif
16958 +
16959 +/**
16960 + * Starts the ADP Probing
16961 + *
16962 + * @param core_if the pointer to core_if structure.
16963 + */
16964 +uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
16965 +{
16966 +
16967 +       adpctl_data_t adpctl = {.d32 = 0};
16968 +       gpwrdn_data_t gpwrdn;
16969 +#if 0
16970 +       adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
16971 +                                                               .b.adp_sns_int = 1, b.adp_tmout_int};
16972 +#endif
16973 +       dwc_otg_disable_global_interrupts(core_if);
16974 +       DWC_PRINTF("ADP Probe Start\n");
16975 +       core_if->adp.probe_enabled = 1;
16976 +
16977 +       adpctl.b.adpres = 1;
16978 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16979 +
16980 +       while (adpctl.b.adpres) {
16981 +               adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16982 +       }
16983 +
16984 +       adpctl.d32 = 0;
16985 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
16986 +
16987 +       /* In Host mode unmask SRP detected interrupt */
16988 +       gpwrdn.d32 = 0;
16989 +       gpwrdn.b.sts_chngint_msk = 1;
16990 +       if (!gpwrdn.b.idsts) {
16991 +               gpwrdn.b.srp_det_msk = 1;
16992 +       }
16993 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16994 +
16995 +       adpctl.b.adp_tmout_int_msk = 1;
16996 +       adpctl.b.adp_prb_int_msk = 1;
16997 +       adpctl.b.prb_dschg = 1;
16998 +       adpctl.b.prb_delta = 1;
16999 +       adpctl.b.prb_per = 1;
17000 +       adpctl.b.adpen = 1;
17001 +       adpctl.b.enaprb = 1;
17002 +
17003 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17004 +       DWC_PRINTF("ADP Probe Finish\n");
17005 +       return 0;
17006 +}
17007 +
17008 +/**
17009 + * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted 
17010 + * within 3 seconds.
17011 + *
17012 + * @param core_if the pointer to core_if strucure.
17013 + */
17014 +void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
17015 +{
17016 +       core_if->adp.sense_timer_started = 1;
17017 +       DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );
17018 +}
17019 +
17020 +/**
17021 + * Starts the ADP Sense
17022 + *
17023 + * @param core_if the pointer to core_if strucure.
17024 + */
17025 +uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
17026 +{
17027 +       adpctl_data_t adpctl;
17028 +
17029 +       DWC_PRINTF("ADP Sense Start\n");
17030 +
17031 +       /* Unmask ADP sense interrupt and mask all other from the core */
17032 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
17033 +       adpctl.b.adp_sns_int_msk = 1;
17034 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17035 +       dwc_otg_disable_global_interrupts(core_if); // vahrama 
17036 +
17037 +       /* Set ADP reset bit*/
17038 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
17039 +       adpctl.b.adpres = 1;
17040 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17041 +
17042 +       while (adpctl.b.adpres) {
17043 +               adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17044 +       }
17045 +
17046 +       adpctl.b.adpres = 0;
17047 +       adpctl.b.adpen = 1;
17048 +       adpctl.b.enasns = 1;
17049 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17050 +
17051 +       dwc_otg_adp_sense_timer_start(core_if);
17052 +
17053 +       return 0;
17054 +}
17055 +
17056 +/**
17057 + * Stops the ADP Probing
17058 + *
17059 + * @param core_if the pointer to core_if strucure.
17060 + */
17061 +uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
17062 +{
17063 +
17064 +       adpctl_data_t adpctl;
17065 +       DWC_PRINTF("Stop ADP probe\n");
17066 +       core_if->adp.probe_enabled = 0;
17067 +       core_if->adp.probe_counter = 0;
17068 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17069 +
17070 +       adpctl.b.adpen = 0;
17071 +       adpctl.b.adp_prb_int = 1;
17072 +       adpctl.b.adp_tmout_int = 1;
17073 +       adpctl.b.adp_sns_int = 1;
17074 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17075 +
17076 +       return 0;
17077 +}
17078 +
17079 +/**
17080 + * Stops the ADP Sensing
17081 + *
17082 + * @param core_if the pointer to core_if strucure.
17083 + */
17084 +uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
17085 +{
17086 +       adpctl_data_t adpctl;
17087 +
17088 +       core_if->adp.sense_enabled = 0;
17089 +
17090 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
17091 +       adpctl.b.enasns = 0;
17092 +       adpctl.b.adp_sns_int = 1;
17093 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17094 +
17095 +       return 0;
17096 +}
17097 +
17098 +/**
17099 + * Called to turn on the VBUS after initial ADP probe in host mode.
17100 + * If port power was already enabled in cil_hcd_start function then
17101 + * only schedule a timer.
17102 + *
17103 + * @param core_if the pointer to core_if structure.
17104 + */
17105 +void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
17106 +{
17107 +       hprt0_data_t hprt0 = {.d32 = 0 };
17108 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
17109 +       DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
17110 +
17111 +       if (hprt0.b.prtpwr == 0) {
17112 +               hprt0.b.prtpwr = 1;
17113 +               //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
17114 +       }
17115 +       
17116 +       dwc_otg_adp_vbuson_timer_start(core_if);
17117 +}
17118 +
17119 +/**
17120 + * Called right after driver is loaded
17121 + * to perform initial actions for ADP
17122 + *
17123 + * @param core_if the pointer to core_if structure.
17124 + * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
17125 + */
17126 +void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
17127 +{
17128 +       gpwrdn_data_t gpwrdn;
17129 +
17130 +       DWC_PRINTF("ADP Initial Start\n");
17131 +       core_if->adp.adp_started = 1;
17132 +
17133 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
17134 +       dwc_otg_disable_global_interrupts(core_if);
17135 +       if (is_host) {
17136 +               DWC_PRINTF("HOST MODE\n");
17137 +               /* Enable Power Down Logic Interrupt*/
17138 +               gpwrdn.d32 = 0;
17139 +               gpwrdn.b.pmuintsel = 1;
17140 +               gpwrdn.b.pmuactv = 1;
17141 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
17142 +               /* Initialize first ADP probe to obtain Ramp Time value */
17143 +               core_if->adp.initial_probe = 1;
17144 +               dwc_otg_adp_probe_start(core_if);
17145 +       } else {
17146 +               gotgctl_data_t gotgctl;
17147 +               gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17148 +               DWC_PRINTF("DEVICE MODE\n");
17149 +               if (gotgctl.b.bsesvld == 0) {
17150 +                       /* Enable Power Down Logic Interrupt*/
17151 +                       gpwrdn.d32 = 0;
17152 +                       DWC_PRINTF("VBUS is not valid - start ADP probe\n");
17153 +                       gpwrdn.b.pmuintsel = 1;
17154 +                       gpwrdn.b.pmuactv = 1;
17155 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
17156 +                       core_if->adp.initial_probe = 1;
17157 +                       dwc_otg_adp_probe_start(core_if);
17158 +               } else {
17159 +                       DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
17160 +                       core_if->op_state = B_PERIPHERAL;
17161 +                       dwc_otg_core_init(core_if);
17162 +                       dwc_otg_enable_global_interrupts(core_if);
17163 +                       cil_pcd_start(core_if);
17164 +                       dwc_otg_dump_global_registers(core_if);
17165 +                       dwc_otg_dump_dev_registers(core_if);
17166 +               }
17167 +       }
17168 +}
17169 +
17170 +void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
17171 +{
17172 +       core_if->adp.adp_started = 0;
17173 +       core_if->adp.initial_probe = 0;
17174 +       core_if->adp.probe_timer_values[0] = -1;
17175 +       core_if->adp.probe_timer_values[1] = -1;
17176 +       core_if->adp.probe_enabled = 0;
17177 +       core_if->adp.sense_enabled = 0;
17178 +       core_if->adp.sense_timer_started = 0;
17179 +       core_if->adp.vbuson_timer_started = 0;
17180 +       core_if->adp.probe_counter = 0;
17181 +       core_if->adp.gpwrdn = 0;
17182 +       core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
17183 +       /* Initialize timers */
17184 +       core_if->adp.sense_timer =
17185 +           DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
17186 +       core_if->adp.vbuson_timer =
17187 +           DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
17188 +       if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
17189 +       {
17190 +               DWC_ERROR("Could not allocate memory for ADP timers\n");
17191 +       }
17192 +}
17193 +
17194 +void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
17195 +{
17196 +       gpwrdn_data_t gpwrdn = { .d32 = 0 };
17197 +       gpwrdn.b.pmuintsel = 1;
17198 +       gpwrdn.b.pmuactv = 1;
17199 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17200 +
17201 +       if (core_if->adp.probe_enabled)         
17202 +               dwc_otg_adp_probe_stop(core_if);
17203 +       if (core_if->adp.sense_enabled)         
17204 +               dwc_otg_adp_sense_stop(core_if);
17205 +       if (core_if->adp.sense_timer_started)           
17206 +               DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17207 +       if (core_if->adp.vbuson_timer_started)          
17208 +               DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
17209 +       DWC_TIMER_FREE(core_if->adp.sense_timer);
17210 +       DWC_TIMER_FREE(core_if->adp.vbuson_timer);
17211 +}
17212 +
17213 +/////////////////////////////////////////////////////////////////////
17214 +////////////// ADP Interrupt Handlers ///////////////////////////////
17215 +/////////////////////////////////////////////////////////////////////
17216 +/**
17217 + * This function sets Ramp Timer values
17218 + */
17219 +static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
17220 +{
17221 +       if (core_if->adp.probe_timer_values[0] == -1) {
17222 +               core_if->adp.probe_timer_values[0] = val;
17223 +               core_if->adp.probe_timer_values[1] = -1;
17224 +               return 1;
17225 +       } else {
17226 +               core_if->adp.probe_timer_values[1] =
17227 +                   core_if->adp.probe_timer_values[0];
17228 +               core_if->adp.probe_timer_values[0] = val;
17229 +               return 0;
17230 +       }
17231 +}
17232 +
17233 +/**
17234 + * This function compares Ramp Timer values
17235 + */
17236 +static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
17237 +{
17238 +       uint32_t diff;
17239 +       if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
17240 +                       diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
17241 +       else
17242 +                       diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];           
17243 +       if(diff < 2) {
17244 +               return 0;
17245 +       } else {
17246 +               return 1;
17247 +       }
17248 +}
17249 +
17250 +/**
17251 + * This function handles ADP Probe Interrupts
17252 + */
17253 +static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
17254 +                                                uint32_t val)
17255 +{
17256 +       adpctl_data_t adpctl = {.d32 = 0 };
17257 +       gpwrdn_data_t gpwrdn, temp;
17258 +       adpctl.d32 = val;
17259 +
17260 +       temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17261 +       core_if->adp.probe_counter++;
17262 +       core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17263 +       if (adpctl.b.rtim == 0 && !temp.b.idsts){
17264 +               DWC_PRINTF("RTIM value is 0\n");        
17265 +               goto exit;
17266 +       }
17267 +       if (set_timer_value(core_if, adpctl.b.rtim) &&
17268 +           core_if->adp.initial_probe) {
17269 +               core_if->adp.initial_probe = 0;
17270 +               dwc_otg_adp_probe_stop(core_if);
17271 +               gpwrdn.d32 = 0;
17272 +               gpwrdn.b.pmuactv = 1;
17273 +               gpwrdn.b.pmuintsel = 1;
17274 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17275 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
17276 +
17277 +               /* check which value is for device mode and which for Host mode */
17278 +               if (!temp.b.idsts) {    /* considered host mode value is 0 */
17279 +                       /*
17280 +                        * Turn on VBUS after initial ADP probe.
17281 +                        */
17282 +                       core_if->op_state = A_HOST;
17283 +                       dwc_otg_enable_global_interrupts(core_if);
17284 +                       DWC_SPINUNLOCK(core_if->lock);
17285 +                       cil_hcd_start(core_if);
17286 +                       dwc_otg_adp_turnon_vbus(core_if);
17287 +                       DWC_SPINLOCK(core_if->lock);
17288 +               } else {
17289 +                       /*
17290 +                        * Initiate SRP after initial ADP probe.
17291 +                        */
17292 +                       dwc_otg_enable_global_interrupts(core_if);
17293 +                       dwc_otg_initiate_srp(core_if);
17294 +               }
17295 +       } else if (core_if->adp.probe_counter > 2){
17296 +               gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17297 +               if (compare_timer_values(core_if)) {
17298 +                       DWC_PRINTF("Difference in timer values !!! \n");
17299 +//                      core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
17300 +                       dwc_otg_adp_probe_stop(core_if);
17301 +
17302 +                       /* Power on the core */
17303 +                       if (core_if->power_down == 2) {
17304 +                               gpwrdn.b.pwrdnswtch = 1;
17305 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17306 +                                                gpwrdn, 0, gpwrdn.d32);
17307 +                       }
17308 +
17309 +                       /* check which value is for device mode and which for Host mode */
17310 +                       if (!temp.b.idsts) {    /* considered host mode value is 0 */
17311 +                               /* Disable Interrupt from Power Down Logic */
17312 +                               gpwrdn.d32 = 0;
17313 +                               gpwrdn.b.pmuintsel = 1;
17314 +                               gpwrdn.b.pmuactv = 1;
17315 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17316 +                                                gpwrdn, gpwrdn.d32, 0);
17317 +
17318 +                               /*
17319 +                                * Initialize the Core for Host mode.
17320 +                                */
17321 +                               core_if->op_state = A_HOST;
17322 +                               dwc_otg_core_init(core_if);
17323 +                               dwc_otg_enable_global_interrupts(core_if);
17324 +                               cil_hcd_start(core_if);
17325 +                       } else {
17326 +                               gotgctl_data_t gotgctl;
17327 +                               /* Mask SRP detected interrupt from Power Down Logic */
17328 +                               gpwrdn.d32 = 0;
17329 +                               gpwrdn.b.srp_det_msk = 1;
17330 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17331 +                                                gpwrdn, gpwrdn.d32, 0);
17332 +
17333 +                               /* Disable Power Down Logic */
17334 +                               gpwrdn.d32 = 0;
17335 +                               gpwrdn.b.pmuintsel = 1;
17336 +                               gpwrdn.b.pmuactv = 1;
17337 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17338 +                                                gpwrdn, gpwrdn.d32, 0);
17339 +
17340 +                               /*
17341 +                                * Initialize the Core for Device mode.
17342 +                                */
17343 +                               core_if->op_state = B_PERIPHERAL;
17344 +                               dwc_otg_core_init(core_if);
17345 +                               dwc_otg_enable_global_interrupts(core_if);
17346 +                               cil_pcd_start(core_if);
17347 +
17348 +                               gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17349 +                               if (!gotgctl.b.bsesvld) {
17350 +                                       dwc_otg_initiate_srp(core_if);
17351 +                               }
17352 +                       }
17353 +               }
17354 +               if (core_if->power_down == 2) {
17355 +                       if (gpwrdn.b.bsessvld) {
17356 +                               /* Mask SRP detected interrupt from Power Down Logic */
17357 +                               gpwrdn.d32 = 0;
17358 +                               gpwrdn.b.srp_det_msk = 1;
17359 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17360 +                               
17361 +                               /* Disable Power Down Logic */
17362 +                               gpwrdn.d32 = 0;
17363 +                               gpwrdn.b.pmuactv = 1;
17364 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17365 +
17366 +                               /*
17367 +                                * Initialize the Core for Device mode.
17368 +                                */
17369 +                               core_if->op_state = B_PERIPHERAL;
17370 +                               dwc_otg_core_init(core_if);
17371 +                               dwc_otg_enable_global_interrupts(core_if);
17372 +                               cil_pcd_start(core_if);
17373 +                       }
17374 +               }
17375 +       }
17376 +exit:
17377 +       /* Clear interrupt */
17378 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17379 +       adpctl.b.adp_prb_int = 1;
17380 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17381 +
17382 +       return 0;
17383 +}
17384 +
17385 +/**
17386 + * This function hadles ADP Sense Interrupt
17387 + */
17388 +static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
17389 +{
17390 +       adpctl_data_t adpctl;
17391 +       /* Stop ADP Sense timer */
17392 +       DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17393 +
17394 +       /* Restart ADP Sense timer */
17395 +       dwc_otg_adp_sense_timer_start(core_if);
17396 +       
17397 +       /* Clear interrupt */
17398 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17399 +       adpctl.b.adp_sns_int = 1;
17400 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17401 +
17402 +       return 0;
17403 +}
17404 +
17405 +/**
17406 + * This function handles ADP Probe Interrupts
17407 + */
17408 +static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
17409 +                                                uint32_t val)
17410 +{
17411 +       adpctl_data_t adpctl = {.d32 = 0 };
17412 +       adpctl.d32 = val;
17413 +       set_timer_value(core_if, adpctl.b.rtim);
17414 +       
17415 +       /* Clear interrupt */
17416 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17417 +       adpctl.b.adp_tmout_int = 1;
17418 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17419 +
17420 +       return 0;
17421 +}
17422 +
17423 +/**
17424 + * ADP Interrupt handler.
17425 + *
17426 + */
17427 +int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
17428 +{
17429 +       int retval = 0;
17430 +       adpctl_data_t adpctl = {.d32 = 0};
17431 +
17432 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17433 +       DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
17434 +
17435 +       if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
17436 +               DWC_PRINTF("ADP Sense interrupt\n");
17437 +               retval |= dwc_otg_adp_handle_sns_intr(core_if);
17438 +       }
17439 +       if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
17440 +               DWC_PRINTF("ADP timeout interrupt\n");
17441 +               retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
17442 +       }
17443 +       if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
17444 +               DWC_PRINTF("ADP Probe interrupt\n");
17445 +               adpctl.b.adp_prb_int = 1;       
17446 +               retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
17447 +       }
17448 +
17449 +//     dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
17450 +       //dwc_otg_adp_write_reg(core_if, adpctl.d32);
17451 +       DWC_PRINTF("RETURN FROM ADP ISR\n");
17452 +
17453 +       return retval;
17454 +}
17455 +
17456 +/**
17457 + *
17458 + * @param core_if Programming view of DWC_otg controller.
17459 + */
17460 +int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
17461 +{
17462 +
17463 +#ifndef DWC_HOST_ONLY
17464 +       hprt0_data_t hprt0;
17465 +       gpwrdn_data_t gpwrdn;
17466 +       DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
17467 +
17468 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17469 +       /* check which value is for device mode and which for Host mode */
17470 +       if (!gpwrdn.b.idsts) {  /* considered host mode value is 0 */
17471 +               DWC_PRINTF("SRP: Host mode\n");
17472 +
17473 +               if (core_if->adp_enable) {
17474 +                       dwc_otg_adp_probe_stop(core_if);
17475 +
17476 +                       /* Power on the core */
17477 +                       if (core_if->power_down == 2) {
17478 +                               gpwrdn.b.pwrdnswtch = 1;
17479 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17480 +                                                gpwrdn, 0, gpwrdn.d32);
17481 +                       }
17482 +
17483 +                       core_if->op_state = A_HOST;
17484 +                       dwc_otg_core_init(core_if);
17485 +                       dwc_otg_enable_global_interrupts(core_if);
17486 +                       cil_hcd_start(core_if);
17487 +               }
17488 +
17489 +               /* Turn on the port power bit. */
17490 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
17491 +               hprt0.b.prtpwr = 1;
17492 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
17493 +
17494 +               /* Start the Connection timer. So a message can be displayed
17495 +                * if connect does not occur within 10 seconds. */
17496 +               cil_hcd_session_start(core_if);
17497 +       } else {
17498 +               DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
17499 +               if (core_if->adp_enable) {
17500 +                       dwc_otg_adp_probe_stop(core_if);
17501 +
17502 +                       /* Power on the core */
17503 +                       if (core_if->power_down == 2) {
17504 +                               gpwrdn.b.pwrdnswtch = 1;
17505 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17506 +                                                gpwrdn, 0, gpwrdn.d32);
17507 +                       }
17508 +
17509 +                       gpwrdn.d32 = 0;
17510 +                       gpwrdn.b.pmuactv = 0;
17511 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
17512 +                                        gpwrdn.d32);
17513 +
17514 +                       core_if->op_state = B_PERIPHERAL;
17515 +                       dwc_otg_core_init(core_if);
17516 +                       dwc_otg_enable_global_interrupts(core_if);
17517 +                       cil_pcd_start(core_if);
17518 +               }
17519 +       }
17520 +#endif
17521 +       return 1;
17522 +}
17523 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.h b/drivers/usb/host/dwc_otg/dwc_otg_adp.h
17524 new file mode 100644
17525 index 0000000..d8c3f85
17526 --- /dev/null
17527 +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.h
17528 @@ -0,0 +1,80 @@
17529 +/* ==========================================================================
17530 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
17531 + * $Revision: #7 $
17532 + * $Date: 2011/10/24 $
17533 + * $Change: 1871159 $
17534 + *
17535 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17536 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17537 + * otherwise expressly agreed to in writing between Synopsys and you.
17538 + *
17539 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17540 + * any End User Software License Agreement or Agreement for Licensed Product
17541 + * with Synopsys or any supplement thereto. You are permitted to use and
17542 + * redistribute this Software in source and binary forms, with or without
17543 + * modification, provided that redistributions of source code must retain this
17544 + * notice. You may not view, use, disclose, copy or distribute this file or
17545 + * any information contained herein except pursuant to this license grant from
17546 + * Synopsys. If you do not agree with this notice, including the disclaimer
17547 + * below, then you are not authorized to use the Software.
17548 + *
17549 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17550 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17551 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17552 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17553 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17554 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17555 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17556 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17557 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17558 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17559 + * DAMAGE.
17560 + * ========================================================================== */
17561 +
17562 +#ifndef __DWC_OTG_ADP_H__
17563 +#define __DWC_OTG_ADP_H__
17564 +
17565 +/**
17566 + * @file
17567 + *
17568 + * This file contains the Attach Detect Protocol interfaces and defines
17569 + * (functions) and structures for Linux.
17570 + *
17571 + */
17572 +
17573 +#define DWC_OTG_ADP_UNATTACHED 0
17574 +#define DWC_OTG_ADP_ATTACHED   1
17575 +#define DWC_OTG_ADP_UNKOWN     2
17576 +
17577 +typedef struct dwc_otg_adp {
17578 +       uint32_t adp_started;   
17579 +       uint32_t initial_probe;
17580 +       int32_t probe_timer_values[2];
17581 +       uint32_t probe_enabled;
17582 +       uint32_t sense_enabled;
17583 +       dwc_timer_t *sense_timer;
17584 +       uint32_t sense_timer_started;
17585 +       dwc_timer_t *vbuson_timer;
17586 +       uint32_t vbuson_timer_started;
17587 +       uint32_t attached;
17588 +       uint32_t probe_counter;
17589 +       uint32_t gpwrdn;
17590 +} dwc_otg_adp_t;
17591 +
17592 +/**
17593 + * Attach Detect Protocol functions
17594 + */
17595 +
17596 +extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value);
17597 +extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if);
17598 +extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if);
17599 +extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if);
17600 +extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if);
17601 +extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if);
17602 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
17603 +extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if);
17604 +extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if);
17605 +extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if);
17606 +extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if);
17607 +
17608 +#endif //__DWC_OTG_ADP_H__
17609 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
17610 new file mode 100644
17611 index 0000000..95eb7f8
17612 --- /dev/null
17613 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
17614 @@ -0,0 +1,1210 @@
17615 +/* ==========================================================================
17616 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
17617 + * $Revision: #44 $
17618 + * $Date: 2010/11/29 $
17619 + * $Change: 1636033 $
17620 + *
17621 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17622 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17623 + * otherwise expressly agreed to in writing between Synopsys and you.
17624 + *
17625 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17626 + * any End User Software License Agreement or Agreement for Licensed Product
17627 + * with Synopsys or any supplement thereto. You are permitted to use and
17628 + * redistribute this Software in source and binary forms, with or without
17629 + * modification, provided that redistributions of source code must retain this
17630 + * notice. You may not view, use, disclose, copy or distribute this file or
17631 + * any information contained herein except pursuant to this license grant from
17632 + * Synopsys. If you do not agree with this notice, including the disclaimer
17633 + * below, then you are not authorized to use the Software.
17634 + *
17635 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17636 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17637 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17638 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17639 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17640 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17641 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17642 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17643 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17644 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17645 + * DAMAGE.
17646 + * ========================================================================== */
17647 +
17648 +/** @file
17649 + *
17650 + * The diagnostic interface will provide access to the controller for
17651 + * bringing up the hardware and testing.  The Linux driver attributes
17652 + * feature will be used to provide the Linux Diagnostic
17653 + * Interface. These attributes are accessed through sysfs.
17654 + */
17655 +
17656 +/** @page "Linux Module Attributes"
17657 + *
17658 + * The Linux module attributes feature is used to provide the Linux
17659 + * Diagnostic Interface.  These attributes are accessed through sysfs.
17660 + * The diagnostic interface will provide access to the controller for
17661 + * bringing up the hardware and testing.
17662 +
17663 + The following table shows the attributes.
17664 + <table>
17665 + <tr>
17666 + <td><b> Name</b></td>
17667 + <td><b> Description</b></td>
17668 + <td><b> Access</b></td>
17669 + </tr>
17670 +
17671 + <tr>
17672 + <td> mode </td>
17673 + <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
17674 + <td> Read</td>
17675 + </tr>
17676 +
17677 + <tr>
17678 + <td> hnpcapable </td>
17679 + <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
17680 + Read returns the current value.</td>
17681 + <td> Read/Write</td>
17682 + </tr>
17683 +
17684 + <tr>
17685 + <td> srpcapable </td>
17686 + <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
17687 + Read returns the current value.</td>
17688 + <td> Read/Write</td>
17689 + </tr>
17690 +
17691 + <tr>
17692 + <td> hsic_connect </td>
17693 + <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register.
17694 + Read returns the current value.</td>
17695 + <td> Read/Write</td>
17696 + </tr>
17697 +
17698 + <tr>
17699 + <td> inv_sel_hsic </td>
17700 + <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register.
17701 + Read returns the current value.</td>
17702 + <td> Read/Write</td>
17703 + </tr>
17704 +
17705 + <tr>
17706 + <td> hnp </td>
17707 + <td> Initiates the Host Negotiation Protocol.  Read returns the status.</td>
17708 + <td> Read/Write</td>
17709 + </tr>
17710 +
17711 + <tr>
17712 + <td> srp </td>
17713 + <td> Initiates the Session Request Protocol.  Read returns the status.</td>
17714 + <td> Read/Write</td>
17715 + </tr>
17716 +
17717 + <tr>
17718 + <td> buspower </td>
17719 + <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
17720 + <td> Read/Write</td>
17721 + </tr>
17722 +
17723 + <tr>
17724 + <td> bussuspend </td>
17725 + <td> Suspends the USB bus.</td>
17726 + <td> Read/Write</td>
17727 + </tr>
17728 +
17729 + <tr>
17730 + <td> busconnected </td>
17731 + <td> Gets the connection status of the bus</td>
17732 + <td> Read</td>
17733 + </tr>
17734 +
17735 + <tr>
17736 + <td> gotgctl </td>
17737 + <td> Gets or sets the Core Control Status Register.</td>
17738 + <td> Read/Write</td>
17739 + </tr>
17740 +
17741 + <tr>
17742 + <td> gusbcfg </td>
17743 + <td> Gets or sets the Core USB Configuration Register</td>
17744 + <td> Read/Write</td>
17745 + </tr>
17746 +
17747 + <tr>
17748 + <td> grxfsiz </td>
17749 + <td> Gets or sets the Receive FIFO Size Register</td>
17750 + <td> Read/Write</td>
17751 + </tr>
17752 +
17753 + <tr>
17754 + <td> gnptxfsiz </td>
17755 + <td> Gets or sets the non-periodic Transmit Size Register</td>
17756 + <td> Read/Write</td>
17757 + </tr>
17758 +
17759 + <tr>
17760 + <td> gpvndctl </td>
17761 + <td> Gets or sets the PHY Vendor Control Register</td>
17762 + <td> Read/Write</td>
17763 + </tr>
17764 +
17765 + <tr>
17766 + <td> ggpio </td>
17767 + <td> Gets the value in the lower 16-bits of the General Purpose IO Register
17768 + or sets the upper 16 bits.</td>
17769 + <td> Read/Write</td>
17770 + </tr>
17771 +
17772 + <tr>
17773 + <td> guid </td>
17774 + <td> Gets or sets the value of the User ID Register</td>
17775 + <td> Read/Write</td>
17776 + </tr>
17777 +
17778 + <tr>
17779 + <td> gsnpsid </td>
17780 + <td> Gets the value of the Synopsys ID Regester</td>
17781 + <td> Read</td>
17782 + </tr>
17783 +
17784 + <tr>
17785 + <td> devspeed </td>
17786 + <td> Gets or sets the device speed setting in the DCFG register</td>
17787 + <td> Read/Write</td>
17788 + </tr>
17789 +
17790 + <tr>
17791 + <td> enumspeed </td>
17792 + <td> Gets the device enumeration Speed.</td>
17793 + <td> Read</td>
17794 + </tr>
17795 +
17796 + <tr>
17797 + <td> hptxfsiz </td>
17798 + <td> Gets the value of the Host Periodic Transmit FIFO</td>
17799 + <td> Read</td>
17800 + </tr>
17801 +
17802 + <tr>
17803 + <td> hprt0 </td>
17804 + <td> Gets or sets the value in the Host Port Control and Status Register</td>
17805 + <td> Read/Write</td>
17806 + </tr>
17807 +
17808 + <tr>
17809 + <td> regoffset </td>
17810 + <td> Sets the register offset for the next Register Access</td>
17811 + <td> Read/Write</td>
17812 + </tr>
17813 +
17814 + <tr>
17815 + <td> regvalue </td>
17816 + <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
17817 + <td> Read/Write</td>
17818 + </tr>
17819 +
17820 + <tr>
17821 + <td> remote_wakeup </td>
17822 + <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
17823 + wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
17824 + Wakeup signalling bit in the Device Control Register is set for 1
17825 + milli-second.</td>
17826 + <td> Read/Write</td>
17827 + </tr>
17828 +
17829 + <tr>
17830 + <td> rem_wakeup_pwrdn </td>
17831 + <td> On read, shows the status core - hibernated or not. On write, initiates 
17832 + a remote wakeup of the device from Hibernation. </td>
17833 + <td> Read/Write</td>
17834 + </tr>
17835 +
17836 + <tr>
17837 + <td> mode_ch_tim_en </td>
17838 + <td> This bit is used to enable or disable the host core to wait for 200 PHY 
17839 + clock cycles at the end of Resume to change the opmode signal to the PHY to 00
17840 + after Suspend or LPM. </td>
17841 + <td> Read/Write</td>
17842 + </tr>
17843
17844 + <tr>
17845 + <td> fr_interval </td>
17846 + <td> On read, shows the value of HFIR Frame Interval. On write, dynamically 
17847 + reload HFIR register during runtime. The application can write a value to this
17848 + register only after the Port Enable bit of the Host Port Control and Status 
17849 + register (HPRT.PrtEnaPort) has been set </td>
17850 + <td> Read/Write</td>
17851 + </tr>
17852
17853 + <tr>
17854 + <td> disconnect_us </td>
17855 + <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us
17856 + which causes soft disconnect for 100us. Applicable only for device mode of operation.</td>
17857 + <td> Read/Write</td>
17858 + </tr>
17859 +
17860 + <tr>
17861 + <td> regdump </td>
17862 + <td> Dumps the contents of core registers.</td>
17863 + <td> Read</td>
17864 + </tr>
17865 +
17866 + <tr>
17867 + <td> spramdump </td>
17868 + <td> Dumps the contents of core registers.</td>
17869 + <td> Read</td>
17870 + </tr>
17871 +
17872 + <tr>
17873 + <td> hcddump </td>
17874 + <td> Dumps the current HCD state.</td>
17875 + <td> Read</td>
17876 + </tr>
17877 +
17878 + <tr>
17879 + <td> hcd_frrem </td>
17880 + <td> Shows the average value of the Frame Remaining
17881 + field in the Host Frame Number/Frame Remaining register when an SOF interrupt
17882 + occurs. This can be used to determine the average interrupt latency. Also
17883 + shows the average Frame Remaining value for start_transfer and the "a" and
17884 + "b" sample points. The "a" and "b" sample points may be used during debugging
17885 + bto determine how long it takes to execute a section of the HCD code.</td>
17886 + <td> Read</td>
17887 + </tr>
17888 +
17889 + <tr>
17890 + <td> rd_reg_test </td>
17891 + <td> Displays the time required to read the GNPTXFSIZ register many times
17892 + (the output shows the number of times the register is read).
17893 + <td> Read</td>
17894 + </tr>
17895 +
17896 + <tr>
17897 + <td> wr_reg_test </td>
17898 + <td> Displays the time required to write the GNPTXFSIZ register many times
17899 + (the output shows the number of times the register is written).
17900 + <td> Read</td>
17901 + </tr>
17902 +
17903 + <tr>
17904 + <td> lpm_response </td>
17905 + <td> Gets or sets lpm_response mode. Applicable only in device mode.
17906 + <td> Write</td>
17907 + </tr>
17908 +
17909 + <tr>
17910 + <td> sleep_status </td>
17911 + <td> Shows sleep status of device.
17912 + <td> Read</td>
17913 + </tr>
17914 +
17915 + </table>
17916 +
17917 + Example usage:
17918 + To get the current mode:
17919 + cat /sys/devices/lm0/mode
17920 +
17921 + To power down the USB:
17922 + echo 0 > /sys/devices/lm0/buspower
17923 + */
17924 +
17925 +#include "dwc_otg_os_dep.h"
17926 +#include "dwc_os.h"
17927 +#include "dwc_otg_driver.h"
17928 +#include "dwc_otg_attr.h"
17929 +#include "dwc_otg_core_if.h"
17930 +#include "dwc_otg_pcd_if.h"
17931 +#include "dwc_otg_hcd_if.h"
17932 +
17933 +/*
17934 + * MACROs for defining sysfs attribute
17935 + */
17936 +#ifdef LM_INTERFACE
17937 +
17938 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17939 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17940 +{ \
17941 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17942 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);             \
17943 +       uint32_t val; \
17944 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17945 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17946 +}
17947 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17948 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17949 +                                       const char *buf, size_t count) \
17950 +{ \
17951 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17952 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17953 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17954 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17955 +       return count; \
17956 +}
17957 +
17958 +#elif defined(PCI_INTERFACE)
17959 +
17960 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17961 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17962 +{ \
17963 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);      \
17964 +       uint32_t val; \
17965 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17966 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17967 +}
17968 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17969 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17970 +                                       const char *buf, size_t count) \
17971 +{ \
17972 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17973 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17974 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17975 +       return count; \
17976 +}
17977 +
17978 +#elif defined(PLATFORM_INTERFACE)
17979 +
17980 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17981 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17982 +{ \
17983 +        struct platform_device *platform_dev = \
17984 +                container_of(_dev, struct platform_device, dev); \
17985 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);  \
17986 +       uint32_t val; \
17987 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
17988 +                    __func__, _dev, platform_dev, otg_dev); \
17989 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17990 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17991 +}
17992 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17993 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17994 +                                       const char *buf, size_t count) \
17995 +{ \
17996 +        struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17997 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17998 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17999 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
18000 +       return count; \
18001 +}
18002 +#endif
18003 +
18004 +/*
18005 + * MACROs for defining sysfs attribute for 32-bit registers
18006 + */
18007 +#ifdef LM_INTERFACE
18008 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
18009 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
18010 +{ \
18011 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
18012 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
18013 +       uint32_t val; \
18014 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
18015 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
18016 +}
18017 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
18018 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
18019 +                                       const char *buf, size_t count) \
18020 +{ \
18021 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
18022 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
18023 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
18024 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
18025 +       return count; \
18026 +}
18027 +#elif defined(PCI_INTERFACE)
18028 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
18029 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
18030 +{ \
18031 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
18032 +       uint32_t val; \
18033 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
18034 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
18035 +}
18036 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
18037 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
18038 +                                       const char *buf, size_t count) \
18039 +{ \
18040 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
18041 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
18042 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
18043 +       return count; \
18044 +}
18045 +
18046 +#elif defined(PLATFORM_INTERFACE)
18047 +#include "dwc_otg_dbg.h"
18048 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
18049 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
18050 +{ \
18051 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
18052 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
18053 +       uint32_t val; \
18054 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
18055 +                    __func__, _dev, platform_dev, otg_dev); \
18056 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
18057 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
18058 +}
18059 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
18060 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
18061 +                                       const char *buf, size_t count) \
18062 +{ \
18063 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
18064 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
18065 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
18066 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
18067 +       return count; \
18068 +}
18069 +
18070 +#endif
18071 +
18072 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \
18073 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
18074 +DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
18075 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
18076 +
18077 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \
18078 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
18079 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
18080 +
18081 +#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
18082 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
18083 +DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
18084 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
18085 +
18086 +#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
18087 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
18088 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
18089 +
18090 +/** @name Functions for Show/Store of Attributes */
18091 +/**@{*/
18092 +
18093 +/**
18094 + * Helper function returning the otg_device structure of the given device
18095 + */
18096 +static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
18097 +{
18098 +        dwc_otg_device_t *otg_dev;
18099 +        DWC_OTG_GETDRVDEV(otg_dev, _dev);
18100 +        return otg_dev;
18101 +}
18102 +
18103 +/**
18104 + * Show the register offset of the Register Access.
18105 + */
18106 +static ssize_t regoffset_show(struct device *_dev,
18107 +                             struct device_attribute *attr, char *buf)
18108 +{
18109 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18110 +       return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",
18111 +                       otg_dev->os_dep.reg_offset);
18112 +}
18113 +
18114 +/**
18115 + * Set the register offset for the next Register Access        Read/Write
18116 + */
18117 +static ssize_t regoffset_store(struct device *_dev,
18118 +                              struct device_attribute *attr,
18119 +                              const char *buf, size_t count)
18120 +{
18121 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18122 +       uint32_t offset = simple_strtoul(buf, NULL, 16);
18123 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
18124 +       if (offset < SZ_256K) {
18125 +#elif  defined(PCI_INTERFACE)
18126 +       if (offset < 0x00040000) {
18127 +#endif
18128 +               otg_dev->os_dep.reg_offset = offset;
18129 +       } else {
18130 +               dev_err(_dev, "invalid offset\n");
18131 +       }
18132 +
18133 +       return count;
18134 +}
18135 +
18136 +DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store);
18137 +
18138 +/**
18139 + * Show the value of the register at the offset in the reg_offset
18140 + * attribute.
18141 + */
18142 +static ssize_t regvalue_show(struct device *_dev,
18143 +                            struct device_attribute *attr, char *buf)
18144 +{
18145 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18146 +       uint32_t val;
18147 +       volatile uint32_t *addr;
18148 +
18149 +       if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
18150 +               /* Calculate the address */
18151 +               addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
18152 +                                    (uint8_t *) otg_dev->os_dep.base);
18153 +               val = DWC_READ_REG32(addr);
18154 +               return snprintf(buf,
18155 +                               sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1,
18156 +                               "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset,
18157 +                               val);
18158 +       } else {
18159 +               dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset);
18160 +               return sprintf(buf, "invalid offset\n");
18161 +       }
18162 +}
18163 +
18164 +/**
18165 + * Store the value in the register at the offset in the reg_offset
18166 + * attribute.
18167 + *
18168 + */
18169 +static ssize_t regvalue_store(struct device *_dev,
18170 +                             struct device_attribute *attr,
18171 +                             const char *buf, size_t count)
18172 +{
18173 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18174 +       volatile uint32_t *addr;
18175 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18176 +       //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
18177 +       if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
18178 +               /* Calculate the address */
18179 +               addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
18180 +                                    (uint8_t *) otg_dev->os_dep.base);
18181 +               DWC_WRITE_REG32(addr, val);
18182 +       } else {
18183 +               dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
18184 +                       otg_dev->os_dep.reg_offset);
18185 +       }
18186 +       return count;
18187 +}
18188 +
18189 +DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store);
18190 +
18191 +/*
18192 + * Attributes
18193 + */
18194 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode");
18195 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable");
18196 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable");
18197 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect");
18198 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC");
18199 +
18200 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
18201 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
18202 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected");
18203 +
18204 +DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL");
18205 +DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,
18206 +                            &(otg_dev->core_if->core_global_regs->gusbcfg),
18207 +                            "GUSBCFG");
18208 +DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,
18209 +                            &(otg_dev->core_if->core_global_regs->grxfsiz),
18210 +                            "GRXFSIZ");
18211 +DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,
18212 +                            &(otg_dev->core_if->core_global_regs->gnptxfsiz),
18213 +                            "GNPTXFSIZ");
18214 +DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,
18215 +                            &(otg_dev->core_if->core_global_regs->gpvndctl),
18216 +                            "GPVNDCTL");
18217 +DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,
18218 +                            &(otg_dev->core_if->core_global_regs->ggpio),
18219 +                            "GGPIO");
18220 +DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid),
18221 +                            "GUID");
18222 +DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,
18223 +                            &(otg_dev->core_if->core_global_regs->gsnpsid),
18224 +                            "GSNPSID");
18225 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed");
18226 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed");
18227 +
18228 +DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,
18229 +                            &(otg_dev->core_if->core_global_regs->hptxfsiz),
18230 +                            "HPTXFSIZ");
18231 +DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0");
18232 +
18233 +/**
18234 + * @todo Add code to initiate the HNP.
18235 + */
18236 +/**
18237 + * Show the HNP status bit
18238 + */
18239 +static ssize_t hnp_show(struct device *_dev,
18240 +                       struct device_attribute *attr, char *buf)
18241 +{
18242 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18243 +       return sprintf(buf, "HstNegScs = 0x%x\n",
18244 +                      dwc_otg_get_hnpstatus(otg_dev->core_if));
18245 +}
18246 +
18247 +/**
18248 + * Set the HNP Request bit
18249 + */
18250 +static ssize_t hnp_store(struct device *_dev,
18251 +                        struct device_attribute *attr,
18252 +                        const char *buf, size_t count)
18253 +{
18254 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18255 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18256 +       dwc_otg_set_hnpreq(otg_dev->core_if, in);
18257 +       return count;
18258 +}
18259 +
18260 +DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
18261 +
18262 +/**
18263 + * @todo Add code to initiate the SRP.
18264 + */
18265 +/**
18266 + * Show the SRP status bit
18267 + */
18268 +static ssize_t srp_show(struct device *_dev,
18269 +                       struct device_attribute *attr, char *buf)
18270 +{
18271 +#ifndef DWC_HOST_ONLY
18272 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18273 +       return sprintf(buf, "SesReqScs = 0x%x\n",
18274 +                      dwc_otg_get_srpstatus(otg_dev->core_if));
18275 +#else
18276 +       return sprintf(buf, "Host Only Mode!\n");
18277 +#endif
18278 +}
18279 +
18280 +/**
18281 + * Set the SRP Request bit
18282 + */
18283 +static ssize_t srp_store(struct device *_dev,
18284 +                        struct device_attribute *attr,
18285 +                        const char *buf, size_t count)
18286 +{
18287 +#ifndef DWC_HOST_ONLY
18288 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18289 +       dwc_otg_pcd_initiate_srp(otg_dev->pcd);
18290 +#endif
18291 +       return count;
18292 +}
18293 +
18294 +DEVICE_ATTR(srp, 0644, srp_show, srp_store);
18295 +
18296 +/**
18297 + * @todo Need to do more for power on/off?
18298 + */
18299 +/**
18300 + * Show the Bus Power status
18301 + */
18302 +static ssize_t buspower_show(struct device *_dev,
18303 +                            struct device_attribute *attr, char *buf)
18304 +{
18305 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18306 +       return sprintf(buf, "Bus Power = 0x%x\n",
18307 +                      dwc_otg_get_prtpower(otg_dev->core_if));
18308 +}
18309 +
18310 +/**
18311 + * Set the Bus Power status
18312 + */
18313 +static ssize_t buspower_store(struct device *_dev,
18314 +                             struct device_attribute *attr,
18315 +                             const char *buf, size_t count)
18316 +{
18317 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18318 +       uint32_t on = simple_strtoul(buf, NULL, 16);
18319 +       dwc_otg_set_prtpower(otg_dev->core_if, on);
18320 +       return count;
18321 +}
18322 +
18323 +DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
18324 +
18325 +/**
18326 + * @todo Need to do more for suspend?
18327 + */
18328 +/**
18329 + * Show the Bus Suspend status
18330 + */
18331 +static ssize_t bussuspend_show(struct device *_dev,
18332 +                              struct device_attribute *attr, char *buf)
18333 +{
18334 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18335 +       return sprintf(buf, "Bus Suspend = 0x%x\n",
18336 +                      dwc_otg_get_prtsuspend(otg_dev->core_if));
18337 +}
18338 +
18339 +/**
18340 + * Set the Bus Suspend status
18341 + */
18342 +static ssize_t bussuspend_store(struct device *_dev,
18343 +                               struct device_attribute *attr,
18344 +                               const char *buf, size_t count)
18345 +{
18346 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18347 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18348 +       dwc_otg_set_prtsuspend(otg_dev->core_if, in);
18349 +       return count;
18350 +}
18351 +
18352 +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
18353 +
18354 +/**
18355 + * Show the Mode Change Ready Timer status
18356 + */
18357 +static ssize_t mode_ch_tim_en_show(struct device *_dev,
18358 +                                  struct device_attribute *attr, char *buf)
18359 +{
18360 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18361 +       return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n",
18362 +                      dwc_otg_get_mode_ch_tim(otg_dev->core_if));
18363 +}
18364 +
18365 +/**
18366 + * Set the Mode Change Ready Timer status
18367 + */
18368 +static ssize_t mode_ch_tim_en_store(struct device *_dev,
18369 +                                   struct device_attribute *attr,
18370 +                                   const char *buf, size_t count)
18371 +{
18372 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18373 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18374 +       dwc_otg_set_mode_ch_tim(otg_dev->core_if, in);
18375 +       return count;
18376 +}
18377 +
18378 +DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store);
18379 +
18380 +/**
18381 + * Show the value of HFIR Frame Interval bitfield
18382 + */
18383 +static ssize_t fr_interval_show(struct device *_dev,
18384 +                               struct device_attribute *attr, char *buf)
18385 +{
18386 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18387 +       return sprintf(buf, "Frame Interval = 0x%x\n",
18388 +                      dwc_otg_get_fr_interval(otg_dev->core_if));
18389 +}
18390 +
18391 +/**
18392 + * Set the HFIR Frame Interval value
18393 + */
18394 +static ssize_t fr_interval_store(struct device *_dev,
18395 +                                struct device_attribute *attr,
18396 +                                const char *buf, size_t count)
18397 +{
18398 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18399 +       uint32_t in = simple_strtoul(buf, NULL, 10);
18400 +       dwc_otg_set_fr_interval(otg_dev->core_if, in);
18401 +       return count;
18402 +}
18403 +
18404 +DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store);
18405 +
18406 +/**
18407 + * Show the status of Remote Wakeup.
18408 + */
18409 +static ssize_t remote_wakeup_show(struct device *_dev,
18410 +                                 struct device_attribute *attr, char *buf)
18411 +{
18412 +#ifndef DWC_HOST_ONLY
18413 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18414 +
18415 +       return sprintf(buf,
18416 +                      "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n",
18417 +                      dwc_otg_get_remotewakesig(otg_dev->core_if),
18418 +                      dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd),
18419 +                      dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if));
18420 +#else
18421 +       return sprintf(buf, "Host Only Mode!\n");
18422 +#endif /* DWC_HOST_ONLY */
18423 +}
18424 +
18425 +/**
18426 + * Initiate a remote wakeup of the host.  The Device control register
18427 + * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
18428 + * flag is set.
18429 + *
18430 + */
18431 +static ssize_t remote_wakeup_store(struct device *_dev,
18432 +                                  struct device_attribute *attr,
18433 +                                  const char *buf, size_t count)
18434 +{
18435 +#ifndef DWC_HOST_ONLY
18436 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18437 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18438 +
18439 +       if (val & 1) {
18440 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
18441 +       } else {
18442 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
18443 +       }
18444 +#endif /* DWC_HOST_ONLY */
18445 +       return count;
18446 +}
18447 +
18448 +DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show,
18449 +           remote_wakeup_store);
18450 +
18451 +/**
18452 + * Show the whether core is hibernated or not.                                         
18453 + */
18454 +static ssize_t rem_wakeup_pwrdn_show(struct device *_dev,
18455 +                                    struct device_attribute *attr, char *buf)
18456 +{
18457 +#ifndef DWC_HOST_ONLY
18458 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18459 +
18460 +       if (dwc_otg_get_core_state(otg_dev->core_if)) {
18461 +               DWC_PRINTF("Core is in hibernation\n");
18462 +       } else {
18463 +               DWC_PRINTF("Core is not in hibernation\n");
18464 +       }
18465 +#endif /* DWC_HOST_ONLY */
18466 +       return 0;
18467 +}
18468 +
18469 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
18470 +                                             int rem_wakeup, int reset);
18471 +
18472 +/**
18473 + * Initiate a remote wakeup of the device to exit from hibernation.
18474 + */
18475 +static ssize_t rem_wakeup_pwrdn_store(struct device *_dev,
18476 +                                     struct device_attribute *attr,
18477 +                                     const char *buf, size_t count)
18478 +{
18479 +#ifndef DWC_HOST_ONLY
18480 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18481 +       dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0);
18482 +#endif
18483 +       return count;
18484 +}
18485 +
18486 +DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show,
18487 +           rem_wakeup_pwrdn_store);
18488 +
18489 +static ssize_t disconnect_us(struct device *_dev,
18490 +                            struct device_attribute *attr,
18491 +                            const char *buf, size_t count)
18492 +{
18493 +
18494 +#ifndef DWC_HOST_ONLY
18495 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18496 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18497 +       DWC_PRINTF("The Passed value is %04x\n", val);
18498 +
18499 +       dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50);
18500 +
18501 +#endif /* DWC_HOST_ONLY */
18502 +       return count;
18503 +}
18504 +
18505 +DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us);
18506 +
18507 +/**
18508 + * Dump global registers and either host or device registers (depending on the
18509 + * current mode of the core).
18510 + */
18511 +static ssize_t regdump_show(struct device *_dev,
18512 +                           struct device_attribute *attr, char *buf)
18513 +{
18514 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18515 +
18516 +       dwc_otg_dump_global_registers(otg_dev->core_if);
18517 +       if (dwc_otg_is_host_mode(otg_dev->core_if)) {
18518 +               dwc_otg_dump_host_registers(otg_dev->core_if);
18519 +       } else {
18520 +               dwc_otg_dump_dev_registers(otg_dev->core_if);
18521 +
18522 +       }
18523 +       return sprintf(buf, "Register Dump\n");
18524 +}
18525 +
18526 +DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
18527 +
18528 +/**
18529 + * Dump global registers and either host or device registers (depending on the
18530 + * current mode of the core).
18531 + */
18532 +static ssize_t spramdump_show(struct device *_dev,
18533 +                             struct device_attribute *attr, char *buf)
18534 +{
18535 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18536 +
18537 +       dwc_otg_dump_spram(otg_dev->core_if);
18538 +
18539 +       return sprintf(buf, "SPRAM Dump\n");
18540 +}
18541 +
18542 +DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
18543 +
18544 +/**
18545 + * Dump the current hcd state.
18546 + */
18547 +static ssize_t hcddump_show(struct device *_dev,
18548 +                           struct device_attribute *attr, char *buf)
18549 +{
18550 +#ifndef DWC_DEVICE_ONLY
18551 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18552 +       dwc_otg_hcd_dump_state(otg_dev->hcd);
18553 +#endif /* DWC_DEVICE_ONLY */
18554 +       return sprintf(buf, "HCD Dump\n");
18555 +}
18556 +
18557 +DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
18558 +
18559 +/**
18560 + * Dump the average frame remaining at SOF. This can be used to
18561 + * determine average interrupt latency. Frame remaining is also shown for
18562 + * start transfer and two additional sample points.
18563 + */
18564 +static ssize_t hcd_frrem_show(struct device *_dev,
18565 +                             struct device_attribute *attr, char *buf)
18566 +{
18567 +#ifndef DWC_DEVICE_ONLY
18568 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18569 +
18570 +       dwc_otg_hcd_dump_frrem(otg_dev->hcd);
18571 +#endif /* DWC_DEVICE_ONLY */
18572 +       return sprintf(buf, "HCD Dump Frame Remaining\n");
18573 +}
18574 +
18575 +DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
18576 +
18577 +/**
18578 + * Displays the time required to read the GNPTXFSIZ register many times (the
18579 + * output shows the number of times the register is read).
18580 + */
18581 +#define RW_REG_COUNT 10000000
18582 +#define MSEC_PER_JIFFIE 1000/HZ
18583 +static ssize_t rd_reg_test_show(struct device *_dev,
18584 +                               struct device_attribute *attr, char *buf)
18585 +{
18586 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18587 +       int i;
18588 +       int time;
18589 +       int start_jiffies;
18590 +
18591 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18592 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18593 +       start_jiffies = jiffies;
18594 +       for (i = 0; i < RW_REG_COUNT; i++) {
18595 +               dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18596 +       }
18597 +       time = jiffies - start_jiffies;
18598 +       return sprintf(buf,
18599 +                      "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18600 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18601 +}
18602 +
18603 +DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
18604 +
18605 +/**
18606 + * Displays the time required to write the GNPTXFSIZ register many times (the
18607 + * output shows the number of times the register is written).
18608 + */
18609 +static ssize_t wr_reg_test_show(struct device *_dev,
18610 +                               struct device_attribute *attr, char *buf)
18611 +{
18612 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18613 +       uint32_t reg_val;
18614 +       int i;
18615 +       int time;
18616 +       int start_jiffies;
18617 +
18618 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18619 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18620 +       reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18621 +       start_jiffies = jiffies;
18622 +       for (i = 0; i < RW_REG_COUNT; i++) {
18623 +               dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val);
18624 +       }
18625 +       time = jiffies - start_jiffies;
18626 +       return sprintf(buf,
18627 +                      "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18628 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18629 +}
18630 +
18631 +DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
18632 +
18633 +#ifdef CONFIG_USB_DWC_OTG_LPM
18634 +
18635 +/**
18636 +* Show the lpm_response attribute.
18637 +*/
18638 +static ssize_t lpmresp_show(struct device *_dev,
18639 +                           struct device_attribute *attr, char *buf)
18640 +{
18641 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18642 +
18643 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if))
18644 +               return sprintf(buf, "** LPM is DISABLED **\n");
18645 +
18646 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18647 +               return sprintf(buf, "** Current mode is not device mode\n");
18648 +       }
18649 +       return sprintf(buf, "lpm_response = %d\n",
18650 +                      dwc_otg_get_lpmresponse(otg_dev->core_if));
18651 +}
18652 +
18653 +/**
18654 +* Store the lpm_response attribute.
18655 +*/
18656 +static ssize_t lpmresp_store(struct device *_dev,
18657 +                            struct device_attribute *attr,
18658 +                            const char *buf, size_t count)
18659 +{
18660 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18661 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18662 +
18663 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) {
18664 +               return 0;
18665 +       }
18666 +
18667 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18668 +               return 0;
18669 +       }
18670 +
18671 +       dwc_otg_set_lpmresponse(otg_dev->core_if, val);
18672 +       return count;
18673 +}
18674 +
18675 +DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store);
18676 +
18677 +/**
18678 +* Show the sleep_status attribute.
18679 +*/
18680 +static ssize_t sleepstatus_show(struct device *_dev,
18681 +                               struct device_attribute *attr, char *buf)
18682 +{
18683 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18684 +       return sprintf(buf, "Sleep Status = %d\n",
18685 +                      dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if));
18686 +}
18687 +
18688 +/**
18689 + * Store the sleep_status attribure.
18690 + */
18691 +static ssize_t sleepstatus_store(struct device *_dev,
18692 +                                struct device_attribute *attr,
18693 +                                const char *buf, size_t count)
18694 +{
18695 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18696 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
18697 +
18698 +       if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) {
18699 +               if (dwc_otg_is_host_mode(core_if)) {
18700 +
18701 +                       DWC_PRINTF("Host initiated resume\n");
18702 +                       dwc_otg_set_prtresume(otg_dev->core_if, 1);
18703 +               }
18704 +       }
18705 +
18706 +       return count;
18707 +}
18708 +
18709 +DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show,
18710 +           sleepstatus_store);
18711 +
18712 +#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */
18713 +
18714 +/**@}*/
18715 +
18716 +/**
18717 + * Create the device files
18718 + */
18719 +void dwc_otg_attr_create(
18720 +#ifdef LM_INTERFACE
18721 +       struct lm_device *dev
18722 +#elif  defined(PCI_INTERFACE)
18723 +       struct pci_dev *dev
18724 +#elif  defined(PLATFORM_INTERFACE)
18725 +        struct platform_device *dev
18726 +#endif
18727 +    )
18728 +{
18729 +       int error;
18730 +
18731 +       error = device_create_file(&dev->dev, &dev_attr_regoffset);
18732 +       error = device_create_file(&dev->dev, &dev_attr_regvalue);
18733 +       error = device_create_file(&dev->dev, &dev_attr_mode);
18734 +       error = device_create_file(&dev->dev, &dev_attr_hnpcapable);
18735 +       error = device_create_file(&dev->dev, &dev_attr_srpcapable);
18736 +       error = device_create_file(&dev->dev, &dev_attr_hsic_connect);
18737 +       error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic);
18738 +       error = device_create_file(&dev->dev, &dev_attr_hnp);
18739 +       error = device_create_file(&dev->dev, &dev_attr_srp);
18740 +       error = device_create_file(&dev->dev, &dev_attr_buspower);
18741 +       error = device_create_file(&dev->dev, &dev_attr_bussuspend);
18742 +       error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18743 +       error = device_create_file(&dev->dev, &dev_attr_fr_interval);
18744 +       error = device_create_file(&dev->dev, &dev_attr_busconnected);
18745 +       error = device_create_file(&dev->dev, &dev_attr_gotgctl);
18746 +       error = device_create_file(&dev->dev, &dev_attr_gusbcfg);
18747 +       error = device_create_file(&dev->dev, &dev_attr_grxfsiz);
18748 +       error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz);
18749 +       error = device_create_file(&dev->dev, &dev_attr_gpvndctl);
18750 +       error = device_create_file(&dev->dev, &dev_attr_ggpio);
18751 +       error = device_create_file(&dev->dev, &dev_attr_guid);
18752 +       error = device_create_file(&dev->dev, &dev_attr_gsnpsid);
18753 +       error = device_create_file(&dev->dev, &dev_attr_devspeed);
18754 +       error = device_create_file(&dev->dev, &dev_attr_enumspeed);
18755 +       error = device_create_file(&dev->dev, &dev_attr_hptxfsiz);
18756 +       error = device_create_file(&dev->dev, &dev_attr_hprt0);
18757 +       error = device_create_file(&dev->dev, &dev_attr_remote_wakeup);
18758 +       error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18759 +       error = device_create_file(&dev->dev, &dev_attr_disconnect_us);
18760 +       error = device_create_file(&dev->dev, &dev_attr_regdump);
18761 +       error = device_create_file(&dev->dev, &dev_attr_spramdump);
18762 +       error = device_create_file(&dev->dev, &dev_attr_hcddump);
18763 +       error = device_create_file(&dev->dev, &dev_attr_hcd_frrem);
18764 +       error = device_create_file(&dev->dev, &dev_attr_rd_reg_test);
18765 +       error = device_create_file(&dev->dev, &dev_attr_wr_reg_test);
18766 +#ifdef CONFIG_USB_DWC_OTG_LPM
18767 +       error = device_create_file(&dev->dev, &dev_attr_lpm_response);
18768 +       error = device_create_file(&dev->dev, &dev_attr_sleep_status);
18769 +#endif
18770 +}
18771 +
18772 +/**
18773 + * Remove the device files
18774 + */
18775 +void dwc_otg_attr_remove(
18776 +#ifdef LM_INTERFACE
18777 +       struct lm_device *dev
18778 +#elif  defined(PCI_INTERFACE)
18779 +       struct pci_dev *dev
18780 +#elif  defined(PLATFORM_INTERFACE)
18781 +       struct platform_device *dev
18782 +#endif
18783 +    )
18784 +{
18785 +       device_remove_file(&dev->dev, &dev_attr_regoffset);
18786 +       device_remove_file(&dev->dev, &dev_attr_regvalue);
18787 +       device_remove_file(&dev->dev, &dev_attr_mode);
18788 +       device_remove_file(&dev->dev, &dev_attr_hnpcapable);
18789 +       device_remove_file(&dev->dev, &dev_attr_srpcapable);
18790 +       device_remove_file(&dev->dev, &dev_attr_hsic_connect);
18791 +       device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic);
18792 +       device_remove_file(&dev->dev, &dev_attr_hnp);
18793 +       device_remove_file(&dev->dev, &dev_attr_srp);
18794 +       device_remove_file(&dev->dev, &dev_attr_buspower);
18795 +       device_remove_file(&dev->dev, &dev_attr_bussuspend);
18796 +       device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18797 +       device_remove_file(&dev->dev, &dev_attr_fr_interval);
18798 +       device_remove_file(&dev->dev, &dev_attr_busconnected);
18799 +       device_remove_file(&dev->dev, &dev_attr_gotgctl);
18800 +       device_remove_file(&dev->dev, &dev_attr_gusbcfg);
18801 +       device_remove_file(&dev->dev, &dev_attr_grxfsiz);
18802 +       device_remove_file(&dev->dev, &dev_attr_gnptxfsiz);
18803 +       device_remove_file(&dev->dev, &dev_attr_gpvndctl);
18804 +       device_remove_file(&dev->dev, &dev_attr_ggpio);
18805 +       device_remove_file(&dev->dev, &dev_attr_guid);
18806 +       device_remove_file(&dev->dev, &dev_attr_gsnpsid);
18807 +       device_remove_file(&dev->dev, &dev_attr_devspeed);
18808 +       device_remove_file(&dev->dev, &dev_attr_enumspeed);
18809 +       device_remove_file(&dev->dev, &dev_attr_hptxfsiz);
18810 +       device_remove_file(&dev->dev, &dev_attr_hprt0);
18811 +       device_remove_file(&dev->dev, &dev_attr_remote_wakeup);
18812 +       device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18813 +       device_remove_file(&dev->dev, &dev_attr_disconnect_us);
18814 +       device_remove_file(&dev->dev, &dev_attr_regdump);
18815 +       device_remove_file(&dev->dev, &dev_attr_spramdump);
18816 +       device_remove_file(&dev->dev, &dev_attr_hcddump);
18817 +       device_remove_file(&dev->dev, &dev_attr_hcd_frrem);
18818 +       device_remove_file(&dev->dev, &dev_attr_rd_reg_test);
18819 +       device_remove_file(&dev->dev, &dev_attr_wr_reg_test);
18820 +#ifdef CONFIG_USB_DWC_OTG_LPM
18821 +       device_remove_file(&dev->dev, &dev_attr_lpm_response);
18822 +       device_remove_file(&dev->dev, &dev_attr_sleep_status);
18823 +#endif
18824 +}
18825 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h
18826 new file mode 100644
18827 index 0000000..fc14d94
18828 --- /dev/null
18829 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h
18830 @@ -0,0 +1,89 @@
18831 +/* ==========================================================================
18832 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
18833 + * $Revision: #13 $
18834 + * $Date: 2010/06/21 $
18835 + * $Change: 1532021 $
18836 + *
18837 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18838 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18839 + * otherwise expressly agreed to in writing between Synopsys and you.
18840 + * 
18841 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18842 + * any End User Software License Agreement or Agreement for Licensed Product
18843 + * with Synopsys or any supplement thereto. You are permitted to use and
18844 + * redistribute this Software in source and binary forms, with or without
18845 + * modification, provided that redistributions of source code must retain this
18846 + * notice. You may not view, use, disclose, copy or distribute this file or
18847 + * any information contained herein except pursuant to this license grant from
18848 + * Synopsys. If you do not agree with this notice, including the disclaimer
18849 + * below, then you are not authorized to use the Software.
18850 + * 
18851 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18852 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18853 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18854 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18855 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18856 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18857 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18858 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18859 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18860 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18861 + * DAMAGE.
18862 + * ========================================================================== */
18863 +
18864 +#if !defined(__DWC_OTG_ATTR_H__)
18865 +#define __DWC_OTG_ATTR_H__
18866 +
18867 +/** @file
18868 + * This file contains the interface to the Linux device attributes.
18869 + */
18870 +extern struct device_attribute dev_attr_regoffset;
18871 +extern struct device_attribute dev_attr_regvalue;
18872 +
18873 +extern struct device_attribute dev_attr_mode;
18874 +extern struct device_attribute dev_attr_hnpcapable;
18875 +extern struct device_attribute dev_attr_srpcapable;
18876 +extern struct device_attribute dev_attr_hnp;
18877 +extern struct device_attribute dev_attr_srp;
18878 +extern struct device_attribute dev_attr_buspower;
18879 +extern struct device_attribute dev_attr_bussuspend;
18880 +extern struct device_attribute dev_attr_mode_ch_tim_en;
18881 +extern struct device_attribute dev_attr_fr_interval;
18882 +extern struct device_attribute dev_attr_busconnected;
18883 +extern struct device_attribute dev_attr_gotgctl;
18884 +extern struct device_attribute dev_attr_gusbcfg;
18885 +extern struct device_attribute dev_attr_grxfsiz;
18886 +extern struct device_attribute dev_attr_gnptxfsiz;
18887 +extern struct device_attribute dev_attr_gpvndctl;
18888 +extern struct device_attribute dev_attr_ggpio;
18889 +extern struct device_attribute dev_attr_guid;
18890 +extern struct device_attribute dev_attr_gsnpsid;
18891 +extern struct device_attribute dev_attr_devspeed;
18892 +extern struct device_attribute dev_attr_enumspeed;
18893 +extern struct device_attribute dev_attr_hptxfsiz;
18894 +extern struct device_attribute dev_attr_hprt0;
18895 +#ifdef CONFIG_USB_DWC_OTG_LPM
18896 +extern struct device_attribute dev_attr_lpm_response;
18897 +extern struct device_attribute devi_attr_sleep_status;
18898 +#endif
18899 +
18900 +void dwc_otg_attr_create(
18901 +#ifdef LM_INTERFACE
18902 +                               struct lm_device *dev
18903 +#elif  defined(PCI_INTERFACE)
18904 +                               struct pci_dev *dev
18905 +#elif  defined(PLATFORM_INTERFACE)
18906 +       struct platform_device *dev
18907 +#endif
18908 +    );
18909 +
18910 +void dwc_otg_attr_remove(
18911 +#ifdef LM_INTERFACE
18912 +                               struct lm_device *dev
18913 +#elif  defined(PCI_INTERFACE)
18914 +                               struct pci_dev *dev
18915 +#elif  defined(PLATFORM_INTERFACE)
18916 +       struct platform_device *dev
18917 +#endif
18918 +    );
18919 +#endif
18920 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.c b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
18921 new file mode 100644
18922 index 0000000..a9878d6
18923 --- /dev/null
18924 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
18925 @@ -0,0 +1,1876 @@
18926 +/* ==========================================================================
18927 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18928 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18929 + * otherwise expressly agreed to in writing between Synopsys and you.
18930 + * 
18931 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18932 + * any End User Software License Agreement or Agreement for Licensed Product
18933 + * with Synopsys or any supplement thereto. You are permitted to use and
18934 + * redistribute this Software in source and binary forms, with or without
18935 + * modification, provided that redistributions of source code must retain this
18936 + * notice. You may not view, use, disclose, copy or distribute this file or
18937 + * any information contained herein except pursuant to this license grant from
18938 + * Synopsys. If you do not agree with this notice, including the disclaimer
18939 + * below, then you are not authorized to use the Software.
18940 + * 
18941 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18942 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18943 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18944 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18945 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18946 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18947 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18948 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18949 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18950 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18951 + * DAMAGE.
18952 + * ========================================================================== */
18953 +
18954 +/** @file 
18955 + *
18956 + * This file contains the most of the CFI(Core Feature Interface) 
18957 + * implementation for the OTG. 
18958 + */
18959 +
18960 +#ifdef DWC_UTE_CFI
18961 +
18962 +#include "dwc_otg_pcd.h"
18963 +#include "dwc_otg_cfi.h"
18964 +
18965 +/** This definition should actually migrate to the Portability Library */
18966 +#define DWC_CONSTANT_CPU_TO_LE16(x) (x)
18967 +
18968 +extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
18969 +
18970 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
18971 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
18972 +                                struct dwc_otg_pcd *pcd,
18973 +                                struct cfi_usb_ctrlrequest *ctrl_req);
18974 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
18975 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18976 +                            struct cfi_usb_ctrlrequest *req);
18977 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18978 +                                struct cfi_usb_ctrlrequest *req);
18979 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18980 +                               struct cfi_usb_ctrlrequest *req);
18981 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
18982 +                            struct cfi_usb_ctrlrequest *req);
18983 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
18984 +
18985 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
18986 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
18987 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
18988 +
18989 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
18990 +
18991 +/** This is the header of the all features descriptor */
18992 +static cfi_all_features_header_t all_props_desc_header = {
18993 +       .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
18994 +       .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
18995 +       .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
18996 +};
18997 +
18998 +/** This is an array of statically allocated feature descriptors */
18999 +static cfi_feature_desc_header_t prop_descs[] = {
19000 +
19001 +       /* FT_ID_DMA_MODE */
19002 +       {
19003 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
19004 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19005 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
19006 +        },
19007 +
19008 +       /* FT_ID_DMA_BUFFER_SETUP */
19009 +       {
19010 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
19011 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19012 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
19013 +        },
19014 +
19015 +       /* FT_ID_DMA_BUFF_ALIGN */
19016 +       {
19017 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
19018 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19019 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
19020 +        },
19021 +
19022 +       /* FT_ID_DMA_CONCAT_SETUP */
19023 +       {
19024 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
19025 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19026 +        //.wDataLength  = DWC_CONSTANT_CPU_TO_LE16(6),
19027 +        },
19028 +
19029 +       /* FT_ID_DMA_CIRCULAR */
19030 +       {
19031 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
19032 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19033 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
19034 +        },
19035 +
19036 +       /* FT_ID_THRESHOLD_SETUP */
19037 +       {
19038 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
19039 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19040 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
19041 +        },
19042 +
19043 +       /* FT_ID_DFIFO_DEPTH */
19044 +       {
19045 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
19046 +        .bmAttributes = CFI_FEATURE_ATTR_RO,
19047 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
19048 +        },
19049 +
19050 +       /* FT_ID_TX_FIFO_DEPTH */
19051 +       {
19052 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
19053 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19054 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
19055 +        },
19056 +
19057 +       /* FT_ID_RX_FIFO_DEPTH */
19058 +       {
19059 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
19060 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19061 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
19062 +        }
19063 +};
19064 +
19065 +/** The table of feature names */
19066 +cfi_string_t prop_name_table[] = {
19067 +       {FT_ID_DMA_MODE, "dma_mode"},
19068 +       {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
19069 +       {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
19070 +       {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
19071 +       {FT_ID_DMA_CIRCULAR, "buffer_circular"},
19072 +       {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
19073 +       {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
19074 +       {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
19075 +       {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
19076 +       {}
19077 +};
19078 +
19079 +/************************************************************************/
19080 +
19081 +/** 
19082 + * Returns the name of the feature by its ID 
19083 + * or NULL if no featute ID matches.
19084 + * 
19085 + */
19086 +const uint8_t *get_prop_name(uint16_t prop_id, int *len)
19087 +{
19088 +       cfi_string_t *pstr;
19089 +       *len = 0;
19090 +
19091 +       for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
19092 +               if (pstr->id == prop_id) {
19093 +                       *len = DWC_STRLEN(pstr->s);
19094 +                       return pstr->s;
19095 +               }
19096 +       }
19097 +       return NULL;
19098 +}
19099 +
19100 +/**
19101 + * This function handles all CFI specific control requests.
19102 + * 
19103 + * Return a negative value to stall the DCE.
19104 + */
19105 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
19106 +{
19107 +       int retval = 0;
19108 +       dwc_otg_pcd_ep_t *ep = NULL;
19109 +       cfiobject_t *cfi = pcd->cfi;
19110 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
19111 +       uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
19112 +       uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
19113 +       uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
19114 +       uint32_t regaddr = 0;
19115 +       uint32_t regval = 0;
19116 +
19117 +       /* Save this Control Request in the CFI object. 
19118 +        * The data field will be assigned in the data stage completion CB function.
19119 +        */
19120 +       cfi->ctrl_req = *ctrl;
19121 +       cfi->ctrl_req.data = NULL;
19122 +
19123 +       cfi->need_gadget_att = 0;
19124 +       cfi->need_status_in_complete = 0;
19125 +
19126 +       switch (ctrl->bRequest) {
19127 +       case VEN_CORE_GET_FEATURES:
19128 +               retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
19129 +               if (retval >= 0) {
19130 +                       //dump_msg(cfi->buf_in.buf, retval);
19131 +                       ep = &pcd->ep0;
19132 +
19133 +                       retval = min((uint16_t) retval, wLen);
19134 +                       /* Transfer this buffer to the host through the EP0-IN EP */
19135 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19136 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19137 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19138 +                       ep->dwc_ep.xfer_len = retval;
19139 +                       ep->dwc_ep.xfer_count = 0;
19140 +                       ep->dwc_ep.sent_zlp = 0;
19141 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19142 +
19143 +                       pcd->ep0_pending = 1;
19144 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19145 +               }
19146 +               retval = 0;
19147 +               break;
19148 +
19149 +       case VEN_CORE_GET_FEATURE:
19150 +               CFI_INFO("VEN_CORE_GET_FEATURE\n");
19151 +               retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
19152 +                                              pcd, ctrl);
19153 +               if (retval >= 0) {
19154 +                       ep = &pcd->ep0;
19155 +
19156 +                       retval = min((uint16_t) retval, wLen);
19157 +                       /* Transfer this buffer to the host through the EP0-IN EP */
19158 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19159 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19160 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19161 +                       ep->dwc_ep.xfer_len = retval;
19162 +                       ep->dwc_ep.xfer_count = 0;
19163 +                       ep->dwc_ep.sent_zlp = 0;
19164 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19165 +
19166 +                       pcd->ep0_pending = 1;
19167 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19168 +               }
19169 +               CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
19170 +               dump_msg(cfi->buf_in.buf, retval);
19171 +               break;
19172 +
19173 +       case VEN_CORE_SET_FEATURE:
19174 +               CFI_INFO("VEN_CORE_SET_FEATURE\n");
19175 +               /* Set up an XFER to get the data stage of the control request,
19176 +                * which is the new value of the feature to be modified.
19177 +                */
19178 +               ep = &pcd->ep0;
19179 +               ep->dwc_ep.is_in = 0;
19180 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
19181 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
19182 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
19183 +               ep->dwc_ep.xfer_len = wLen;
19184 +               ep->dwc_ep.xfer_count = 0;
19185 +               ep->dwc_ep.sent_zlp = 0;
19186 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19187 +
19188 +               pcd->ep0_pending = 1;
19189 +               /* Read the control write's data stage */
19190 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19191 +               retval = 0;
19192 +               break;
19193 +
19194 +       case VEN_CORE_RESET_FEATURES:
19195 +               CFI_INFO("VEN_CORE_RESET_FEATURES\n");
19196 +               cfi->need_gadget_att = 1;
19197 +               cfi->need_status_in_complete = 1;
19198 +               retval = cfi_preproc_reset(pcd, ctrl);
19199 +               CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
19200 +               break;
19201 +
19202 +       case VEN_CORE_ACTIVATE_FEATURES:
19203 +               CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
19204 +               break;
19205 +
19206 +       case VEN_CORE_READ_REGISTER:
19207 +               CFI_INFO("VEN_CORE_READ_REGISTER\n");
19208 +               /* wValue optionally contains the HI WORD of the register offset and
19209 +                * wIndex contains the LOW WORD of the register offset 
19210 +                */
19211 +               if (wValue == 0) {
19212 +                       /* @TODO - MAS - fix the access to the base field */
19213 +                       regaddr = 0;
19214 +                       //regaddr = (uint32_t) pcd->otg_dev->os_dep.base;
19215 +                       //GET_CORE_IF(pcd)->co
19216 +                       regaddr |= wIndex;
19217 +               } else {
19218 +                       regaddr = (wValue << 16) | wIndex;
19219 +               }
19220 +
19221 +               /* Read a 32-bit value of the memory at the regaddr */
19222 +               regval = DWC_READ_REG32((uint32_t *) regaddr);
19223 +
19224 +               ep = &pcd->ep0;
19225 +               dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
19226 +               ep->dwc_ep.is_in = 1;
19227 +               ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19228 +               ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19229 +               ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19230 +               ep->dwc_ep.xfer_len = wLen;
19231 +               ep->dwc_ep.xfer_count = 0;
19232 +               ep->dwc_ep.sent_zlp = 0;
19233 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19234 +
19235 +               pcd->ep0_pending = 1;
19236 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19237 +               cfi->need_gadget_att = 0;
19238 +               retval = 0;
19239 +               break;
19240 +
19241 +       case VEN_CORE_WRITE_REGISTER:
19242 +               CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
19243 +               /* Set up an XFER to get the data stage of the control request,
19244 +                * which is the new value of the register to be modified.
19245 +                */
19246 +               ep = &pcd->ep0;
19247 +               ep->dwc_ep.is_in = 0;
19248 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
19249 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
19250 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
19251 +               ep->dwc_ep.xfer_len = wLen;
19252 +               ep->dwc_ep.xfer_count = 0;
19253 +               ep->dwc_ep.sent_zlp = 0;
19254 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19255 +
19256 +               pcd->ep0_pending = 1;
19257 +               /* Read the control write's data stage */
19258 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19259 +               retval = 0;
19260 +               break;
19261 +
19262 +       default:
19263 +               retval = -DWC_E_NOT_SUPPORTED;
19264 +               break;
19265 +       }
19266 +
19267 +       return retval;
19268 +}
19269 +
19270 +/**
19271 + * This function prepares the core features descriptors and copies its
19272 + * raw representation into the buffer <buf>.
19273 + * 
19274 + * The buffer structure is as follows:
19275 + *     all_features_header (8 bytes)
19276 + *     features_#1 (8 bytes + feature name string length)
19277 + *     features_#2 (8 bytes + feature name string length)
19278 + *     .....
19279 + *     features_#n - where n=the total count of feature descriptors
19280 + */
19281 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
19282 +{
19283 +       cfi_feature_desc_header_t *prop_hdr = prop_descs;
19284 +       cfi_feature_desc_header_t *prop;
19285 +       cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
19286 +       cfi_all_features_header_t *tmp;
19287 +       uint8_t *tmpbuf = buf;
19288 +       const uint8_t *pname = NULL;
19289 +       int i, j, namelen = 0, totlen;
19290 +
19291 +       /* Prepare and copy the core features into the buffer */
19292 +       CFI_INFO("%s:\n", __func__);
19293 +
19294 +       tmp = (cfi_all_features_header_t *) tmpbuf;
19295 +       *tmp = *all_props_hdr;
19296 +       tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
19297 +
19298 +       j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
19299 +       for (i = 0; i < j; i++, prop_hdr++) {
19300 +               pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
19301 +               prop = (cfi_feature_desc_header_t *) tmpbuf;
19302 +               *prop = *prop_hdr;
19303 +
19304 +               prop->bNameLen = namelen;
19305 +               prop->wLength =
19306 +                   DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
19307 +                                            namelen);
19308 +
19309 +               tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
19310 +               dwc_memcpy(tmpbuf, pname, namelen);
19311 +               tmpbuf += namelen;
19312 +       }
19313 +
19314 +       totlen = tmpbuf - buf;
19315 +
19316 +       if (totlen > 0) {
19317 +               tmp = (cfi_all_features_header_t *) buf;
19318 +               tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
19319 +       }
19320 +
19321 +       return totlen;
19322 +}
19323 +
19324 +/**
19325 + * This function releases all the dynamic memory in the CFI object.
19326 + */
19327 +static void cfi_release(cfiobject_t * cfiobj)
19328 +{
19329 +       cfi_ep_t *cfiep;
19330 +       dwc_list_link_t *tmp;
19331 +
19332 +       CFI_INFO("%s\n", __func__);
19333 +
19334 +       if (cfiobj->buf_in.buf) {
19335 +               DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
19336 +                            cfiobj->buf_in.addr);
19337 +               cfiobj->buf_in.buf = NULL;
19338 +       }
19339 +
19340 +       if (cfiobj->buf_out.buf) {
19341 +               DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
19342 +                            cfiobj->buf_out.addr);
19343 +               cfiobj->buf_out.buf = NULL;
19344 +       }
19345 +
19346 +       /* Free the Buffer Setup values for each EP */
19347 +       //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
19348 +       DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
19349 +               cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19350 +               cfi_free_ep_bs_dyn_data(cfiep);
19351 +       }
19352 +}
19353 +
19354 +/**
19355 + * This function frees the dynamically allocated EP buffer setup data.
19356 + */
19357 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
19358 +{
19359 +       if (cfiep->bm_sg) {
19360 +               DWC_FREE(cfiep->bm_sg);
19361 +               cfiep->bm_sg = NULL;
19362 +       }
19363 +
19364 +       if (cfiep->bm_align) {
19365 +               DWC_FREE(cfiep->bm_align);
19366 +               cfiep->bm_align = NULL;
19367 +       }
19368 +
19369 +       if (cfiep->bm_concat) {
19370 +               if (NULL != cfiep->bm_concat->wTxBytes) {
19371 +                       DWC_FREE(cfiep->bm_concat->wTxBytes);
19372 +                       cfiep->bm_concat->wTxBytes = NULL;
19373 +               }
19374 +               DWC_FREE(cfiep->bm_concat);
19375 +               cfiep->bm_concat = NULL;
19376 +       }
19377 +}
19378 +
19379 +/**
19380 + * This function initializes the default values of the features
19381 + * for a specific endpoint and should be called only once when
19382 + * the EP is enabled first time.
19383 + */
19384 +static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
19385 +{
19386 +       int retval = 0;
19387 +
19388 +       cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));
19389 +       if (NULL == cfiep->bm_sg) {
19390 +               CFI_INFO("Failed to allocate memory for SG feature value\n");
19391 +               return -DWC_E_NO_MEMORY;
19392 +       }
19393 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19394 +
19395 +       /* For the Concatenation feature's default value we do not allocate
19396 +        * memory for the wTxBytes field - it will be done in the set_feature_value
19397 +        * request handler.
19398 +        */
19399 +       cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));
19400 +       if (NULL == cfiep->bm_concat) {
19401 +               CFI_INFO
19402 +                   ("Failed to allocate memory for CONCATENATION feature value\n");
19403 +               DWC_FREE(cfiep->bm_sg);
19404 +               return -DWC_E_NO_MEMORY;
19405 +       }
19406 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19407 +
19408 +       cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));
19409 +       if (NULL == cfiep->bm_align) {
19410 +               CFI_INFO
19411 +                   ("Failed to allocate memory for Alignment feature value\n");
19412 +               DWC_FREE(cfiep->bm_sg);
19413 +               DWC_FREE(cfiep->bm_concat);
19414 +               return -DWC_E_NO_MEMORY;
19415 +       }
19416 +       dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
19417 +
19418 +       return retval;
19419 +}
19420 +
19421 +/**
19422 + * The callback function that notifies the CFI on the activation of
19423 + * an endpoint in the PCD. The following steps are done in this function:
19424 + *
19425 + *     Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's 
19426 + *             active endpoint)
19427 + *     Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP
19428 + *     Set the Buffer Mode to standard
19429 + *     Initialize the default values for all EP modes (SG, Circular, Concat, Align)
19430 + *     Add the cfi_ep_t object to the list of active endpoints in the CFI object
19431 + */
19432 +static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19433 +                        struct dwc_otg_pcd_ep *ep)
19434 +{
19435 +       cfi_ep_t *cfiep;
19436 +       int retval = -DWC_E_NOT_SUPPORTED;
19437 +
19438 +       CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
19439 +                "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
19440 +       /* MAS - Check whether this endpoint already is in the list */
19441 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19442 +
19443 +       if (NULL == cfiep) {
19444 +               /* Allocate a cfi_ep_t object */
19445 +               cfiep = DWC_ALLOC(sizeof(cfi_ep_t));
19446 +               if (NULL == cfiep) {
19447 +                       CFI_INFO
19448 +                           ("Unable to allocate memory for <cfiep> in function %s\n",
19449 +                            __func__);
19450 +                       return -DWC_E_NO_MEMORY;
19451 +               }
19452 +               dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
19453 +
19454 +               /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
19455 +               cfiep->ep = ep;
19456 +
19457 +               /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
19458 +               ep->dwc_ep.descs =
19459 +                   DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *
19460 +                                 sizeof(dwc_otg_dma_desc_t),
19461 +                                 &ep->dwc_ep.descs_dma_addr);
19462 +
19463 +               if (NULL == ep->dwc_ep.descs) {
19464 +                       DWC_FREE(cfiep);
19465 +                       return -DWC_E_NO_MEMORY;
19466 +               }
19467 +
19468 +               DWC_LIST_INIT(&cfiep->lh);
19469 +
19470 +               /* Set the buffer mode to BM_STANDARD. It will be modified 
19471 +                * when building descriptors for a specific buffer mode */
19472 +               ep->dwc_ep.buff_mode = BM_STANDARD;
19473 +
19474 +               /* Create and initialize the default values for this EP's Buffer modes */
19475 +               if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
19476 +                       return retval;
19477 +
19478 +               /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
19479 +               DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
19480 +               retval = 0;
19481 +       } else {                /* The sought EP already is in the list */
19482 +               CFI_INFO("%s: The sought EP already is in the list\n",
19483 +                        __func__);
19484 +       }
19485 +
19486 +       return retval;
19487 +}
19488 +
19489 +/**
19490 + * This function is called when the data stage of a 3-stage Control Write request
19491 + * is complete.
19492 + * 
19493 + */
19494 +static int cfi_ctrl_write_complete(struct cfiobject *cfi,
19495 +                                  struct dwc_otg_pcd *pcd)
19496 +{
19497 +       uint32_t addr, reg_value;
19498 +       uint16_t wIndex, wValue;
19499 +       uint8_t bRequest;
19500 +       uint8_t *buf = cfi->buf_out.buf;
19501 +       //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
19502 +       struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
19503 +       int retval = -DWC_E_NOT_SUPPORTED;
19504 +
19505 +       CFI_INFO("%s\n", __func__);
19506 +
19507 +       bRequest = ctrl_req->bRequest;
19508 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
19509 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
19510 +
19511 +       /* 
19512 +        * Save the pointer to the data stage in the ctrl_req's <data> field.
19513 +        * The request should be already saved in the command stage by now.
19514 +        */
19515 +       ctrl_req->data = cfi->buf_out.buf;
19516 +       cfi->need_status_in_complete = 0;
19517 +       cfi->need_gadget_att = 0;
19518 +
19519 +       switch (bRequest) {
19520 +       case VEN_CORE_WRITE_REGISTER:
19521 +               /* The buffer contains raw data of the new value for the register */
19522 +               reg_value = *((uint32_t *) buf);
19523 +               if (wValue == 0) {
19524 +                       addr = 0;
19525 +                       //addr = (uint32_t) pcd->otg_dev->os_dep.base;
19526 +                       addr += wIndex;
19527 +               } else {
19528 +                       addr = (wValue << 16) | wIndex;
19529 +               }
19530 +
19531 +               //writel(reg_value, addr);
19532 +
19533 +               retval = 0;
19534 +               cfi->need_status_in_complete = 1;
19535 +               break;
19536 +
19537 +       case VEN_CORE_SET_FEATURE:
19538 +               /* The buffer contains raw data of the new value of the feature */
19539 +               retval = cfi_set_feature_value(pcd);
19540 +               if (retval < 0)
19541 +                       return retval;
19542 +
19543 +               cfi->need_status_in_complete = 1;
19544 +               break;
19545 +
19546 +       default:
19547 +               break;
19548 +       }
19549 +
19550 +       return retval;
19551 +}
19552 +
19553 +/**
19554 + * This function builds the DMA descriptors for the SG buffer mode.
19555 + */
19556 +static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19557 +                              dwc_otg_pcd_request_t * req)
19558 +{
19559 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19560 +       ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
19561 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19562 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19563 +       dma_addr_t buff_addr = req->dma;
19564 +       int i;
19565 +       uint32_t txsize, off;
19566 +
19567 +       txsize = sgval->wSize;
19568 +       off = sgval->bOffset;
19569 +
19570 +//      CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", 
19571 +//              __func__, cfiep->ep->ep.name, txsize, off);
19572 +
19573 +       for (i = 0; i < sgval->bCount; i++) {
19574 +               desc->status.b.bs = BS_HOST_BUSY;
19575 +               desc->buf = buff_addr;
19576 +               desc->status.b.l = 0;
19577 +               desc->status.b.ioc = 0;
19578 +               desc->status.b.sp = 0;
19579 +               desc->status.b.bytes = txsize;
19580 +               desc->status.b.bs = BS_HOST_READY;
19581 +
19582 +               /* Set the next address of the buffer */
19583 +               buff_addr += txsize + off;
19584 +               desc_last = desc;
19585 +               desc++;
19586 +       }
19587 +
19588 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19589 +       desc_last->status.b.l = 1;
19590 +       desc_last->status.b.ioc = 1;
19591 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19592 +       /* Save the last DMA descriptor pointer */
19593 +       cfiep->dma_desc_last = desc_last;
19594 +       cfiep->desc_count = sgval->bCount;
19595 +}
19596 +
19597 +/**
19598 + * This function builds the DMA descriptors for the Concatenation buffer mode.
19599 + */
19600 +static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19601 +                                  dwc_otg_pcd_request_t * req)
19602 +{
19603 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19604 +       ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
19605 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19606 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19607 +       dma_addr_t buff_addr = req->dma;
19608 +       int i;
19609 +       uint16_t *txsize;
19610 +
19611 +       txsize = concatval->wTxBytes;
19612 +
19613 +       for (i = 0; i < concatval->hdr.bDescCount; i++) {
19614 +               desc->buf = buff_addr;
19615 +               desc->status.b.bs = BS_HOST_BUSY;
19616 +               desc->status.b.l = 0;
19617 +               desc->status.b.ioc = 0;
19618 +               desc->status.b.sp = 0;
19619 +               desc->status.b.bytes = *txsize;
19620 +               desc->status.b.bs = BS_HOST_READY;
19621 +
19622 +               txsize++;
19623 +               /* Set the next address of the buffer */
19624 +               buff_addr += UGETW(ep->desc->wMaxPacketSize);
19625 +               desc_last = desc;
19626 +               desc++;
19627 +       }
19628 +
19629 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19630 +       desc_last->status.b.l = 1;
19631 +       desc_last->status.b.ioc = 1;
19632 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19633 +       cfiep->dma_desc_last = desc_last;
19634 +       cfiep->desc_count = concatval->hdr.bDescCount;
19635 +}
19636 +
19637 +/**
19638 + * This function builds the DMA descriptors for the Circular buffer mode
19639 + */
19640 +static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19641 +                                dwc_otg_pcd_request_t * req)
19642 +{
19643 +       /* @todo: MAS - add implementation when this feature needs to be tested */
19644 +}
19645 +
19646 +/**
19647 + * This function builds the DMA descriptors for the Alignment buffer mode
19648 + */
19649 +static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19650 +                                 dwc_otg_pcd_request_t * req)
19651 +{
19652 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19653 +       ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
19654 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19655 +       dma_addr_t buff_addr = req->dma;
19656 +
19657 +       desc->status.b.bs = BS_HOST_BUSY;
19658 +       desc->status.b.l = 1;
19659 +       desc->status.b.ioc = 1;
19660 +       desc->status.b.sp = ep->dwc_ep.sent_zlp;
19661 +       desc->status.b.bytes = req->length;
19662 +       /* Adjust the buffer alignment */
19663 +       desc->buf = (buff_addr + alignval->bAlign);
19664 +       desc->status.b.bs = BS_HOST_READY;
19665 +       cfiep->dma_desc_last = desc;
19666 +       cfiep->desc_count = 1;
19667 +}
19668 +
19669 +/**
19670 + * This function builds the DMA descriptors chain for different modes of the
19671 + * buffer setup of an endpoint.
19672 + */
19673 +static void cfi_build_descriptors(struct cfiobject *cfi,
19674 +                                 struct dwc_otg_pcd *pcd,
19675 +                                 struct dwc_otg_pcd_ep *ep,
19676 +                                 dwc_otg_pcd_request_t * req)
19677 +{
19678 +       cfi_ep_t *cfiep;
19679 +
19680 +       /* Get the cfiep by the dwc_otg_pcd_ep */
19681 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19682 +       if (NULL == cfiep) {
19683 +               CFI_INFO("%s: Unable to find a matching active endpoint\n",
19684 +                        __func__);
19685 +               return;
19686 +       }
19687 +
19688 +       cfiep->xfer_len = req->length;
19689 +
19690 +       /* Iterate through all the DMA descriptors */
19691 +       switch (cfiep->ep->dwc_ep.buff_mode) {
19692 +       case BM_SG:
19693 +               cfi_build_sg_descs(cfi, cfiep, req);
19694 +               break;
19695 +
19696 +       case BM_CONCAT:
19697 +               cfi_build_concat_descs(cfi, cfiep, req);
19698 +               break;
19699 +
19700 +       case BM_CIRCULAR:
19701 +               cfi_build_circ_descs(cfi, cfiep, req);
19702 +               break;
19703 +
19704 +       case BM_ALIGN:
19705 +               cfi_build_align_descs(cfi, cfiep, req);
19706 +               break;
19707 +
19708 +       default:
19709 +               break;
19710 +       }
19711 +}
19712 +
19713 +/**
19714 + * Allocate DMA buffer for different Buffer modes.
19715 + */
19716 +static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19717 +                             struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
19718 +                             unsigned size, gfp_t flags)
19719 +{
19720 +       return DWC_DMA_ALLOC(size, dma);
19721 +}
19722 +
19723 +/**
19724 + * This function initializes the CFI object.
19725 + */
19726 +int init_cfi(cfiobject_t * cfiobj)
19727 +{
19728 +       CFI_INFO("%s\n", __func__);
19729 +
19730 +       /* Allocate a buffer for IN XFERs */
19731 +       cfiobj->buf_in.buf =
19732 +           DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
19733 +       if (NULL == cfiobj->buf_in.buf) {
19734 +               CFI_INFO("Unable to allocate buffer for INs\n");
19735 +               return -DWC_E_NO_MEMORY;
19736 +       }
19737 +
19738 +       /* Allocate a buffer for OUT XFERs */
19739 +       cfiobj->buf_out.buf =
19740 +           DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
19741 +       if (NULL == cfiobj->buf_out.buf) {
19742 +               CFI_INFO("Unable to allocate buffer for OUT\n");
19743 +               return -DWC_E_NO_MEMORY;
19744 +       }
19745 +
19746 +       /* Initialize the callback function pointers */
19747 +       cfiobj->ops.release = cfi_release;
19748 +       cfiobj->ops.ep_enable = cfi_ep_enable;
19749 +       cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
19750 +       cfiobj->ops.build_descriptors = cfi_build_descriptors;
19751 +       cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
19752 +
19753 +       /* Initialize the list of active endpoints in the CFI object */
19754 +       DWC_LIST_INIT(&cfiobj->active_eps);
19755 +
19756 +       return 0;
19757 +}
19758 +
19759 +/**
19760 + * This function reads the required feature's current value into the buffer
19761 + *
19762 + * @retval: Returns negative as error, or the data length of the feature  
19763 + */
19764 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
19765 +                                struct dwc_otg_pcd *pcd,
19766 +                                struct cfi_usb_ctrlrequest *ctrl_req)
19767 +{
19768 +       int retval = -DWC_E_NOT_SUPPORTED;
19769 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
19770 +       uint16_t dfifo, rxfifo, txfifo;
19771 +
19772 +       switch (ctrl_req->wIndex) {
19773 +               /* Whether the DDMA is enabled or not */
19774 +       case FT_ID_DMA_MODE:
19775 +               *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
19776 +               retval = 1;
19777 +               break;
19778 +
19779 +       case FT_ID_DMA_BUFFER_SETUP:
19780 +               retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
19781 +               break;
19782 +
19783 +       case FT_ID_DMA_BUFF_ALIGN:
19784 +               retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
19785 +               break;
19786 +
19787 +       case FT_ID_DMA_CONCAT_SETUP:
19788 +               retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
19789 +               break;
19790 +
19791 +       case FT_ID_DMA_CIRCULAR:
19792 +               CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
19793 +               break;
19794 +
19795 +       case FT_ID_THRESHOLD_SETUP:
19796 +               CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
19797 +               break;
19798 +
19799 +       case FT_ID_DFIFO_DEPTH:
19800 +               dfifo = get_dfifo_size(coreif);
19801 +               *((uint16_t *) buf) = dfifo;
19802 +               retval = sizeof(uint16_t);
19803 +               break;
19804 +
19805 +       case FT_ID_TX_FIFO_DEPTH:
19806 +               retval = get_txfifo_size(pcd, ctrl_req->wValue);
19807 +               if (retval >= 0) {
19808 +                       txfifo = retval;
19809 +                       *((uint16_t *) buf) = txfifo;
19810 +                       retval = sizeof(uint16_t);
19811 +               }
19812 +               break;
19813 +
19814 +       case FT_ID_RX_FIFO_DEPTH:
19815 +               retval = get_rxfifo_size(coreif, ctrl_req->wValue);
19816 +               if (retval >= 0) {
19817 +                       rxfifo = retval;
19818 +                       *((uint16_t *) buf) = rxfifo;
19819 +                       retval = sizeof(uint16_t);
19820 +               }
19821 +               break;
19822 +       }
19823 +
19824 +       return retval;
19825 +}
19826 +
19827 +/**
19828 + * This function resets the SG for the specified EP to its default value
19829 + */
19830 +static int cfi_reset_sg_val(cfi_ep_t * cfiep)
19831 +{
19832 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19833 +       return 0;
19834 +}
19835 +
19836 +/**
19837 + * This function resets the Alignment for the specified EP to its default value
19838 + */
19839 +static int cfi_reset_align_val(cfi_ep_t * cfiep)
19840 +{
19841 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19842 +       return 0;
19843 +}
19844 +
19845 +/**
19846 + * This function resets the Concatenation for the specified EP to its default value
19847 + * This function will also set the value of the wTxBytes field to NULL after 
19848 + * freeing the memory previously allocated for this field.
19849 + */
19850 +static int cfi_reset_concat_val(cfi_ep_t * cfiep)
19851 +{
19852 +       /* First we need to free the wTxBytes field */
19853 +       if (cfiep->bm_concat->wTxBytes) {
19854 +               DWC_FREE(cfiep->bm_concat->wTxBytes);
19855 +               cfiep->bm_concat->wTxBytes = NULL;
19856 +       }
19857 +
19858 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19859 +       return 0;
19860 +}
19861 +
19862 +/**
19863 + * This function resets all the buffer setups of the specified endpoint
19864 + */
19865 +static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
19866 +{
19867 +       cfi_reset_sg_val(cfiep);
19868 +       cfi_reset_align_val(cfiep);
19869 +       cfi_reset_concat_val(cfiep);
19870 +       return 0;
19871 +}
19872 +
19873 +static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
19874 +                                    uint8_t rx_rst, uint8_t tx_rst)
19875 +{
19876 +       int retval = -DWC_E_INVALID;
19877 +       uint16_t tx_siz[15];
19878 +       uint16_t rx_siz = 0;
19879 +       dwc_otg_pcd_ep_t *ep = NULL;
19880 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
19881 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
19882 +
19883 +       if (rx_rst) {
19884 +               rx_siz = params->dev_rx_fifo_size;
19885 +               params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
19886 +       }
19887 +
19888 +       if (tx_rst) {
19889 +               if (ep_addr == 0) {
19890 +                       int i;
19891 +
19892 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
19893 +                               tx_siz[i] =
19894 +                                   core_if->core_params->dev_tx_fifo_size[i];
19895 +                               core_if->core_params->dev_tx_fifo_size[i] =
19896 +                                   core_if->init_txfsiz[i];
19897 +                       }
19898 +               } else {
19899 +
19900 +                       ep = get_ep_by_addr(pcd, ep_addr);
19901 +
19902 +                       if (NULL == ep) {
19903 +                               CFI_INFO
19904 +                                   ("%s: Unable to get the endpoint addr=0x%02x\n",
19905 +                                    __func__, ep_addr);
19906 +                               return -DWC_E_INVALID;
19907 +                       }
19908 +
19909 +                       tx_siz[0] =
19910 +                           params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
19911 +                                                    1];
19912 +                       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
19913 +                           GET_CORE_IF(pcd)->init_txfsiz[ep->
19914 +                                                         dwc_ep.tx_fifo_num -
19915 +                                                         1];
19916 +               }
19917 +       }
19918 +
19919 +       if (resize_fifos(GET_CORE_IF(pcd))) {
19920 +               retval = 0;
19921 +       } else {
19922 +               CFI_INFO
19923 +                   ("%s: Error resetting the feature Reset All(FIFO size)\n",
19924 +                    __func__);
19925 +               if (rx_rst) {
19926 +                       params->dev_rx_fifo_size = rx_siz;
19927 +               }
19928 +
19929 +               if (tx_rst) {
19930 +                       if (ep_addr == 0) {
19931 +                               int i;
19932 +                               for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
19933 +                                    i++) {
19934 +                                       core_if->
19935 +                                           core_params->dev_tx_fifo_size[i] =
19936 +                                           tx_siz[i];
19937 +                               }
19938 +                       } else {
19939 +                               params->dev_tx_fifo_size[ep->
19940 +                                                        dwc_ep.tx_fifo_num -
19941 +                                                        1] = tx_siz[0];
19942 +                       }
19943 +               }
19944 +               retval = -DWC_E_INVALID;
19945 +       }
19946 +       return retval;
19947 +}
19948 +
19949 +static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
19950 +{
19951 +       int retval = 0;
19952 +       cfi_ep_t *cfiep;
19953 +       cfiobject_t *cfi = pcd->cfi;
19954 +       dwc_list_link_t *tmp;
19955 +
19956 +       retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
19957 +       if (retval < 0) {
19958 +               return retval;
19959 +       }
19960 +
19961 +       /* If the EP address is known then reset the features for only that EP */
19962 +       if (addr) {
19963 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19964 +               if (NULL == cfiep) {
19965 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19966 +                                __func__, addr);
19967 +                       return -DWC_E_INVALID;
19968 +               }
19969 +               retval = cfi_ep_reset_all_setup_vals(cfiep);
19970 +               cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19971 +       }
19972 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19973 +       else {
19974 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19975 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19976 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19977 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19978 +                       retval = cfi_ep_reset_all_setup_vals(cfiep);
19979 +                       cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19980 +                       if (retval < 0) {
19981 +                               CFI_INFO
19982 +                                   ("%s: Error resetting the feature Reset All\n",
19983 +                                    __func__);
19984 +                               return retval;
19985 +                       }
19986 +               }
19987 +       }
19988 +       return retval;
19989 +}
19990 +
19991 +static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
19992 +                                          uint8_t addr)
19993 +{
19994 +       int retval = 0;
19995 +       cfi_ep_t *cfiep;
19996 +       cfiobject_t *cfi = pcd->cfi;
19997 +       dwc_list_link_t *tmp;
19998 +
19999 +       /* If the EP address is known then reset the features for only that EP */
20000 +       if (addr) {
20001 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
20002 +               if (NULL == cfiep) {
20003 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
20004 +                                __func__, addr);
20005 +                       return -DWC_E_INVALID;
20006 +               }
20007 +               retval = cfi_reset_sg_val(cfiep);
20008 +       }
20009 +       /* Otherwise (wValue == 0), reset all features of all EP's */
20010 +       else {
20011 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
20012 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
20013 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20014 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20015 +                       retval = cfi_reset_sg_val(cfiep);
20016 +                       if (retval < 0) {
20017 +                               CFI_INFO
20018 +                                   ("%s: Error resetting the feature Buffer Setup\n",
20019 +                                    __func__);
20020 +                               return retval;
20021 +                       }
20022 +               }
20023 +       }
20024 +       return retval;
20025 +}
20026 +
20027 +static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
20028 +{
20029 +       int retval = 0;
20030 +       cfi_ep_t *cfiep;
20031 +       cfiobject_t *cfi = pcd->cfi;
20032 +       dwc_list_link_t *tmp;
20033 +
20034 +       /* If the EP address is known then reset the features for only that EP */
20035 +       if (addr) {
20036 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
20037 +               if (NULL == cfiep) {
20038 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
20039 +                                __func__, addr);
20040 +                       return -DWC_E_INVALID;
20041 +               }
20042 +               retval = cfi_reset_concat_val(cfiep);
20043 +       }
20044 +       /* Otherwise (wValue == 0), reset all features of all EP's */
20045 +       else {
20046 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
20047 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
20048 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20049 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20050 +                       retval = cfi_reset_concat_val(cfiep);
20051 +                       if (retval < 0) {
20052 +                               CFI_INFO
20053 +                                   ("%s: Error resetting the feature Concatenation Value\n",
20054 +                                    __func__);
20055 +                               return retval;
20056 +                       }
20057 +               }
20058 +       }
20059 +       return retval;
20060 +}
20061 +
20062 +static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
20063 +{
20064 +       int retval = 0;
20065 +       cfi_ep_t *cfiep;
20066 +       cfiobject_t *cfi = pcd->cfi;
20067 +       dwc_list_link_t *tmp;
20068 +
20069 +       /* If the EP address is known then reset the features for only that EP */
20070 +       if (addr) {
20071 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
20072 +               if (NULL == cfiep) {
20073 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
20074 +                                __func__, addr);
20075 +                       return -DWC_E_INVALID;
20076 +               }
20077 +               retval = cfi_reset_align_val(cfiep);
20078 +       }
20079 +       /* Otherwise (wValue == 0), reset all features of all EP's */
20080 +       else {
20081 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
20082 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
20083 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20084 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20085 +                       retval = cfi_reset_align_val(cfiep);
20086 +                       if (retval < 0) {
20087 +                               CFI_INFO
20088 +                                   ("%s: Error resetting the feature Aliignment Value\n",
20089 +                                    __func__);
20090 +                               return retval;
20091 +                       }
20092 +               }
20093 +       }
20094 +       return retval;
20095 +
20096 +}
20097 +
20098 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
20099 +                            struct cfi_usb_ctrlrequest *req)
20100 +{
20101 +       int retval = 0;
20102 +
20103 +       switch (req->wIndex) {
20104 +       case 0:
20105 +               /* Reset all features */
20106 +               retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
20107 +               break;
20108 +
20109 +       case FT_ID_DMA_BUFFER_SETUP:
20110 +               /* Reset the SG buffer setup */
20111 +               retval =
20112 +                   cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
20113 +               break;
20114 +
20115 +       case FT_ID_DMA_CONCAT_SETUP:
20116 +               /* Reset the Concatenation buffer setup */
20117 +               retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
20118 +               break;
20119 +
20120 +       case FT_ID_DMA_BUFF_ALIGN:
20121 +               /* Reset the Alignment buffer setup */
20122 +               retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
20123 +               break;
20124 +
20125 +       case FT_ID_TX_FIFO_DEPTH:
20126 +               retval =
20127 +                   cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
20128 +               pcd->cfi->need_gadget_att = 0;
20129 +               break;
20130 +
20131 +       case FT_ID_RX_FIFO_DEPTH:
20132 +               retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
20133 +               pcd->cfi->need_gadget_att = 0;
20134 +               break;
20135 +       default:
20136 +               break;
20137 +       }
20138 +       return retval;
20139 +}
20140 +
20141 +/**
20142 + * This function sets a new value for the SG buffer setup.
20143 + */
20144 +static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20145 +{
20146 +       uint8_t inaddr, outaddr;
20147 +       cfi_ep_t *epin, *epout;
20148 +       ddma_sg_buffer_setup_t *psgval;
20149 +       uint32_t desccount, size;
20150 +
20151 +       CFI_INFO("%s\n", __func__);
20152 +
20153 +       psgval = (ddma_sg_buffer_setup_t *) buf;
20154 +       desccount = (uint32_t) psgval->bCount;
20155 +       size = (uint32_t) psgval->wSize;
20156 +
20157 +       /* Check the DMA descriptor count */
20158 +       if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
20159 +               CFI_INFO
20160 +                   ("%s: The count of DMA Descriptors should be between 1 and %d\n",
20161 +                    __func__, MAX_DMA_DESCS_PER_EP);
20162 +               return -DWC_E_INVALID;
20163 +       }
20164 +
20165 +       /* Check the DMA descriptor count */
20166 +
20167 +       if (size == 0) {
20168 +
20169 +               CFI_INFO("%s: The transfer size should be at least 1 byte\n",
20170 +                        __func__);
20171 +
20172 +               return -DWC_E_INVALID;
20173 +
20174 +       }
20175 +
20176 +       inaddr = psgval->bInEndpointAddress;
20177 +       outaddr = psgval->bOutEndpointAddress;
20178 +
20179 +       epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
20180 +       epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
20181 +
20182 +       if (NULL == epin || NULL == epout) {
20183 +               CFI_INFO
20184 +                   ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
20185 +                    __func__, inaddr, outaddr);
20186 +               return -DWC_E_INVALID;
20187 +       }
20188 +
20189 +       epin->ep->dwc_ep.buff_mode = BM_SG;
20190 +       dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
20191 +
20192 +       epout->ep->dwc_ep.buff_mode = BM_SG;
20193 +       dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
20194 +
20195 +       return 0;
20196 +}
20197 +
20198 +/**
20199 + * This function sets a new value for the buffer Alignment setup.
20200 + */
20201 +static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20202 +{
20203 +       cfi_ep_t *ep;
20204 +       uint8_t addr;
20205 +       ddma_align_buffer_setup_t *palignval;
20206 +
20207 +       palignval = (ddma_align_buffer_setup_t *) buf;
20208 +       addr = palignval->bEndpointAddress;
20209 +
20210 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20211 +
20212 +       if (NULL == ep) {
20213 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20214 +                        __func__, addr);
20215 +               return -DWC_E_INVALID;
20216 +       }
20217 +
20218 +       ep->ep->dwc_ep.buff_mode = BM_ALIGN;
20219 +       dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
20220 +
20221 +       return 0;
20222 +}
20223 +
20224 +/**
20225 + * This function sets a new value for the Concatenation buffer setup.
20226 + */
20227 +static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20228 +{
20229 +       uint8_t addr;
20230 +       cfi_ep_t *ep;
20231 +       struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
20232 +       uint16_t *pVals;
20233 +       uint32_t desccount;
20234 +       int i;
20235 +       uint16_t mps;
20236 +
20237 +       pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
20238 +       desccount = (uint32_t) pConcatValHdr->bDescCount;
20239 +       pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
20240 +
20241 +       /* Check the DMA descriptor count */
20242 +       if (desccount > MAX_DMA_DESCS_PER_EP) {
20243 +               CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
20244 +                        __func__, MAX_DMA_DESCS_PER_EP);
20245 +               return -DWC_E_INVALID;
20246 +       }
20247 +
20248 +       addr = pConcatValHdr->bEndpointAddress;
20249 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20250 +       if (NULL == ep) {
20251 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20252 +                        __func__, addr);
20253 +               return -DWC_E_INVALID;
20254 +       }
20255 +
20256 +       mps = UGETW(ep->ep->desc->wMaxPacketSize);
20257 +
20258 +#if 0
20259 +       for (i = 0; i < desccount; i++) {
20260 +               CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
20261 +       }
20262 +       CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
20263 +#endif
20264 +
20265 +       /* Check the wTxSizes to be less than or equal to the mps */
20266 +       for (i = 0; i < desccount; i++) {
20267 +               if (pVals[i] > mps) {
20268 +                       CFI_INFO
20269 +                           ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
20270 +                            __func__, i, pVals[i]);
20271 +                       return -DWC_E_INVALID;
20272 +               }
20273 +       }
20274 +
20275 +       ep->ep->dwc_ep.buff_mode = BM_CONCAT;
20276 +       dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
20277 +
20278 +       /* Free the previously allocated storage for the wTxBytes */
20279 +       if (ep->bm_concat->wTxBytes) {
20280 +               DWC_FREE(ep->bm_concat->wTxBytes);
20281 +       }
20282 +
20283 +       /* Allocate a new storage for the wTxBytes field */
20284 +       ep->bm_concat->wTxBytes =
20285 +           DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);
20286 +       if (NULL == ep->bm_concat->wTxBytes) {
20287 +               CFI_INFO("%s: Unable to allocate memory\n", __func__);
20288 +               return -DWC_E_NO_MEMORY;
20289 +       }
20290 +
20291 +       /* Copy the new values into the wTxBytes filed */
20292 +       dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
20293 +                  sizeof(uint16_t) * pConcatValHdr->bDescCount);
20294 +
20295 +       return 0;
20296 +}
20297 +
20298 +/**
20299 + * This function calculates the total of all FIFO sizes
20300 + * 
20301 + * @param core_if Programming view of DWC_otg controller
20302 + *
20303 + * @return The total of data FIFO sizes.
20304 + *
20305 + */
20306 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
20307 +{
20308 +       dwc_otg_core_params_t *params = core_if->core_params;
20309 +       uint16_t dfifo_total = 0;
20310 +       int i;
20311 +
20312 +       /* The shared RxFIFO size */
20313 +       dfifo_total =
20314 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20315 +
20316 +       /* Add up each TxFIFO size to the total */
20317 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20318 +               dfifo_total += params->dev_tx_fifo_size[i];
20319 +       }
20320 +
20321 +       return dfifo_total;
20322 +}
20323 +
20324 +/**
20325 + * This function returns Rx FIFO size
20326 + * 
20327 + * @param core_if Programming view of DWC_otg controller
20328 + *
20329 + * @return The total of data FIFO sizes.
20330 + *
20331 + */
20332 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
20333 +{
20334 +       switch (wValue >> 8) {
20335 +       case 0:
20336 +               return (core_if->pwron_rxfsiz <
20337 +                       32768) ? core_if->pwron_rxfsiz : 32768;
20338 +               break;
20339 +       case 1:
20340 +               return core_if->core_params->dev_rx_fifo_size;
20341 +               break;
20342 +       default:
20343 +               return -DWC_E_INVALID;
20344 +               break;
20345 +       }
20346 +}
20347 +
20348 +/**
20349 + * This function returns Tx FIFO size for IN EP
20350 + * 
20351 + * @param core_if Programming view of DWC_otg controller
20352 + *
20353 + * @return The total of data FIFO sizes.
20354 + *
20355 + */
20356 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
20357 +{
20358 +       dwc_otg_pcd_ep_t *ep;
20359 +
20360 +       ep = get_ep_by_addr(pcd, wValue & 0xff);
20361 +
20362 +       if (NULL == ep) {
20363 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20364 +                        __func__, wValue & 0xff);
20365 +               return -DWC_E_INVALID;
20366 +       }
20367 +
20368 +       if (!ep->dwc_ep.is_in) {
20369 +               CFI_INFO
20370 +                   ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
20371 +                    __func__, wValue & 0xff);
20372 +               return -DWC_E_INVALID;
20373 +       }
20374 +
20375 +       switch (wValue >> 8) {
20376 +       case 0:
20377 +               return (GET_CORE_IF(pcd)->pwron_txfsiz
20378 +                       [ep->dwc_ep.tx_fifo_num - 1] <
20379 +                       768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->
20380 +                                                             dwc_ep.tx_fifo_num
20381 +                                                             - 1] : 32768;
20382 +               break;
20383 +       case 1:
20384 +               return GET_CORE_IF(pcd)->core_params->
20385 +                   dev_tx_fifo_size[ep->dwc_ep.num - 1];
20386 +               break;
20387 +       default:
20388 +               return -DWC_E_INVALID;
20389 +               break;
20390 +       }
20391 +}
20392 +
20393 +/**
20394 + * This function checks if the submitted combination of 
20395 + * device mode FIFO sizes is possible or not.
20396 + * 
20397 + * @param core_if Programming view of DWC_otg controller
20398 + *
20399 + * @return 1 if possible, 0 otherwise.
20400 + *
20401 + */
20402 +static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
20403 +{
20404 +       uint16_t dfifo_actual = 0;
20405 +       dwc_otg_core_params_t *params = core_if->core_params;
20406 +       uint16_t start_addr = 0;
20407 +       int i;
20408 +
20409 +       dfifo_actual =
20410 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20411 +
20412 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20413 +               dfifo_actual += params->dev_tx_fifo_size[i];
20414 +       }
20415 +
20416 +       if (dfifo_actual > core_if->total_fifo_size) {
20417 +               return 0;
20418 +       }
20419 +
20420 +       if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
20421 +               return 0;
20422 +
20423 +       if (params->dev_nperio_tx_fifo_size > 32768
20424 +           || params->dev_nperio_tx_fifo_size < 16)
20425 +               return 0;
20426 +
20427 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20428 +
20429 +               if (params->dev_tx_fifo_size[i] > 768
20430 +                   || params->dev_tx_fifo_size[i] < 4)
20431 +                       return 0;
20432 +       }
20433 +
20434 +       if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
20435 +               return 0;
20436 +       start_addr = params->dev_rx_fifo_size;
20437 +
20438 +       if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
20439 +               return 0;
20440 +       start_addr += params->dev_nperio_tx_fifo_size;
20441 +
20442 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20443 +
20444 +               if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
20445 +                       return 0;
20446 +               start_addr += params->dev_tx_fifo_size[i];
20447 +       }
20448 +
20449 +       return 1;
20450 +}
20451 +
20452 +/**
20453 + * This function resizes Device mode FIFOs
20454 + * 
20455 + * @param core_if Programming view of DWC_otg controller
20456 + *
20457 + * @return 1 if successful, 0 otherwise
20458 + *
20459 + */
20460 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
20461 +{
20462 +       int i = 0;
20463 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
20464 +       dwc_otg_core_params_t *params = core_if->core_params;
20465 +       uint32_t rx_fifo_size;
20466 +       fifosize_data_t nptxfifosize;
20467 +       fifosize_data_t txfifosize[15];
20468 +
20469 +       uint32_t rx_fsz_bak;
20470 +       uint32_t nptxfsz_bak;
20471 +       uint32_t txfsz_bak[15];
20472 +
20473 +       uint16_t start_address;
20474 +       uint8_t retval = 1;
20475 +
20476 +       if (!check_fifo_sizes(core_if)) {
20477 +               return 0;
20478 +       }
20479 +
20480 +       /* Configure data FIFO sizes */
20481 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
20482 +               rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);
20483 +               rx_fifo_size = params->dev_rx_fifo_size;
20484 +               DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
20485 +
20486 +               /*
20487 +                * Tx FIFOs These FIFOs are numbered from 1 to 15.
20488 +                * Indexes of the FIFO size module parameters in the
20489 +                * dev_tx_fifo_size array and the FIFO size registers in
20490 +                * the dtxfsiz array run from 0 to 14.
20491 +                */
20492 +
20493 +               /* Non-periodic Tx FIFO */
20494 +               nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
20495 +               nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
20496 +               start_address = params->dev_rx_fifo_size;
20497 +               nptxfifosize.b.startaddr = start_address;
20498 +
20499 +               DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
20500 +
20501 +               start_address += nptxfifosize.b.depth;
20502 +
20503 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20504 +                       txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);
20505 +
20506 +                       txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
20507 +                       txfifosize[i].b.startaddr = start_address;
20508 +                       DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20509 +                                       txfifosize[i].d32);
20510 +
20511 +                       start_address += txfifosize[i].b.depth;
20512 +               }
20513 +
20514 +               /** Check if register values are set correctly */
20515 +               if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {
20516 +                       retval = 0;
20517 +               }
20518 +
20519 +               if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {
20520 +                       retval = 0;
20521 +               }
20522 +
20523 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20524 +                       if (txfifosize[i].d32 !=
20525 +                           DWC_READ_REG32(&global_regs->dtxfsiz[i])) {
20526 +                               retval = 0;
20527 +                       }
20528 +               }
20529 +
20530 +               /** If register values are not set correctly, reset old values */
20531 +               if (retval == 0) {
20532 +                       DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);
20533 +
20534 +                       /* Non-periodic Tx FIFO */
20535 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);
20536 +
20537 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20538 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20539 +                                               txfsz_bak[i]);
20540 +                       }
20541 +               }
20542 +       } else {
20543 +               return 0;
20544 +       }
20545 +
20546 +       /* Flush the FIFOs */
20547 +       dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
20548 +       dwc_otg_flush_rx_fifo(core_if);
20549 +
20550 +       return retval;
20551 +}
20552 +
20553 +/**
20554 + * This function sets a new value for the buffer Alignment setup.
20555 + */
20556 +static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20557 +{
20558 +       int retval;
20559 +       uint32_t fsiz;
20560 +       uint16_t size;
20561 +       uint16_t ep_addr;
20562 +       dwc_otg_pcd_ep_t *ep;
20563 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20564 +       tx_fifo_size_setup_t *ptxfifoval;
20565 +
20566 +       ptxfifoval = (tx_fifo_size_setup_t *) buf;
20567 +       ep_addr = ptxfifoval->bEndpointAddress;
20568 +       size = ptxfifoval->wDepth;
20569 +
20570 +       ep = get_ep_by_addr(pcd, ep_addr);
20571 +
20572 +       CFI_INFO
20573 +           ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
20574 +            __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
20575 +
20576 +       if (NULL == ep) {
20577 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20578 +                        __func__, ep_addr);
20579 +               return -DWC_E_INVALID;
20580 +       }
20581 +
20582 +       fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
20583 +       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
20584 +
20585 +       if (resize_fifos(GET_CORE_IF(pcd))) {
20586 +               retval = 0;
20587 +       } else {
20588 +               CFI_INFO
20589 +                   ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
20590 +                    __func__, ep_addr);
20591 +               params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
20592 +               retval = -DWC_E_INVALID;
20593 +       }
20594 +
20595 +       return retval;
20596 +}
20597 +
20598 +/**
20599 + * This function sets a new value for the buffer Alignment setup.
20600 + */
20601 +static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20602 +{
20603 +       int retval;
20604 +       uint32_t fsiz;
20605 +       uint16_t size;
20606 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20607 +       rx_fifo_size_setup_t *prxfifoval;
20608 +
20609 +       prxfifoval = (rx_fifo_size_setup_t *) buf;
20610 +       size = prxfifoval->wDepth;
20611 +
20612 +       fsiz = params->dev_rx_fifo_size;
20613 +       params->dev_rx_fifo_size = size;
20614 +
20615 +       if (resize_fifos(GET_CORE_IF(pcd))) {
20616 +               retval = 0;
20617 +       } else {
20618 +               CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
20619 +                        __func__);
20620 +               params->dev_rx_fifo_size = fsiz;
20621 +               retval = -DWC_E_INVALID;
20622 +       }
20623 +
20624 +       return retval;
20625 +}
20626 +
20627 +/**
20628 + * This function reads the SG of an EP's buffer setup into the buffer buf
20629 + */
20630 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20631 +                            struct cfi_usb_ctrlrequest *req)
20632 +{
20633 +       int retval = -DWC_E_INVALID;
20634 +       uint8_t addr;
20635 +       cfi_ep_t *ep;
20636 +
20637 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20638 +       addr = req->wValue & 0xFF;
20639 +       if (addr == 0)          /* The address should be non-zero */
20640 +               return retval;
20641 +
20642 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20643 +       if (NULL == ep) {
20644 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20645 +                        __func__, addr);
20646 +               return retval;
20647 +       }
20648 +
20649 +       dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
20650 +       retval = BS_SG_VAL_DESC_LEN;
20651 +       return retval;
20652 +}
20653 +
20654 +/**
20655 + * This function reads the Concatenation value of an EP's buffer mode into 
20656 + * the buffer buf
20657 + */
20658 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20659 +                                struct cfi_usb_ctrlrequest *req)
20660 +{
20661 +       int retval = -DWC_E_INVALID;
20662 +       uint8_t addr;
20663 +       cfi_ep_t *ep;
20664 +       uint8_t desc_count;
20665 +
20666 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20667 +       addr = req->wValue & 0xFF;
20668 +       if (addr == 0)          /* The address should be non-zero */
20669 +               return retval;
20670 +
20671 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20672 +       if (NULL == ep) {
20673 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20674 +                        __func__, addr);
20675 +               return retval;
20676 +       }
20677 +
20678 +       /* Copy the header to the buffer */
20679 +       dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
20680 +       /* Advance the buffer pointer by the header size */
20681 +       buf += BS_CONCAT_VAL_HDR_LEN;
20682 +
20683 +       desc_count = ep->bm_concat->hdr.bDescCount;
20684 +       /* Copy alll the wTxBytes to the buffer */
20685 +       dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
20686 +
20687 +       retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
20688 +       return retval;
20689 +}
20690 +
20691 +/**
20692 + * This function reads the buffer Alignment value of an EP's buffer mode into 
20693 + * the buffer buf
20694 + *
20695 + * @return The total number of bytes copied to the buffer or negative error code.
20696 + */
20697 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20698 +                               struct cfi_usb_ctrlrequest *req)
20699 +{
20700 +       int retval = -DWC_E_INVALID;
20701 +       uint8_t addr;
20702 +       cfi_ep_t *ep;
20703 +
20704 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20705 +       addr = req->wValue & 0xFF;
20706 +       if (addr == 0)          /* The address should be non-zero */
20707 +               return retval;
20708 +
20709 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20710 +       if (NULL == ep) {
20711 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20712 +                        __func__, addr);
20713 +               return retval;
20714 +       }
20715 +
20716 +       dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
20717 +       retval = BS_ALIGN_VAL_HDR_LEN;
20718 +
20719 +       return retval;
20720 +}
20721 +
20722 +/**
20723 + * This function sets a new value for the specified feature
20724 + * 
20725 + * @param      pcd     A pointer to the PCD object
20726 + * 
20727 + * @return 0 if successful, negative error code otherwise to stall the DCE.
20728 + */
20729 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
20730 +{
20731 +       int retval = -DWC_E_NOT_SUPPORTED;
20732 +       uint16_t wIndex, wValue;
20733 +       uint8_t bRequest;
20734 +       struct dwc_otg_core_if *coreif;
20735 +       cfiobject_t *cfi = pcd->cfi;
20736 +       struct cfi_usb_ctrlrequest *ctrl_req;
20737 +       uint8_t *buf;
20738 +       ctrl_req = &cfi->ctrl_req;
20739 +
20740 +       buf = pcd->cfi->ctrl_req.data;
20741 +
20742 +       coreif = GET_CORE_IF(pcd);
20743 +       bRequest = ctrl_req->bRequest;
20744 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
20745 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
20746 +
20747 +       /* See which feature is to be modified */
20748 +       switch (wIndex) {
20749 +       case FT_ID_DMA_BUFFER_SETUP:
20750 +               /* Modify the feature */
20751 +               if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
20752 +                       return retval;
20753 +
20754 +               /* And send this request to the gadget */
20755 +               cfi->need_gadget_att = 1;
20756 +               break;
20757 +
20758 +       case FT_ID_DMA_BUFF_ALIGN:
20759 +               if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
20760 +                       return retval;
20761 +               cfi->need_gadget_att = 1;
20762 +               break;
20763 +
20764 +       case FT_ID_DMA_CONCAT_SETUP:
20765 +               /* Modify the feature */
20766 +               if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
20767 +                       return retval;
20768 +               cfi->need_gadget_att = 1;
20769 +               break;
20770 +
20771 +       case FT_ID_DMA_CIRCULAR:
20772 +               CFI_INFO("FT_ID_DMA_CIRCULAR\n");
20773 +               break;
20774 +
20775 +       case FT_ID_THRESHOLD_SETUP:
20776 +               CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
20777 +               break;
20778 +
20779 +       case FT_ID_DFIFO_DEPTH:
20780 +               CFI_INFO("FT_ID_DFIFO_DEPTH\n");
20781 +               break;
20782 +
20783 +       case FT_ID_TX_FIFO_DEPTH:
20784 +               CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
20785 +               if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
20786 +                       return retval;
20787 +               cfi->need_gadget_att = 0;
20788 +               break;
20789 +
20790 +       case FT_ID_RX_FIFO_DEPTH:
20791 +               CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
20792 +               if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
20793 +                       return retval;
20794 +               cfi->need_gadget_att = 0;
20795 +               break;
20796 +       }
20797 +
20798 +       return retval;
20799 +}
20800 +
20801 +#endif //DWC_UTE_CFI
20802 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.h b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
20803 new file mode 100644
20804 index 0000000..cbccdab
20805 --- /dev/null
20806 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
20807 @@ -0,0 +1,320 @@
20808 +/* ==========================================================================
20809 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
20810 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
20811 + * otherwise expressly agreed to in writing between Synopsys and you.
20812 + *
20813 + * The Software IS NOT an item of Licensed Software or Licensed Product under
20814 + * any End User Software License Agreement or Agreement for Licensed Product
20815 + * with Synopsys or any supplement thereto. You are permitted to use and
20816 + * redistribute this Software in source and binary forms, with or without
20817 + * modification, provided that redistributions of source code must retain this
20818 + * notice. You may not view, use, disclose, copy or distribute this file or
20819 + * any information contained herein except pursuant to this license grant from
20820 + * Synopsys. If you do not agree with this notice, including the disclaimer
20821 + * below, then you are not authorized to use the Software.
20822 + *
20823 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
20824 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20825 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20826 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
20827 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20828 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20829 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20830 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20831 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20832 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20833 + * DAMAGE.
20834 + * ========================================================================== */
20835 +
20836 +#if !defined(__DWC_OTG_CFI_H__)
20837 +#define __DWC_OTG_CFI_H__
20838 +
20839 +#include "dwc_otg_pcd.h"
20840 +#include "dwc_cfi_common.h"
20841 +
20842 +/**
20843 + * @file
20844 + * This file contains the CFI related OTG PCD specific common constants, 
20845 + * interfaces(functions and macros) and data structures.The CFI Protocol is an 
20846 + * optional interface for internal testing purposes that a DUT may implement to 
20847 + * support testing of configurable features.
20848 + *
20849 + */
20850 +
20851 +struct dwc_otg_pcd;
20852 +struct dwc_otg_pcd_ep;
20853 +
20854 +/** OTG CFI Features (properties) ID constants */
20855 +/** This is a request for all Core Features */
20856 +#define FT_ID_DMA_MODE                                 0x0001
20857 +#define FT_ID_DMA_BUFFER_SETUP                 0x0002
20858 +#define FT_ID_DMA_BUFF_ALIGN                   0x0003
20859 +#define FT_ID_DMA_CONCAT_SETUP                 0x0004
20860 +#define FT_ID_DMA_CIRCULAR                             0x0005
20861 +#define FT_ID_THRESHOLD_SETUP                  0x0006
20862 +#define FT_ID_DFIFO_DEPTH                              0x0007
20863 +#define FT_ID_TX_FIFO_DEPTH                            0x0008
20864 +#define FT_ID_RX_FIFO_DEPTH                            0x0009
20865 +
20866 +/**********************************************************/
20867 +#define CFI_INFO_DEF
20868 +
20869 +#ifdef CFI_INFO_DEF
20870 +#define CFI_INFO(fmt...)       DWC_PRINTF("CFI: " fmt);
20871 +#else
20872 +#define CFI_INFO(fmt...)
20873 +#endif
20874 +
20875 +#define min(x,y) ({ \
20876 +       x < y ? x : y; })
20877 +
20878 +#define max(x,y) ({ \
20879 +       x > y ? x : y; })
20880 +
20881 +/**
20882 + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is
20883 + * also used for setting up a buffer for Circular DDMA.
20884 + */
20885 +struct _ddma_sg_buffer_setup {
20886 +#define BS_SG_VAL_DESC_LEN     6
20887 +       /* The OUT EP address */
20888 +       uint8_t bOutEndpointAddress;
20889 +       /* The IN EP address */
20890 +       uint8_t bInEndpointAddress;
20891 +       /* Number of bytes to put between transfer segments (must be DWORD boundaries) */
20892 +       uint8_t bOffset;
20893 +       /* The number of transfer segments (a DMA descriptors per each segment) */
20894 +       uint8_t bCount;
20895 +       /* Size (in byte) of each transfer segment */
20896 +       uint16_t wSize;
20897 +} __attribute__ ((packed));
20898 +typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t;
20899 +
20900 +/** Descriptor DMA Concatenation Buffer setup structure */
20901 +struct _ddma_concat_buffer_setup_hdr {
20902 +#define BS_CONCAT_VAL_HDR_LEN  4
20903 +       /* The endpoint for which the buffer is to be set up */
20904 +       uint8_t bEndpointAddress;
20905 +       /* The count of descriptors to be used */
20906 +       uint8_t bDescCount;
20907 +       /* The total size of the transfer */
20908 +       uint16_t wSize;
20909 +} __attribute__ ((packed));
20910 +typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t;
20911 +
20912 +/** Descriptor DMA Concatenation Buffer setup structure */
20913 +struct _ddma_concat_buffer_setup {
20914 +       /* The SG header */
20915 +       ddma_concat_buffer_setup_hdr_t hdr;
20916 +
20917 +       /* The XFER sizes pointer (allocated dynamically) */
20918 +       uint16_t *wTxBytes;
20919 +} __attribute__ ((packed));
20920 +typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t;
20921 +
20922 +/** Descriptor DMA Alignment Buffer setup structure */
20923 +struct _ddma_align_buffer_setup {
20924 +#define BS_ALIGN_VAL_HDR_LEN   2
20925 +       uint8_t bEndpointAddress;
20926 +       uint8_t bAlign;
20927 +} __attribute__ ((packed));
20928 +typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t;
20929 +
20930 +/** Transmit FIFO Size setup structure */
20931 +struct _tx_fifo_size_setup {
20932 +       uint8_t bEndpointAddress;
20933 +       uint16_t wDepth;
20934 +} __attribute__ ((packed));
20935 +typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t;
20936 +
20937 +/** Transmit FIFO Size setup structure */
20938 +struct _rx_fifo_size_setup {
20939 +       uint16_t wDepth;
20940 +} __attribute__ ((packed));
20941 +typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t;
20942 +
20943 +/**
20944 + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest
20945 + * This structure encapsulates the standard usb_ctrlrequest and adds a pointer
20946 + * to the data returned in the data stage of a 3-stage Control Write requests.
20947 + */
20948 +struct cfi_usb_ctrlrequest {
20949 +       uint8_t bRequestType;
20950 +       uint8_t bRequest;
20951 +       uint16_t wValue;
20952 +       uint16_t wIndex;
20953 +       uint16_t wLength;
20954 +       uint8_t *data;
20955 +} UPACKED;
20956 +
20957 +/*---------------------------------------------------------------------------*/
20958 +
20959 +/**
20960 + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures.
20961 + * This structure is used to store the buffer setup data for any
20962 + * enabled endpoint in the PCD.
20963 + */
20964 +struct cfi_ep {
20965 +       /* Entry for the list container */
20966 +       dwc_list_link_t lh;
20967 +       /* Pointer to the active PCD endpoint structure */
20968 +       struct dwc_otg_pcd_ep *ep;
20969 +       /* The last descriptor in the chain of DMA descriptors of the endpoint */
20970 +       struct dwc_otg_dma_desc *dma_desc_last;
20971 +       /* The SG feature value */
20972 +       ddma_sg_buffer_setup_t *bm_sg;
20973 +       /* The Circular feature value */
20974 +       ddma_sg_buffer_setup_t *bm_circ;
20975 +       /* The Concatenation feature value */
20976 +       ddma_concat_buffer_setup_t *bm_concat;
20977 +       /* The Alignment feature value */
20978 +       ddma_align_buffer_setup_t *bm_align;
20979 +       /* XFER length */
20980 +       uint32_t xfer_len;
20981 +       /*
20982 +        * Count of DMA descriptors currently used.
20983 +        * The total should not exceed the MAX_DMA_DESCS_PER_EP value
20984 +        * defined in the dwc_otg_cil.h
20985 +        */
20986 +       uint32_t desc_count;
20987 +};
20988 +typedef struct cfi_ep cfi_ep_t;
20989 +
20990 +typedef struct cfi_dma_buff {
20991 +#define CFI_IN_BUF_LEN 1024
20992 +#define CFI_OUT_BUF_LEN        1024
20993 +       dma_addr_t addr;
20994 +       uint8_t *buf;
20995 +} cfi_dma_buff_t;
20996 +
20997 +struct cfiobject;
20998 +
20999 +/**
21000 + * This is the interface for the CFI operations.
21001 + *
21002 + * @param      ep_enable                       Called when any endpoint is enabled and activated.
21003 + * @param      release                         Called when the CFI object is released and it needs to correctly
21004 + *                                                             deallocate the dynamic memory
21005 + * @param      ctrl_write_complete     Called when the data stage of the request is complete
21006 + */
21007 +typedef struct cfi_ops {
21008 +       int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
21009 +                         struct dwc_otg_pcd_ep * ep);
21010 +       void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
21011 +                              struct dwc_otg_pcd_ep * ep, dma_addr_t * dma,
21012 +                              unsigned size, gfp_t flags);
21013 +       void (*release) (struct cfiobject * cfi);
21014 +       int (*ctrl_write_complete) (struct cfiobject * cfi,
21015 +                                   struct dwc_otg_pcd * pcd);
21016 +       void (*build_descriptors) (struct cfiobject * cfi,
21017 +                                  struct dwc_otg_pcd * pcd,
21018 +                                  struct dwc_otg_pcd_ep * ep,
21019 +                                  dwc_otg_pcd_request_t * req);
21020 +} cfi_ops_t;
21021 +
21022 +struct cfiobject {
21023 +       cfi_ops_t ops;
21024 +       struct dwc_otg_pcd *pcd;
21025 +       struct usb_gadget *gadget;
21026 +
21027 +       /* Buffers used to send/receive CFI-related request data */
21028 +       cfi_dma_buff_t buf_in;
21029 +       cfi_dma_buff_t buf_out;
21030 +
21031 +       /* CFI specific Control request wrapper */
21032 +       struct cfi_usb_ctrlrequest ctrl_req;
21033 +
21034 +       /* The list of active EP's in the PCD of type cfi_ep_t */
21035 +       dwc_list_link_t active_eps;
21036 +
21037 +       /* This flag shall control the propagation of a specific request
21038 +        * to the gadget's processing routines.
21039 +        * 0 - no gadget handling
21040 +        * 1 - the gadget needs to know about this request (w/o completing a status
21041 +        * phase - just return a 0 to the _setup callback)
21042 +        */
21043 +       uint8_t need_gadget_att;
21044 +
21045 +       /* Flag indicating whether the status IN phase needs to be
21046 +        * completed by the PCD
21047 +        */
21048 +       uint8_t need_status_in_complete;
21049 +};
21050 +typedef struct cfiobject cfiobject_t;
21051 +
21052 +#define DUMP_MSG
21053 +
21054 +#if defined(DUMP_MSG)
21055 +static inline void dump_msg(const u8 * buf, unsigned int length)
21056 +{
21057 +       unsigned int start, num, i;
21058 +       char line[52], *p;
21059 +
21060 +       if (length >= 512)
21061 +               return;
21062 +
21063 +       start = 0;
21064 +       while (length > 0) {
21065 +               num = min(length, 16u);
21066 +               p = line;
21067 +               for (i = 0; i < num; ++i) {
21068 +                       if (i == 8)
21069 +                               *p++ = ' ';
21070 +                       DWC_SPRINTF(p, " %02x", buf[i]);
21071 +                       p += 3;
21072 +               }
21073 +               *p = 0;
21074 +               DWC_DEBUG("%6x: %s\n", start, line);
21075 +               buf += num;
21076 +               start += num;
21077 +               length -= num;
21078 +       }
21079 +}
21080 +#else
21081 +static inline void dump_msg(const u8 * buf, unsigned int length)
21082 +{
21083 +}
21084 +#endif
21085 +
21086 +/**
21087 + * This function returns a pointer to cfi_ep_t object with the addr address.
21088 + */
21089 +static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi,
21090 +                                               uint8_t addr)
21091 +{
21092 +       struct cfi_ep *pcfiep;
21093 +       dwc_list_link_t *tmp;
21094 +
21095 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
21096 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
21097 +
21098 +               if (pcfiep->ep->desc->bEndpointAddress == addr) {
21099 +                       return pcfiep;
21100 +               }
21101 +       }
21102 +
21103 +       return NULL;
21104 +}
21105 +
21106 +/**
21107 + * This function returns a pointer to cfi_ep_t object that matches
21108 + * the dwc_otg_pcd_ep object.
21109 + */
21110 +static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi,
21111 +                                                 struct dwc_otg_pcd_ep *ep)
21112 +{
21113 +       struct cfi_ep *pcfiep = NULL;
21114 +       dwc_list_link_t *tmp;
21115 +
21116 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
21117 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
21118 +               if (pcfiep->ep == ep) {
21119 +                       return pcfiep;
21120 +               }
21121 +       }
21122 +       return NULL;
21123 +}
21124 +
21125 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
21126 +
21127 +#endif /* (__DWC_OTG_CFI_H__) */
21128 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
21129 new file mode 100644
21130 index 0000000..9b67537
21131 --- /dev/null
21132 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
21133 @@ -0,0 +1,7151 @@
21134 +/* ==========================================================================
21135 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
21136 + * $Revision: #191 $
21137 + * $Date: 2012/08/10 $
21138 + * $Change: 2047372 $
21139 + *
21140 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
21141 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
21142 + * otherwise expressly agreed to in writing between Synopsys and you.
21143 + *
21144 + * The Software IS NOT an item of Licensed Software or Licensed Product under
21145 + * any End User Software License Agreement or Agreement for Licensed Product
21146 + * with Synopsys or any supplement thereto. You are permitted to use and
21147 + * redistribute this Software in source and binary forms, with or without
21148 + * modification, provided that redistributions of source code must retain this
21149 + * notice. You may not view, use, disclose, copy or distribute this file or
21150 + * any information contained herein except pursuant to this license grant from
21151 + * Synopsys. If you do not agree with this notice, including the disclaimer
21152 + * below, then you are not authorized to use the Software.
21153 + *
21154 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
21155 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21156 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21157 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
21158 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21159 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21160 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21161 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21162 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21163 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
21164 + * DAMAGE.
21165 + * ========================================================================== */
21166 +
21167 +/** @file
21168 + *
21169 + * The Core Interface Layer provides basic services for accessing and
21170 + * managing the DWC_otg hardware. These services are used by both the
21171 + * Host Controller Driver and the Peripheral Controller Driver.
21172 + *
21173 + * The CIL manages the memory map for the core so that the HCD and PCD
21174 + * don't have to do this separately. It also handles basic tasks like
21175 + * reading/writing the registers and data FIFOs in the controller.
21176 + * Some of the data access functions provide encapsulation of several
21177 + * operations required to perform a task, such as writing multiple
21178 + * registers to start a transfer. Finally, the CIL performs basic
21179 + * services that are not specific to either the host or device modes
21180 + * of operation. These services include management of the OTG Host
21181 + * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
21182 + * Diagnostic API is also provided to allow testing of the controller
21183 + * hardware.
21184 + *
21185 + * The Core Interface Layer has the following requirements:
21186 + * - Provides basic controller operations.
21187 + * - Minimal use of OS services. 
21188 + * - The OS services used will be abstracted by using inline functions
21189 + *      or macros.
21190 + *
21191 + */
21192 +
21193 +#include "dwc_os.h"
21194 +#include "dwc_otg_regs.h"
21195 +#include "dwc_otg_cil.h"
21196 +
21197 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
21198 +
21199 +/**
21200 + * This function is called to initialize the DWC_otg CSR data
21201 + * structures. The register addresses in the device and host
21202 + * structures are initialized from the base address supplied by the
21203 + * caller. The calling function must make the OS calls to get the
21204 + * base address of the DWC_otg controller registers. The core_params
21205 + * argument holds the parameters that specify how the core should be
21206 + * configured.
21207 + *
21208 + * @param reg_base_addr Base address of DWC_otg core registers
21209 + *
21210 + */
21211 +dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
21212 +{
21213 +       dwc_otg_core_if_t *core_if = 0;
21214 +       dwc_otg_dev_if_t *dev_if = 0;
21215 +       dwc_otg_host_if_t *host_if = 0;
21216 +       uint8_t *reg_base = (uint8_t *) reg_base_addr;
21217 +       int i = 0;
21218 +
21219 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr);
21220 +
21221 +       core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t));
21222 +
21223 +       if (core_if == NULL) {
21224 +               DWC_DEBUGPL(DBG_CIL,
21225 +                           "Allocation of dwc_otg_core_if_t failed\n");
21226 +               return 0;
21227 +       }
21228 +       core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
21229 +
21230 +       /*
21231 +        * Allocate the Device Mode structures.
21232 +        */
21233 +       dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t));
21234 +
21235 +       if (dev_if == NULL) {
21236 +               DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");
21237 +               DWC_FREE(core_if);
21238 +               return 0;
21239 +       }
21240 +
21241 +       dev_if->dev_global_regs =
21242 +           (dwc_otg_device_global_regs_t *) (reg_base +
21243 +                                             DWC_DEV_GLOBAL_REG_OFFSET);
21244 +
21245 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21246 +               dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
21247 +                   (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
21248 +                    (i * DWC_EP_REG_OFFSET));
21249 +
21250 +               dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
21251 +                   (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
21252 +                    (i * DWC_EP_REG_OFFSET));
21253 +               DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",
21254 +                           i, &dev_if->in_ep_regs[i]->diepctl);
21255 +               DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",
21256 +                           i, &dev_if->out_ep_regs[i]->doepctl);
21257 +       }
21258 +
21259 +       dev_if->speed = 0;      // unknown
21260 +
21261 +       core_if->dev_if = dev_if;
21262 +
21263 +       /*
21264 +        * Allocate the Host Mode structures.
21265 +        */
21266 +       host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t));
21267 +
21268 +       if (host_if == NULL) {
21269 +               DWC_DEBUGPL(DBG_CIL,
21270 +                           "Allocation of dwc_otg_host_if_t failed\n");
21271 +               DWC_FREE(dev_if);
21272 +               DWC_FREE(core_if);
21273 +               return 0;
21274 +       }
21275 +
21276 +       host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
21277 +           (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
21278 +
21279 +       host_if->hprt0 =
21280 +           (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
21281 +
21282 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21283 +               host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
21284 +                   (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
21285 +                    (i * DWC_OTG_CHAN_REGS_OFFSET));
21286 +               DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
21287 +                           i, &host_if->hc_regs[i]->hcchar);
21288 +       }
21289 +
21290 +       host_if->num_host_channels = MAX_EPS_CHANNELS;
21291 +       core_if->host_if = host_if;
21292 +
21293 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21294 +               core_if->data_fifo[i] =
21295 +                   (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
21296 +                                 (i * DWC_OTG_DATA_FIFO_SIZE));
21297 +               DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n",
21298 +                           i, (unsigned long)core_if->data_fifo[i]);
21299 +       }
21300 +
21301 +       core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
21302 +
21303 +       /* Initiate lx_state to L3 disconnected state */
21304 +       core_if->lx_state = DWC_OTG_L3;
21305 +       /*
21306 +        * Store the contents of the hardware configuration registers here for
21307 +        * easy access later.
21308 +        */
21309 +       core_if->hwcfg1.d32 =
21310 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
21311 +       core_if->hwcfg2.d32 =
21312 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
21313 +       core_if->hwcfg3.d32 =
21314 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
21315 +       core_if->hwcfg4.d32 =
21316 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
21317 +
21318 +       /* Force host mode to get HPTXFSIZ exact power on value */
21319 +       {
21320 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
21321 +               gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21322 +               gusbcfg.b.force_host_mode = 1;
21323 +               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21324 +               dwc_mdelay(100); 
21325 +               core_if->hptxfsiz.d32 =
21326 +               DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21327 +               gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21328 +               gusbcfg.b.force_host_mode = 0;
21329 +               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21330 +               dwc_mdelay(100); 
21331 +       }
21332 +
21333 +       DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
21334 +       DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);
21335 +       DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);
21336 +       DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);
21337 +
21338 +       core_if->hcfg.d32 =
21339 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21340 +       core_if->dcfg.d32 =
21341 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21342 +
21343 +       DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32);
21344 +       DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32);
21345 +
21346 +       DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
21347 +       DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);
21348 +       DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
21349 +       DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",
21350 +                   core_if->hwcfg2.b.num_host_chan);
21351 +       DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",
21352 +                   core_if->hwcfg2.b.nonperio_tx_q_depth);
21353 +       DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",
21354 +                   core_if->hwcfg2.b.host_perio_tx_q_depth);
21355 +       DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",
21356 +                   core_if->hwcfg2.b.dev_token_q_depth);
21357 +
21358 +       DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",
21359 +                   core_if->hwcfg3.b.dfifo_depth);
21360 +       DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",
21361 +                   core_if->hwcfg3.b.xfer_size_cntr_width);
21362 +
21363 +       /*
21364 +        * Set the SRP sucess bit for FS-I2c
21365 +        */
21366 +       core_if->srp_success = 0;
21367 +       core_if->srp_timer_started = 0;
21368 +
21369 +       /*
21370 +        * Create new workqueue and init works
21371 +        */
21372 +       core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg");
21373 +       if (core_if->wq_otg == 0) {
21374 +               DWC_WARN("DWC_WORKQ_ALLOC failed\n");
21375 +               DWC_FREE(host_if);
21376 +               DWC_FREE(dev_if);
21377 +               DWC_FREE(core_if);
21378 +               return 0;
21379 +       }
21380 +
21381 +       core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);
21382 +
21383 +       DWC_PRINTF("Core Release: %x.%x%x%x\n",
21384 +                  (core_if->snpsid >> 12 & 0xF),
21385 +                  (core_if->snpsid >> 8 & 0xF),
21386 +                  (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
21387 +
21388 +       core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer",
21389 +                                            w_wakeup_detected, core_if);
21390 +       if (core_if->wkp_timer == 0) {
21391 +               DWC_WARN("DWC_TIMER_ALLOC failed\n");
21392 +               DWC_FREE(host_if);
21393 +               DWC_FREE(dev_if);
21394 +               DWC_WORKQ_FREE(core_if->wq_otg);
21395 +               DWC_FREE(core_if);
21396 +               return 0;
21397 +       }
21398 +
21399 +       if (dwc_otg_setup_params(core_if)) {
21400 +               DWC_WARN("Error while setting core params\n");
21401 +       }
21402 +
21403 +       core_if->hibernation_suspend = 0;
21404 +
21405 +       /** ADP initialization */
21406 +       dwc_otg_adp_init(core_if);
21407 +       
21408 +       return core_if;
21409 +}
21410 +
21411 +/**
21412 + * This function frees the structures allocated by dwc_otg_cil_init().
21413 + *
21414 + * @param core_if The core interface pointer returned from
21415 + *               dwc_otg_cil_init().
21416 + *
21417 + */
21418 +void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if)
21419 +{
21420 +       dctl_data_t dctl = {.d32 = 0 };
21421 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
21422 +
21423 +       /* Disable all interrupts */
21424 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0);
21425 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
21426 +
21427 +       dctl.b.sftdiscon = 1;
21428 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
21429 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0,
21430 +                                dctl.d32);
21431 +       }
21432 +
21433 +       if (core_if->wq_otg) {
21434 +               DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500);
21435 +               DWC_WORKQ_FREE(core_if->wq_otg);
21436 +       }
21437 +       if (core_if->dev_if) {
21438 +               DWC_FREE(core_if->dev_if);
21439 +       }
21440 +       if (core_if->host_if) {
21441 +               DWC_FREE(core_if->host_if);
21442 +       }
21443 +
21444 +       /** Remove ADP Stuff  */
21445 +       dwc_otg_adp_remove(core_if);
21446 +       if (core_if->core_params) {
21447 +               DWC_FREE(core_if->core_params);
21448 +       }
21449 +       if (core_if->wkp_timer) {
21450 +               DWC_TIMER_FREE(core_if->wkp_timer);
21451 +       }
21452 +       if (core_if->srp_timer) {
21453 +               DWC_TIMER_FREE(core_if->srp_timer);
21454 +       }
21455 +       DWC_FREE(core_if);
21456 +}
21457 +
21458 +/**
21459 + * This function enables the controller's Global Interrupt in the AHB Config
21460 + * register.
21461 + *
21462 + * @param core_if Programming view of DWC_otg controller.
21463 + */
21464 +void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if)
21465 +{
21466 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
21467 +       ahbcfg.b.glblintrmsk = 1;       /* Enable interrupts */
21468 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
21469 +}
21470 +
21471 +/**
21472 + * This function disables the controller's Global Interrupt in the AHB Config
21473 + * register.
21474 + *
21475 + * @param core_if Programming view of DWC_otg controller.
21476 + */
21477 +void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if)
21478 +{
21479 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
21480 +       ahbcfg.b.glblintrmsk = 1;       /* Disable interrupts */
21481 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
21482 +}
21483 +
21484 +/**
21485 + * This function initializes the commmon interrupts, used in both
21486 + * device and host modes.
21487 + *
21488 + * @param core_if Programming view of the DWC_otg controller
21489 + *
21490 + */
21491 +static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if)
21492 +{
21493 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
21494 +       gintmsk_data_t intr_mask = {.d32 = 0 };
21495 +
21496 +       /* Clear any pending OTG Interrupts */
21497 +       DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF);
21498 +
21499 +       /* Clear any pending interrupts */
21500 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
21501 +
21502 +       /*
21503 +        * Enable the interrupts in the GINTMSK.
21504 +        */
21505 +       intr_mask.b.modemismatch = 1;
21506 +       intr_mask.b.otgintr = 1;
21507 +
21508 +       if (!core_if->dma_enable) {
21509 +               intr_mask.b.rxstsqlvl = 1;
21510 +       }
21511 +
21512 +       intr_mask.b.conidstschng = 1;
21513 +       intr_mask.b.wkupintr = 1;
21514 +       intr_mask.b.disconnect = 0;
21515 +       intr_mask.b.usbsuspend = 1;
21516 +       intr_mask.b.sessreqintr = 1;
21517 +#ifdef CONFIG_USB_DWC_OTG_LPM
21518 +       if (core_if->core_params->lpm_enable) {
21519 +               intr_mask.b.lpmtranrcvd = 1;
21520 +       }
21521 +#endif
21522 +       DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
21523 +}
21524 +
21525 +/*
21526 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21527 + * Hibernation. This function is for exiting from Device mode hibernation by
21528 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21529 + * @param core_if Programming view of DWC_otg controller.
21530 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21531 + * @param reset - indicates whether resume is initiated by Reset.
21532 + */
21533 +int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
21534 +                                      int rem_wakeup, int reset)
21535 +{
21536 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
21537 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
21538 +       dctl_data_t dctl = {.d32 = 0 };
21539 +
21540 +       int timeout = 2000;
21541 +
21542 +       if (!core_if->hibernation_suspend) {
21543 +               DWC_PRINTF("Already exited from Hibernation\n");
21544 +               return 1;
21545 +       }
21546 +
21547 +       DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__);
21548 +       /* Switch-on voltage to the core */
21549 +       gpwrdn.b.pwrdnswtch = 1;
21550 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21551 +       dwc_udelay(10);
21552 +
21553 +       /* Reset core */
21554 +       gpwrdn.d32 = 0;
21555 +       gpwrdn.b.pwrdnrstn = 1;
21556 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21557 +       dwc_udelay(10);
21558 +
21559 +       /* Assert Restore signal */
21560 +       gpwrdn.d32 = 0;
21561 +       gpwrdn.b.restore = 1;
21562 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21563 +       dwc_udelay(10);
21564 +
21565 +       /* Disable power clamps */
21566 +       gpwrdn.d32 = 0;
21567 +       gpwrdn.b.pwrdnclmp = 1;
21568 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21569 +
21570 +       if (rem_wakeup) {
21571 +               dwc_udelay(70);
21572 +       }
21573 +
21574 +       /* Deassert Reset core */
21575 +       gpwrdn.d32 = 0;
21576 +       gpwrdn.b.pwrdnrstn = 1;
21577 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21578 +       dwc_udelay(10);
21579 +
21580 +       /* Disable PMU interrupt */
21581 +       gpwrdn.d32 = 0;
21582 +       gpwrdn.b.pmuintsel = 1;
21583 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21584 +
21585 +       /* Mask interrupts from gpwrdn */
21586 +       gpwrdn.d32 = 0;
21587 +       gpwrdn.b.connect_det_msk = 1;
21588 +       gpwrdn.b.srp_det_msk = 1;
21589 +       gpwrdn.b.disconn_det_msk = 1;
21590 +       gpwrdn.b.rst_det_msk = 1;
21591 +       gpwrdn.b.lnstchng_msk = 1;
21592 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21593 +
21594 +       /* Indicates that we are going out from hibernation */
21595 +       core_if->hibernation_suspend = 0;
21596 +
21597 +       /*
21598 +        * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1
21599 +        * indicates restore from remote_wakeup
21600 +        */
21601 +       restore_essential_regs(core_if, rem_wakeup, 0);
21602 +
21603 +       /*
21604 +        * Wait a little for seeing new value of variable hibernation_suspend if
21605 +        * Restore done interrupt received before polling
21606 +        */
21607 +       dwc_udelay(10);
21608 +
21609 +       if (core_if->hibernation_suspend == 0) {
21610 +               /*
21611 +                * Wait For Restore_done Interrupt. This mechanism of polling the 
21612 +                * interrupt is introduced to avoid any possible race conditions
21613 +                */
21614 +               do {
21615 +                       gintsts_data_t gintsts;
21616 +                       gintsts.d32 =
21617 +                           DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21618 +                       if (gintsts.b.restoredone) {
21619 +                               gintsts.d32 = 0;
21620 +                               gintsts.b.restoredone = 1;
21621 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
21622 +                                               gintsts, gintsts.d32);
21623 +                               DWC_PRINTF("Restore Done Interrupt seen\n");
21624 +                               break;
21625 +                       }
21626 +                       dwc_udelay(10);
21627 +               } while (--timeout);
21628 +               if (!timeout) {
21629 +                       DWC_PRINTF("Restore Done interrupt wasn't generated here\n");
21630 +               }
21631 +       }
21632 +       /* Clear all pending interupts */
21633 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21634 +
21635 +       /* De-assert Restore */
21636 +       gpwrdn.d32 = 0;
21637 +       gpwrdn.b.restore = 1;
21638 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21639 +       dwc_udelay(10);
21640 +
21641 +       if (!rem_wakeup) {
21642 +               pcgcctl.d32 = 0;
21643 +               pcgcctl.b.rstpdwnmodule = 1;
21644 +               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
21645 +       }
21646 +
21647 +       /* Restore GUSBCFG and DCFG */
21648 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21649 +                       core_if->gr_backup->gusbcfg_local);
21650 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
21651 +                       core_if->dr_backup->dcfg);
21652 +
21653 +       /* De-assert Wakeup Logic */
21654 +       gpwrdn.d32 = 0;
21655 +       gpwrdn.b.pmuactv = 1;
21656 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21657 +       dwc_udelay(10);
21658 +
21659 +       if (!rem_wakeup) {
21660 +               /* Set Device programming done bit */
21661 +               dctl.b.pwronprgdone = 1;
21662 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
21663 +       } else {
21664 +               /* Start Remote Wakeup Signaling */
21665 +               dctl.d32 = core_if->dr_backup->dctl;
21666 +               dctl.b.rmtwkupsig = 1;
21667 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
21668 +       }
21669 +
21670 +       dwc_mdelay(2);
21671 +       /* Clear all pending interupts */
21672 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21673 +
21674 +       /* Restore global registers */
21675 +       dwc_otg_restore_global_regs(core_if);
21676 +       /* Restore device global registers */
21677 +       dwc_otg_restore_dev_regs(core_if, rem_wakeup);
21678 +
21679 +       if (rem_wakeup) {
21680 +               dwc_mdelay(7);
21681 +               dctl.d32 = 0;
21682 +               dctl.b.rmtwkupsig = 1;
21683 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
21684 +       }
21685 +
21686 +       core_if->hibernation_suspend = 0;
21687 +       /* The core will be in ON STATE */
21688 +       core_if->lx_state = DWC_OTG_L0;
21689 +       DWC_PRINTF("Hibernation recovery completes here\n");
21690 +
21691 +       return 1;
21692 +}
21693 +
21694 +/*
21695 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21696 + * Hibernation. This function is for exiting from Host mode hibernation by
21697 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21698 + * @param core_if Programming view of DWC_otg controller.
21699 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21700 + * @param reset - indicates whether resume is initiated by Reset.
21701 + */
21702 +int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
21703 +                                    int rem_wakeup, int reset)
21704 +{
21705 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
21706 +       hprt0_data_t hprt0 = {.d32 = 0 };
21707 +
21708 +       int timeout = 2000;
21709 +
21710 +       DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__);
21711 +       /* Switch-on voltage to the core */
21712 +       gpwrdn.b.pwrdnswtch = 1;
21713 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21714 +       dwc_udelay(10);
21715 +
21716 +       /* Reset core */
21717 +       gpwrdn.d32 = 0;
21718 +       gpwrdn.b.pwrdnrstn = 1;
21719 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21720 +       dwc_udelay(10);
21721 +
21722 +       /* Assert Restore signal */
21723 +       gpwrdn.d32 = 0;
21724 +       gpwrdn.b.restore = 1;
21725 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21726 +       dwc_udelay(10);
21727 +
21728 +       /* Disable power clamps */
21729 +       gpwrdn.d32 = 0;
21730 +       gpwrdn.b.pwrdnclmp = 1;
21731 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21732 +
21733 +       if (!rem_wakeup) {
21734 +               dwc_udelay(50);
21735 +       }
21736 +
21737 +       /* Deassert Reset core */
21738 +       gpwrdn.d32 = 0;
21739 +       gpwrdn.b.pwrdnrstn = 1;
21740 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21741 +       dwc_udelay(10);
21742 +
21743 +       /* Disable PMU interrupt */
21744 +       gpwrdn.d32 = 0;
21745 +       gpwrdn.b.pmuintsel = 1;
21746 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21747 +
21748 +       gpwrdn.d32 = 0;
21749 +       gpwrdn.b.connect_det_msk = 1;
21750 +       gpwrdn.b.srp_det_msk = 1;
21751 +       gpwrdn.b.disconn_det_msk = 1;
21752 +       gpwrdn.b.rst_det_msk = 1;
21753 +       gpwrdn.b.lnstchng_msk = 1;
21754 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21755 +
21756 +       /* Indicates that we are going out from hibernation */
21757 +       core_if->hibernation_suspend = 0;
21758 +
21759 +       /* Set Restore Essential Regs bit in PCGCCTL register */
21760 +       restore_essential_regs(core_if, rem_wakeup, 1);
21761 +
21762 +       /* Wait a little for seeing new value of variable hibernation_suspend if
21763 +        * Restore done interrupt received before polling */
21764 +       dwc_udelay(10);
21765 +
21766 +       if (core_if->hibernation_suspend == 0) {
21767 +               /* Wait For Restore_done Interrupt. This mechanism of polling the
21768 +                * interrupt is introduced to avoid any possible race conditions
21769 +                */
21770 +               do {
21771 +                       gintsts_data_t gintsts;
21772 +                       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21773 +                       if (gintsts.b.restoredone) {
21774 +                               gintsts.d32 = 0;
21775 +                               gintsts.b.restoredone = 1;
21776 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
21777 +                               DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");   
21778 +                               break;
21779 +                       }
21780 +                       dwc_udelay(10);
21781 +               } while (--timeout);
21782 +               if (!timeout) {
21783 +                       DWC_WARN("Restore Done interrupt wasn't generated\n");
21784 +               }
21785 +       }
21786 +
21787 +       /* Set the flag's value to 0 again after receiving restore done interrupt */
21788 +       core_if->hibernation_suspend = 0;
21789 +
21790 +       /* This step is not described in functional spec but if not wait for this
21791 +        * delay, mismatch interrupts occurred because just after restore core is
21792 +        * in Device mode(gintsts.curmode == 0) */
21793 +       dwc_mdelay(100);
21794 +
21795 +       /* Clear all pending interrupts */
21796 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21797 +
21798 +       /* De-assert Restore */
21799 +       gpwrdn.d32 = 0;
21800 +       gpwrdn.b.restore = 1;
21801 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21802 +       dwc_udelay(10);
21803 +
21804 +       /* Restore GUSBCFG and HCFG */
21805 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21806 +                       core_if->gr_backup->gusbcfg_local);
21807 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
21808 +                       core_if->hr_backup->hcfg_local);
21809 +
21810 +       /* De-assert Wakeup Logic */
21811 +       gpwrdn.d32 = 0;
21812 +       gpwrdn.b.pmuactv = 1;
21813 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21814 +       dwc_udelay(10);
21815 +
21816 +       /* Start the Resume operation by programming HPRT0 */
21817 +       hprt0.d32 = core_if->hr_backup->hprt0_local;
21818 +       hprt0.b.prtpwr = 1;
21819 +       hprt0.b.prtena = 0;
21820 +       hprt0.b.prtsusp = 0;
21821 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21822 +
21823 +       DWC_PRINTF("Resume Starts Now\n");
21824 +       if (!reset) {           // Indicates it is Resume Operation
21825 +               hprt0.d32 = core_if->hr_backup->hprt0_local;
21826 +               hprt0.b.prtres = 1;
21827 +               hprt0.b.prtpwr = 1;
21828 +               hprt0.b.prtena = 0;
21829 +               hprt0.b.prtsusp = 0;
21830 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21831 +
21832 +               if (!rem_wakeup)
21833 +                       hprt0.b.prtres = 0;
21834 +               /* Wait for Resume time and then program HPRT again */
21835 +               dwc_mdelay(100);
21836 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21837 +
21838 +       } else {                // Indicates it is Reset Operation
21839 +               hprt0.d32 = core_if->hr_backup->hprt0_local;
21840 +               hprt0.b.prtrst = 1;
21841 +               hprt0.b.prtpwr = 1;
21842 +               hprt0.b.prtena = 0;
21843 +               hprt0.b.prtsusp = 0;
21844 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21845 +               /* Wait for Reset time and then program HPRT again */
21846 +               dwc_mdelay(60);
21847 +               hprt0.b.prtrst = 0;
21848 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21849 +       }
21850 +       /* Clear all interrupt status */
21851 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
21852 +       hprt0.b.prtconndet = 1;
21853 +       hprt0.b.prtenchng = 1;
21854 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21855 +
21856 +       /* Clear all pending interupts */
21857 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21858 +
21859 +       /* Restore global registers */
21860 +       dwc_otg_restore_global_regs(core_if);
21861 +       /* Restore host global registers */
21862 +       dwc_otg_restore_host_regs(core_if, reset);
21863 +
21864 +       /* The core will be in ON STATE */
21865 +       core_if->lx_state = DWC_OTG_L0;
21866 +       DWC_PRINTF("Hibernation recovery is complete here\n");
21867 +       return 0;
21868 +}
21869 +
21870 +/** Saves some register values into system memory. */
21871 +int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if)
21872 +{
21873 +       struct dwc_otg_global_regs_backup *gr;
21874 +       int i;
21875 +
21876 +       gr = core_if->gr_backup;
21877 +       if (!gr) {
21878 +               gr = DWC_ALLOC(sizeof(*gr));
21879 +               if (!gr) {
21880 +                       return -DWC_E_NO_MEMORY;
21881 +               }
21882 +               core_if->gr_backup = gr;
21883 +       }
21884 +
21885 +       gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
21886 +       gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21887 +       gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
21888 +       gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21889 +       gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
21890 +       gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
21891 +       gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21892 +#ifdef CONFIG_USB_DWC_OTG_LPM
21893 +       gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
21894 +#endif
21895 +       gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl);
21896 +       gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl);
21897 +       gr->gdfifocfg_local =
21898 +           DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg);
21899 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21900 +               gr->dtxfsiz_local[i] =
21901 +                   DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i]));
21902 +       }
21903 +
21904 +       DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n");
21905 +       DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl   = %08x\n", gr->gotgctl_local);
21906 +       DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);
21907 +       DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg   = %08x\n", gr->gahbcfg_local);
21908 +       DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg   = %08x\n", gr->gusbcfg_local);
21909 +       DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz   = %08x\n", gr->grxfsiz_local);
21910 +       DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n",
21911 +                   gr->gnptxfsiz_local);
21912 +       DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz  = %08x\n",
21913 +                   gr->hptxfsiz_local);
21914 +#ifdef CONFIG_USB_DWC_OTG_LPM
21915 +       DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg   = %08x\n", gr->glpmcfg_local);
21916 +#endif
21917 +       DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl   = %08x\n", gr->gi2cctl_local);
21918 +       DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl   = %08x\n", gr->pcgcctl_local);
21919 +       DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg   = %08x\n",gr->gdfifocfg_local);
21920 +
21921 +       return 0;
21922 +}
21923 +
21924 +/** Saves GINTMSK register before setting the msk bits. */
21925 +int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if)
21926 +{
21927 +       struct dwc_otg_global_regs_backup *gr;
21928 +
21929 +       gr = core_if->gr_backup;
21930 +       if (!gr) {
21931 +               gr = DWC_ALLOC(sizeof(*gr));
21932 +               if (!gr) {
21933 +                       return -DWC_E_NO_MEMORY;
21934 +               }
21935 +               core_if->gr_backup = gr;
21936 +       }
21937 +
21938 +       gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21939 +
21940 +       DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n");
21941 +       DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);
21942 +
21943 +       return 0;
21944 +}
21945 +
21946 +int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if)
21947 +{
21948 +       struct dwc_otg_dev_regs_backup *dr;
21949 +       int i;
21950 +
21951 +       dr = core_if->dr_backup;
21952 +       if (!dr) {
21953 +               dr = DWC_ALLOC(sizeof(*dr));
21954 +               if (!dr) {
21955 +                       return -DWC_E_NO_MEMORY;
21956 +               }
21957 +               core_if->dr_backup = dr;
21958 +       }
21959 +
21960 +       dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21961 +       dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
21962 +       dr->daintmsk =
21963 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
21964 +       dr->diepmsk =
21965 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk);
21966 +       dr->doepmsk =
21967 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk);
21968 +
21969 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21970 +               dr->diepctl[i] =
21971 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
21972 +               dr->dieptsiz[i] =
21973 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz);
21974 +               dr->diepdma[i] =
21975 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma);
21976 +       }
21977 +
21978 +       DWC_DEBUGPL(DBG_ANY,
21979 +                   "=============Backing Host registers==============\n");
21980 +       DWC_DEBUGPL(DBG_ANY, "Backed up dcfg            = %08x\n", dr->dcfg);
21981 +       DWC_DEBUGPL(DBG_ANY, "Backed up dctl        = %08x\n", dr->dctl);
21982 +       DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk            = %08x\n",
21983 +                   dr->daintmsk);
21984 +       DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk        = %08x\n", dr->diepmsk);
21985 +       DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk        = %08x\n", dr->doepmsk);
21986 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21987 +               DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d]        = %08x\n", i,
21988 +                           dr->diepctl[i]);
21989 +               DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d]        = %08x\n",
21990 +                           i, dr->dieptsiz[i]);
21991 +               DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d]        = %08x\n", i,
21992 +                           dr->diepdma[i]);
21993 +       }
21994 +
21995 +       return 0;
21996 +}
21997 +
21998 +int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if)
21999 +{
22000 +       struct dwc_otg_host_regs_backup *hr;
22001 +       int i;
22002 +
22003 +       hr = core_if->hr_backup;
22004 +       if (!hr) {
22005 +               hr = DWC_ALLOC(sizeof(*hr));
22006 +               if (!hr) {
22007 +                       return -DWC_E_NO_MEMORY;
22008 +               }
22009 +               core_if->hr_backup = hr;
22010 +       }
22011 +
22012 +       hr->hcfg_local =
22013 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
22014 +       hr->haintmsk_local =
22015 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
22016 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
22017 +               hr->hcintmsk_local[i] =
22018 +                   DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk);
22019 +       }
22020 +       hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0);
22021 +       hr->hfir_local =
22022 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
22023 +
22024 +       DWC_DEBUGPL(DBG_ANY,
22025 +                   "=============Backing Host registers===============\n");
22026 +       DWC_DEBUGPL(DBG_ANY, "Backed up hcfg            = %08x\n",
22027 +                   hr->hcfg_local);
22028 +       DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local);
22029 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
22030 +               DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i,
22031 +                           hr->hcintmsk_local[i]);
22032 +       }
22033 +       DWC_DEBUGPL(DBG_ANY, "Backed up hprt0           = %08x\n",
22034 +                   hr->hprt0_local);
22035 +       DWC_DEBUGPL(DBG_ANY, "Backed up hfir           = %08x\n",
22036 +                   hr->hfir_local);
22037 +
22038 +       return 0;
22039 +}
22040 +
22041 +int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if)
22042 +{
22043 +       struct dwc_otg_global_regs_backup *gr;
22044 +       int i;
22045 +
22046 +       gr = core_if->gr_backup;
22047 +       if (!gr) {
22048 +               return -DWC_E_INVALID;
22049 +       }
22050 +   
22051 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local);
22052 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local);
22053 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local);
22054 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local);
22055 +       DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local);
22056 +       DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz,
22057 +                       gr->gnptxfsiz_local);
22058 +       DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz,
22059 +                       gr->hptxfsiz_local);
22060 +       DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg,
22061 +                       gr->gdfifocfg_local);
22062 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
22063 +               DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i],
22064 +                               gr->dtxfsiz_local[i]);
22065 +       }
22066 +
22067 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
22068 +       DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A);
22069 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg,
22070 +                       (gr->gahbcfg_local));
22071 +       return 0;
22072 +}
22073 +
22074 +int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup)
22075 +{
22076 +       struct dwc_otg_dev_regs_backup *dr;
22077 +       int i;
22078 +
22079 +       dr = core_if->dr_backup;
22080 +
22081 +       if (!dr) {
22082 +               return -DWC_E_INVALID;
22083 +       }
22084 +
22085 +       if (!rem_wakeup) {
22086 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
22087 +                               dr->dctl);
22088 +       }
22089 +       
22090 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk);
22091 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk);
22092 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk);
22093 +
22094 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
22095 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]);
22096 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]);
22097 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]);
22098 +       }
22099 +       
22100 +       return 0;
22101 +}
22102 +
22103 +int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset)
22104 +{
22105 +       struct dwc_otg_host_regs_backup *hr;
22106 +       int i;
22107 +       hr = core_if->hr_backup;
22108 +
22109 +       if (!hr) {
22110 +               return -DWC_E_INVALID;
22111 +       }
22112 +
22113 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local);
22114 +       //if (!reset)
22115 +       //{
22116 +       //      DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local);
22117 +       //}
22118 +
22119 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk,
22120 +                       hr->haintmsk_local);
22121 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
22122 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk,
22123 +                               hr->hcintmsk_local[i]);
22124 +       }
22125 +
22126 +       return 0;
22127 +}
22128 +
22129 +int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if)
22130 +{
22131 +       struct dwc_otg_global_regs_backup *gr;
22132 +
22133 +       gr = core_if->gr_backup;
22134 +
22135 +       /* Restore values for LPM and I2C */
22136 +#ifdef CONFIG_USB_DWC_OTG_LPM
22137 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local);
22138 +#endif
22139 +       DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local);
22140 +
22141 +       return 0;
22142 +}
22143 +
22144 +int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host)
22145 +{
22146 +       struct dwc_otg_global_regs_backup *gr;
22147 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
22148 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
22149 +       gusbcfg_data_t gusbcfg = {.d32 = 0 };
22150 +       gintmsk_data_t gintmsk = {.d32 = 0 };
22151 +
22152 +       /* Restore LPM and I2C registers */
22153 +       restore_lpm_i2c_regs(core_if);
22154 +
22155 +       /* Set PCGCCTL to 0 */
22156 +       DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000);
22157 +
22158 +       gr = core_if->gr_backup;
22159 +       /* Load restore values for [31:14] bits */
22160 +       DWC_WRITE_REG32(core_if->pcgcctl,
22161 +                       ((gr->pcgcctl_local & 0xffffc000) | 0x00020000));
22162 +
22163 +       /* Umnask global Interrupt in GAHBCFG and restore it */
22164 +       gahbcfg.d32 = gr->gahbcfg_local;
22165 +       gahbcfg.b.glblintrmsk = 1;
22166 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
22167 +
22168 +       /* Clear all pending interupts */
22169 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
22170 +
22171 +       /* Unmask restore done interrupt */
22172 +       gintmsk.b.restoredone = 1;
22173 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
22174 +
22175 +       /* Restore GUSBCFG and HCFG/DCFG */
22176 +       gusbcfg.d32 = core_if->gr_backup->gusbcfg_local;
22177 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
22178 +
22179 +       if (is_host) {
22180 +               hcfg_data_t hcfg = {.d32 = 0 };
22181 +               hcfg.d32 = core_if->hr_backup->hcfg_local;
22182 +               DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
22183 +                               hcfg.d32);
22184 +
22185 +               /* Load restore values for [31:14] bits */
22186 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22187 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22188 +
22189 +               if (rmode)
22190 +                       pcgcctl.b.restoremode = 1;
22191 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22192 +               dwc_udelay(10);
22193 +
22194 +               /* Load restore values for [31:14] bits and set EssRegRestored bit */
22195 +               pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000;
22196 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22197 +               pcgcctl.b.ess_reg_restored = 1;
22198 +               if (rmode)
22199 +                       pcgcctl.b.restoremode = 1;
22200 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22201 +       } else {
22202 +               dcfg_data_t dcfg = {.d32 = 0 };
22203 +               dcfg.d32 = core_if->dr_backup->dcfg;
22204 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
22205 +
22206 +               /* Load restore values for [31:14] bits */
22207 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22208 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22209 +               if (!rmode) {
22210 +                       pcgcctl.d32 |= 0x208;
22211 +               }
22212 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22213 +               dwc_udelay(10);
22214 +
22215 +               /* Load restore values for [31:14] bits */
22216 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22217 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22218 +               pcgcctl.b.ess_reg_restored = 1;
22219 +               if (!rmode)
22220 +                       pcgcctl.d32 |= 0x208;
22221 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22222 +       }
22223 +
22224 +       return 0;
22225 +}
22226 +
22227 +/**
22228 + * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
22229 + * type.
22230 + */
22231 +static void init_fslspclksel(dwc_otg_core_if_t * core_if)
22232 +{
22233 +       uint32_t val;
22234 +       hcfg_data_t hcfg;
22235 +
22236 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
22237 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
22238 +            (core_if->core_params->ulpi_fs_ls)) ||
22239 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22240 +               /* Full speed PHY */
22241 +               val = DWC_HCFG_48_MHZ;
22242 +       } else {
22243 +               /* High speed PHY running at full speed or high speed */
22244 +               val = DWC_HCFG_30_60_MHZ;
22245 +       }
22246 +
22247 +       DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
22248 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
22249 +       hcfg.b.fslspclksel = val;
22250 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
22251 +}
22252 +
22253 +/**
22254 + * Initializes the DevSpd field of the DCFG register depending on the PHY type
22255 + * and the enumeration speed of the device.
22256 + */
22257 +static void init_devspd(dwc_otg_core_if_t * core_if)
22258 +{
22259 +       uint32_t val;
22260 +       dcfg_data_t dcfg;
22261 +
22262 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
22263 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
22264 +            (core_if->core_params->ulpi_fs_ls)) ||
22265 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22266 +               /* Full speed PHY */
22267 +               val = 0x3;
22268 +       } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
22269 +               /* High speed PHY running at full speed */
22270 +               val = 0x1;
22271 +       } else {
22272 +               /* High speed PHY running at high speed */
22273 +               val = 0x0;
22274 +       }
22275 +
22276 +       DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
22277 +
22278 +       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
22279 +       dcfg.b.devspd = val;
22280 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
22281 +}
22282 +
22283 +/**
22284 + * This function calculates the number of IN EPS
22285 + * using GHWCFG1 and GHWCFG2 registers values
22286 + *
22287 + * @param core_if Programming view of the DWC_otg controller
22288 + */
22289 +static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if)
22290 +{
22291 +       uint32_t num_in_eps = 0;
22292 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
22293 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3;
22294 +       uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps;
22295 +       int i;
22296 +
22297 +       for (i = 0; i < num_eps; ++i) {
22298 +               if (!(hwcfg1 & 0x1))
22299 +                       num_in_eps++;
22300 +
22301 +               hwcfg1 >>= 2;
22302 +       }
22303 +
22304 +       if (core_if->hwcfg4.b.ded_fifo_en) {
22305 +               num_in_eps =
22306 +                   (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
22307 +       }
22308 +
22309 +       return num_in_eps;
22310 +}
22311 +
22312 +/**
22313 + * This function calculates the number of OUT EPS
22314 + * using GHWCFG1 and GHWCFG2 registers values
22315 + *
22316 + * @param core_if Programming view of the DWC_otg controller
22317 + */
22318 +static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if)
22319 +{
22320 +       uint32_t num_out_eps = 0;
22321 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
22322 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2;
22323 +       int i;
22324 +
22325 +       for (i = 0; i < num_eps; ++i) {
22326 +               if (!(hwcfg1 & 0x1))
22327 +                       num_out_eps++;
22328 +
22329 +               hwcfg1 >>= 2;
22330 +       }
22331 +       return num_out_eps;
22332 +}
22333 +
22334 +/**
22335 + * This function initializes the DWC_otg controller registers and
22336 + * prepares the core for device mode or host mode operation.
22337 + *
22338 + * @param core_if Programming view of the DWC_otg controller
22339 + *
22340 + */
22341 +void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
22342 +{
22343 +       int i = 0;
22344 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22345 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22346 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
22347 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
22348 +       gi2cctl_data_t i2cctl = {.d32 = 0 };
22349 +
22350 +       DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p) regs at %p\n",
22351 +                    core_if, global_regs);
22352 +
22353 +       /* Common Initialization */
22354 +       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22355 +
22356 +       /* Program the ULPI External VBUS bit if needed */
22357 +       usbcfg.b.ulpi_ext_vbus_drv =
22358 +           (core_if->core_params->phy_ulpi_ext_vbus ==
22359 +            DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
22360 +
22361 +       /* Set external TS Dline pulsing */
22362 +       usbcfg.b.term_sel_dl_pulse =
22363 +           (core_if->core_params->ts_dline == 1) ? 1 : 0;
22364 +       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22365 +
22366 +       /* Reset the Controller */
22367 +       dwc_otg_core_reset(core_if);
22368 +
22369 +       core_if->adp_enable = core_if->core_params->adp_supp_enable;
22370 +       core_if->power_down = core_if->core_params->power_down;
22371 +       core_if->otg_sts = 0;
22372 +
22373 +       /* Initialize parameters from Hardware configuration registers. */
22374 +       dev_if->num_in_eps = calc_num_in_eps(core_if);
22375 +       dev_if->num_out_eps = calc_num_out_eps(core_if);
22376 +
22377 +       DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
22378 +                   core_if->hwcfg4.b.num_dev_perio_in_ep);
22379 +
22380 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22381 +               dev_if->perio_tx_fifo_size[i] =
22382 +                   DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22383 +               DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n",
22384 +                           i, dev_if->perio_tx_fifo_size[i]);
22385 +       }
22386 +
22387 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22388 +               dev_if->tx_fifo_size[i] =
22389 +                   DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22390 +               DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n",
22391 +                           i, dev_if->tx_fifo_size[i]);
22392 +       }
22393 +
22394 +       core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
22395 +       core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
22396 +       core_if->nperio_tx_fifo_size =
22397 +           DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
22398 +
22399 +       DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size);
22400 +       DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
22401 +       DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",
22402 +                   core_if->nperio_tx_fifo_size);
22403 +
22404 +       /* This programming sequence needs to happen in FS mode before any other
22405 +        * programming occurs */
22406 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
22407 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22408 +               /* If FS mode with FS PHY */
22409 +
22410 +               /* core_init() is now called on every switch so only call the
22411 +                * following for the first time through. */
22412 +               if (!core_if->phy_init_done) {
22413 +                       core_if->phy_init_done = 1;
22414 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
22415 +                       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22416 +                       usbcfg.b.physel = 1;
22417 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22418 +
22419 +                       /* Reset after a PHY select */
22420 +                       dwc_otg_core_reset(core_if);
22421 +               }
22422 +
22423 +               /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.      Also
22424 +                * do this on HNP Dev/Host mode switches (done in dev_init and
22425 +                * host_init). */
22426 +               if (dwc_otg_is_host_mode(core_if)) {
22427 +                       init_fslspclksel(core_if);
22428 +               } else {
22429 +                       init_devspd(core_if);
22430 +               }
22431 +
22432 +               if (core_if->core_params->i2c_enable) {
22433 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
22434 +                       /* Program GUSBCFG.OtgUtmifsSel to I2C */
22435 +                       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22436 +                       usbcfg.b.otgutmifssel = 1;
22437 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22438 +
22439 +                       /* Program GI2CCTL.I2CEn */
22440 +                       i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl);
22441 +                       i2cctl.b.i2cdevaddr = 1;
22442 +                       i2cctl.b.i2cen = 0;
22443 +                       DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22444 +                       i2cctl.b.i2cen = 1;
22445 +                       DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22446 +               }
22447 +
22448 +       } /* endif speed == DWC_SPEED_PARAM_FULL */
22449 +       else {
22450 +               /* High speed PHY. */
22451 +               if (!core_if->phy_init_done) {
22452 +                       core_if->phy_init_done = 1;
22453 +                       /* HS PHY parameters.  These parameters are preserved
22454 +                        * during soft reset so only program the first time.  Do
22455 +                        * a soft reset immediately after setting phyif.  */
22456 +
22457 +                       if (core_if->core_params->phy_type == 2) {
22458 +                               /* ULPI interface */
22459 +                               usbcfg.b.ulpi_utmi_sel = 1;
22460 +                               usbcfg.b.phyif = 0;
22461 +                               usbcfg.b.ddrsel =
22462 +                                   core_if->core_params->phy_ulpi_ddr;
22463 +                       } else if (core_if->core_params->phy_type == 1) {
22464 +                               /* UTMI+ interface */
22465 +                               usbcfg.b.ulpi_utmi_sel = 0;
22466 +                               if (core_if->core_params->phy_utmi_width == 16) {
22467 +                                       usbcfg.b.phyif = 1;
22468 +
22469 +                               } else {
22470 +                                       usbcfg.b.phyif = 0;
22471 +                               }
22472 +                       } else {
22473 +                               DWC_ERROR("FS PHY TYPE\n");
22474 +                       }
22475 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22476 +                       /* Reset after setting the PHY parameters */
22477 +                       dwc_otg_core_reset(core_if);
22478 +               }
22479 +       }
22480 +
22481 +       if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
22482 +           (core_if->hwcfg2.b.fs_phy_type == 1) &&
22483 +           (core_if->core_params->ulpi_fs_ls)) {
22484 +               DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
22485 +               usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22486 +               usbcfg.b.ulpi_fsls = 1;
22487 +               usbcfg.b.ulpi_clk_sus_m = 1;
22488 +               DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22489 +       } else {
22490 +               usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22491 +               usbcfg.b.ulpi_fsls = 0;
22492 +               usbcfg.b.ulpi_clk_sus_m = 0;
22493 +               DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22494 +       }
22495 +
22496 +       /* Program the GAHBCFG Register. */
22497 +       switch (core_if->hwcfg2.b.architecture) {
22498 +
22499 +       case DWC_SLAVE_ONLY_ARCH:
22500 +               DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
22501 +               ahbcfg.b.nptxfemplvl_txfemplvl =
22502 +                   DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22503 +               ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22504 +               core_if->dma_enable = 0;
22505 +               core_if->dma_desc_enable = 0;
22506 +               break;
22507 +
22508 +       case DWC_EXT_DMA_ARCH:
22509 +               DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
22510 +               {
22511 +                       uint8_t brst_sz = core_if->core_params->dma_burst_size;
22512 +                       ahbcfg.b.hburstlen = 0;
22513 +                       while (brst_sz > 1) {
22514 +                               ahbcfg.b.hburstlen++;
22515 +                               brst_sz >>= 1;
22516 +                       }
22517 +               }
22518 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22519 +               core_if->dma_desc_enable =
22520 +                   (core_if->core_params->dma_desc_enable != 0);
22521 +               break;
22522 +
22523 +       case DWC_INT_DMA_ARCH:
22524 +               DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
22525 +               /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for 
22526 +                 Host mode ISOC in issue fix - vahrama */
22527 +               /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */
22528 +               ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4;
22529 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22530 +               core_if->dma_desc_enable =
22531 +                   (core_if->core_params->dma_desc_enable != 0);
22532 +               break;
22533 +
22534 +       }
22535 +       if (core_if->dma_enable) {
22536 +               if (core_if->dma_desc_enable) {
22537 +                       DWC_PRINTF("Using Descriptor DMA mode\n");
22538 +               } else {
22539 +                       DWC_PRINTF("Using Buffer DMA mode\n");
22540 +
22541 +               }
22542 +       } else {
22543 +               DWC_PRINTF("Using Slave mode\n");
22544 +               core_if->dma_desc_enable = 0;
22545 +       }
22546 +
22547 +       if (core_if->core_params->ahb_single) {
22548 +               ahbcfg.b.ahbsingle = 1;
22549 +       }
22550 +       
22551 +       ahbcfg.b.dmaenable = core_if->dma_enable;
22552 +       DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
22553 +
22554 +       core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
22555 +
22556 +       core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
22557 +       core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
22558 +       DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n",
22559 +                  ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
22560 +       DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n",
22561 +                  ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
22562 +
22563 +       /*
22564 +        * Program the GUSBCFG register.
22565 +        */
22566 +       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22567 +
22568 +       switch (core_if->hwcfg2.b.op_mode) {
22569 +       case DWC_MODE_HNP_SRP_CAPABLE:
22570 +               usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
22571 +                                  DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
22572 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22573 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22574 +               break;
22575 +
22576 +       case DWC_MODE_SRP_ONLY_CAPABLE:
22577 +               usbcfg.b.hnpcap = 0;
22578 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22579 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22580 +               break;
22581 +
22582 +       case DWC_MODE_NO_HNP_SRP_CAPABLE:
22583 +               usbcfg.b.hnpcap = 0;
22584 +               usbcfg.b.srpcap = 0;
22585 +               break;
22586 +
22587 +       case DWC_MODE_SRP_CAPABLE_DEVICE:
22588 +               usbcfg.b.hnpcap = 0;
22589 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22590 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22591 +               break;
22592 +
22593 +       case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
22594 +               usbcfg.b.hnpcap = 0;
22595 +               usbcfg.b.srpcap = 0;
22596 +               break;
22597 +
22598 +       case DWC_MODE_SRP_CAPABLE_HOST:
22599 +               usbcfg.b.hnpcap = 0;
22600 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22601 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22602 +               break;
22603 +
22604 +       case DWC_MODE_NO_SRP_CAPABLE_HOST:
22605 +               usbcfg.b.hnpcap = 0;
22606 +               usbcfg.b.srpcap = 0;
22607 +               break;
22608 +       }
22609 +
22610 +       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22611 +
22612 +#ifdef CONFIG_USB_DWC_OTG_LPM
22613 +       if (core_if->core_params->lpm_enable) {
22614 +               glpmcfg_data_t lpmcfg = {.d32 = 0 };
22615 +
22616 +               /* To enable LPM support set lpm_cap_en bit */
22617 +               lpmcfg.b.lpm_cap_en = 1;
22618 +
22619 +               /* Make AppL1Res ACK */
22620 +               lpmcfg.b.appl_resp = 1;
22621 +
22622 +               /* Retry 3 times */
22623 +               lpmcfg.b.retry_count = 3;
22624 +
22625 +               DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg,
22626 +                                0, lpmcfg.d32);
22627 +
22628 +       }
22629 +#endif
22630 +       if (core_if->core_params->ic_usb_cap) {
22631 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
22632 +               gusbcfg.b.ic_usb_cap = 1;
22633 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg,
22634 +                                0, gusbcfg.d32);
22635 +       }
22636 +       {
22637 +               gotgctl_data_t gotgctl = {.d32 = 0 };
22638 +               gotgctl.b.otgver = core_if->core_params->otg_ver;
22639 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0,
22640 +                                gotgctl.d32);
22641 +               /* Set OTG version supported */
22642 +               core_if->otg_ver = core_if->core_params->otg_ver;
22643 +               DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n",
22644 +                          core_if->core_params->otg_ver, core_if->otg_ver);
22645 +       }
22646 +       
22647 +
22648 +       /* Enable common interrupts */
22649 +       dwc_otg_enable_common_interrupts(core_if);
22650 +
22651 +       /* Do device or host intialization based on mode during PCD
22652 +        * and HCD initialization  */
22653 +       if (dwc_otg_is_host_mode(core_if)) {
22654 +               DWC_DEBUGPL(DBG_ANY, "Host Mode\n");
22655 +               core_if->op_state = A_HOST;
22656 +       } else {
22657 +               DWC_DEBUGPL(DBG_ANY, "Device Mode\n");
22658 +               core_if->op_state = B_PERIPHERAL;
22659 +#ifdef DWC_DEVICE_ONLY
22660 +               dwc_otg_core_dev_init(core_if);
22661 +#endif
22662 +       }
22663 +}
22664 +
22665 +/**
22666 + * This function enables the Device mode interrupts.
22667 + *
22668 + * @param core_if Programming view of DWC_otg controller
22669 + */
22670 +void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
22671 +{
22672 +       gintmsk_data_t intr_mask = {.d32 = 0 };
22673 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22674 +
22675 +       DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
22676 +
22677 +       /* Disable all interrupts. */
22678 +       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
22679 +
22680 +       /* Clear any pending interrupts */
22681 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
22682 +
22683 +       /* Enable the common interrupts */
22684 +       dwc_otg_enable_common_interrupts(core_if);
22685 +
22686 +       /* Enable interrupts */
22687 +       intr_mask.b.usbreset = 1;
22688 +       intr_mask.b.enumdone = 1;
22689 +       /* Disable Disconnect interrupt in Device mode */
22690 +       intr_mask.b.disconnect = 0;
22691 +
22692 +       if (!core_if->multiproc_int_enable) {
22693 +               intr_mask.b.inepintr = 1;
22694 +               intr_mask.b.outepintr = 1;
22695 +       }
22696 +
22697 +       intr_mask.b.erlysuspend = 1;
22698 +
22699 +       if (core_if->en_multiple_tx_fifo == 0) {
22700 +               intr_mask.b.epmismatch = 1;
22701 +       }
22702 +
22703 +       //intr_mask.b.incomplisoout = 1;
22704 +       intr_mask.b.incomplisoin = 1;
22705 +       
22706 +/* Enable the ignore frame number for ISOC xfers - MAS */
22707 +/* Disable to support high bandwith ISOC transfers - manukz */
22708 +#if 0
22709 +#ifdef DWC_UTE_PER_IO
22710 +       if (core_if->dma_enable) {
22711 +               if (core_if->dma_desc_enable) {
22712 +                       dctl_data_t dctl1 = {.d32 = 0 };
22713 +                       dctl1.b.ifrmnum = 1;
22714 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
22715 +                                        dctl, 0, dctl1.d32);
22716 +                       DWC_DEBUG("----Enabled Ignore frame number (0x%08x)",
22717 +                                 DWC_READ_REG32(&core_if->dev_if->
22718 +                                                dev_global_regs->dctl));
22719 +               }
22720 +       }
22721 +#endif
22722 +#endif
22723 +#ifdef DWC_EN_ISOC
22724 +       if (core_if->dma_enable) {
22725 +               if (core_if->dma_desc_enable == 0) {
22726 +                       if (core_if->pti_enh_enable) {
22727 +                               dctl_data_t dctl = {.d32 = 0 };
22728 +                               dctl.b.ifrmnum = 1;
22729 +                               DWC_MODIFY_REG32(&core_if->
22730 +                                                dev_if->dev_global_regs->dctl,
22731 +                                                0, dctl.d32);
22732 +                       } else {
22733 +                               intr_mask.b.incomplisoin = 1;
22734 +                               intr_mask.b.incomplisoout = 1;
22735 +                       }
22736 +               }
22737 +       } else {
22738 +               intr_mask.b.incomplisoin = 1;
22739 +               intr_mask.b.incomplisoout = 1;
22740 +       }
22741 +#endif /* DWC_EN_ISOC */
22742 +
22743 +       /** @todo NGS: Should this be a module parameter? */
22744 +#ifdef USE_PERIODIC_EP
22745 +       intr_mask.b.isooutdrop = 1;
22746 +       intr_mask.b.eopframe = 1;
22747 +       intr_mask.b.incomplisoin = 1;
22748 +       intr_mask.b.incomplisoout = 1;
22749 +#endif
22750 +
22751 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
22752 +
22753 +       DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
22754 +                   DWC_READ_REG32(&global_regs->gintmsk));
22755 +}
22756 +
22757 +/**
22758 + * This function initializes the DWC_otg controller registers for
22759 + * device mode.
22760 + *
22761 + * @param core_if Programming view of DWC_otg controller
22762 + *
22763 + */
22764 +void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
22765 +{
22766 +       int i;
22767 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22768 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22769 +       dwc_otg_core_params_t *params = core_if->core_params;
22770 +       dcfg_data_t dcfg = {.d32 = 0 };
22771 +       depctl_data_t diepctl = {.d32 = 0 };
22772 +       grstctl_t resetctl = {.d32 = 0 };
22773 +       uint32_t rx_fifo_size;
22774 +       fifosize_data_t nptxfifosize;
22775 +       fifosize_data_t txfifosize;
22776 +       dthrctl_data_t dthrctl;
22777 +       fifosize_data_t ptxfifosize;
22778 +       uint16_t rxfsiz, nptxfsiz;
22779 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
22780 +       hwcfg3_data_t hwcfg3 = {.d32 = 0 };
22781 +
22782 +       /* Restart the Phy Clock */
22783 +       DWC_WRITE_REG32(core_if->pcgcctl, 0);
22784 +
22785 +       /* Device configuration register */
22786 +       init_devspd(core_if);
22787 +       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22788 +       dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0;
22789 +       dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
22790 +       /* Enable Device OUT NAK in case of DDMA mode*/
22791 +       if (core_if->core_params->dev_out_nak) {
22792 +               dcfg.b.endevoutnak = 1;         
22793 +       }
22794 +
22795 +       if (core_if->core_params->cont_on_bna) {
22796 +               dctl_data_t dctl = {.d32 = 0 };
22797 +               dctl.b.encontonbna = 1;
22798 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
22799 +       }
22800 +       
22801 +
22802 +       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22803 +
22804 +       /* Configure data FIFO sizes */
22805 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
22806 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
22807 +                           core_if->total_fifo_size);
22808 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
22809 +                           params->dev_rx_fifo_size);
22810 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
22811 +                           params->dev_nperio_tx_fifo_size);
22812 +
22813 +               /* Rx FIFO */
22814 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
22815 +                           DWC_READ_REG32(&global_regs->grxfsiz));
22816 +
22817 +#ifdef DWC_UTE_CFI
22818 +               core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz);
22819 +               core_if->init_rxfsiz = params->dev_rx_fifo_size;
22820 +#endif
22821 +               rx_fifo_size = params->dev_rx_fifo_size;
22822 +               DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
22823 +
22824 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
22825 +                           DWC_READ_REG32(&global_regs->grxfsiz));
22826 +
22827 +               /** Set Periodic Tx FIFO Mask all bits 0 */
22828 +               core_if->p_tx_msk = 0;
22829 +
22830 +               /** Set Tx FIFO Mask all bits 0 */
22831 +               core_if->tx_msk = 0;
22832 +
22833 +               if (core_if->en_multiple_tx_fifo == 0) {
22834 +                       /* Non-periodic Tx FIFO */
22835 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22836 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22837 +
22838 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22839 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22840 +
22841 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22842 +                                       nptxfifosize.d32);
22843 +
22844 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22845 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22846 +
22847 +                       /**@todo NGS: Fix Periodic FIFO Sizing! */
22848 +                       /*
22849 +                        * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.
22850 +                        * Indexes of the FIFO size module parameters in the
22851 +                        * dev_perio_tx_fifo_size array and the FIFO size registers in
22852 +                        * the dptxfsiz array run from 0 to 14.
22853 +                        */
22854 +                       /** @todo Finish debug of this */
22855 +                       ptxfifosize.b.startaddr =
22856 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22857 +                       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22858 +                               ptxfifosize.b.depth =
22859 +                                   params->dev_perio_tx_fifo_size[i];
22860 +                               DWC_DEBUGPL(DBG_CIL,
22861 +                                           "initial dtxfsiz[%d]=%08x\n", i,
22862 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22863 +                                                          [i]));
22864 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22865 +                                               ptxfifosize.d32);
22866 +                               DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n",
22867 +                                           i,
22868 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22869 +                                                          [i]));
22870 +                               ptxfifosize.b.startaddr += ptxfifosize.b.depth;
22871 +                       }
22872 +               } else {
22873 +                       /*
22874 +                        * Tx FIFOs These FIFOs are numbered from 1 to 15.
22875 +                        * Indexes of the FIFO size module parameters in the
22876 +                        * dev_tx_fifo_size array and the FIFO size registers in
22877 +                        * the dtxfsiz array run from 0 to 14.
22878 +                        */
22879 +
22880 +                       /* Non-periodic Tx FIFO */
22881 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22882 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22883 +
22884 +#ifdef DWC_UTE_CFI
22885 +                       core_if->pwron_gnptxfsiz =
22886 +                           (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22887 +                       core_if->init_gnptxfsiz =
22888 +                           params->dev_nperio_tx_fifo_size;
22889 +#endif
22890 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22891 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22892 +
22893 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22894 +                                       nptxfifosize.d32);
22895 +
22896 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22897 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22898 +
22899 +                       txfifosize.b.startaddr =
22900 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22901 +
22902 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22903 +
22904 +                               txfifosize.b.depth =
22905 +                                   params->dev_tx_fifo_size[i];
22906 +
22907 +                               DWC_DEBUGPL(DBG_CIL,
22908 +                                           "initial dtxfsiz[%d]=%08x\n",
22909 +                                           i,
22910 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22911 +                                                          [i]));
22912 +
22913 +#ifdef DWC_UTE_CFI
22914 +                               core_if->pwron_txfsiz[i] =
22915 +                                   (DWC_READ_REG32
22916 +                                    (&global_regs->dtxfsiz[i]) >> 16);
22917 +                               core_if->init_txfsiz[i] =
22918 +                                   params->dev_tx_fifo_size[i];
22919 +#endif
22920 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22921 +                                               txfifosize.d32);
22922 +
22923 +                               DWC_DEBUGPL(DBG_CIL,
22924 +                                           "new dtxfsiz[%d]=%08x\n",
22925 +                                           i,
22926 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22927 +                                                          [i]));
22928 +
22929 +                               txfifosize.b.startaddr += txfifosize.b.depth;
22930 +                       }
22931 +                       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
22932 +                               /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */
22933 +                               gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
22934 +                               hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3);
22935 +                               gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16);
22936 +                               DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22937 +                               rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
22938 +                               nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22939 +                               gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz;
22940 +                               DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22941 +                       }
22942 +               }
22943 +
22944 +               /* Flush the FIFOs */
22945 +               dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
22946 +               dwc_otg_flush_rx_fifo(core_if);
22947 +
22948 +               /* Flush the Learning Queue. */
22949 +               resetctl.b.intknqflsh = 1;
22950 +               DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
22951 +
22952 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
22953 +                       core_if->start_predict = 0;
22954 +                       for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
22955 +                               core_if->nextep_seq[i] = 0xff;  // 0xff - EP not active
22956 +                       }
22957 +                       core_if->nextep_seq[0] = 0;
22958 +                       core_if->first_in_nextep_seq = 0;
22959 +                       diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
22960 +                       diepctl.b.nextep = 0;
22961 +                       DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
22962 +               
22963 +                       /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
22964 +                       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22965 +                       dcfg.b.epmscnt = 2;
22966 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22967 +
22968 +                       DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
22969 +                               __func__, core_if->first_in_nextep_seq);
22970 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
22971 +                               DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]);
22972 +                       }
22973 +                       DWC_DEBUGPL(DBG_CILV,"\n");
22974 +               }
22975 +       
22976 +               /* Clear all pending Device Interrupts */
22977 +               /** @todo - if the condition needed to be checked
22978 +                *  or in any case all pending interrutps should be cleared?
22979 +            */
22980 +               if (core_if->multiproc_int_enable) {
22981 +                       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
22982 +                               DWC_WRITE_REG32(&dev_if->
22983 +                                               dev_global_regs->diepeachintmsk[i], 0);
22984 +                       }
22985 +               }
22986 +
22987 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
22988 +                       DWC_WRITE_REG32(&dev_if->
22989 +                                       dev_global_regs->doepeachintmsk[i], 0);
22990 +               }
22991 +
22992 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF);
22993 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0);
22994 +       } else {
22995 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
22996 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
22997 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
22998 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
22999 +       }
23000 +
23001 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
23002 +               depctl_data_t depctl;
23003 +               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
23004 +               if (depctl.b.epena) {
23005 +                       depctl.d32 = 0;
23006 +                       depctl.b.epdis = 1;
23007 +                       depctl.b.snak = 1;
23008 +               } else {
23009 +                       depctl.d32 = 0;
23010 +               }
23011 +
23012 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
23013 +
23014 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
23015 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
23016 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
23017 +       }
23018 +
23019 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
23020 +               depctl_data_t depctl;
23021 +               depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
23022 +               if (depctl.b.epena) {
23023 +                       dctl_data_t dctl = {.d32 = 0 };
23024 +                       gintmsk_data_t gintsts = {.d32 = 0 };
23025 +                       doepint_data_t doepint = {.d32 = 0 };
23026 +                       dctl.b.sgoutnak = 1;
23027 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
23028 +                       do {
23029 +                               dwc_udelay(10);
23030 +                               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
23031 +                       } while (!gintsts.b.goutnakeff);
23032 +                       gintsts.d32 = 0;
23033 +                       gintsts.b.goutnakeff = 1;
23034 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
23035 +
23036 +                       depctl.d32 = 0;
23037 +                       depctl.b.epdis = 1;
23038 +                       depctl.b.snak = 1;
23039 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32);
23040 +                       do {
23041 +                               dwc_udelay(10);
23042 +                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
23043 +                                       out_ep_regs[i]->doepint);
23044 +                       } while (!doepint.b.epdisabled);
23045 +
23046 +                       doepint.b.epdisabled = 1;
23047 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32);
23048 +
23049 +                       dctl.d32 = 0;
23050 +                       dctl.b.cgoutnak = 1;
23051 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
23052 +               } else {
23053 +                       depctl.d32 = 0;
23054 +               }
23055 +
23056 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32);
23057 +
23058 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
23059 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
23060 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
23061 +       }
23062 +
23063 +       if (core_if->en_multiple_tx_fifo && core_if->dma_enable) {
23064 +               dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1;
23065 +               dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1;
23066 +               dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1;
23067 +
23068 +               dev_if->rx_thr_length = params->rx_thr_length;
23069 +               dev_if->tx_thr_length = params->tx_thr_length;
23070 +
23071 +               dev_if->setup_desc_index = 0;
23072 +
23073 +               dthrctl.d32 = 0;
23074 +               dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;
23075 +               dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;
23076 +               dthrctl.b.tx_thr_len = dev_if->tx_thr_length;
23077 +               dthrctl.b.rx_thr_en = dev_if->rx_thr_en;
23078 +               dthrctl.b.rx_thr_len = dev_if->rx_thr_length;
23079 +               dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio;
23080 +
23081 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl,
23082 +                               dthrctl.d32);
23083 +
23084 +               DWC_DEBUGPL(DBG_CIL,
23085 +                           "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",
23086 +                           dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,
23087 +                           dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,
23088 +                           dthrctl.b.rx_thr_len);
23089 +
23090 +       }
23091 +
23092 +       dwc_otg_enable_device_interrupts(core_if);
23093 +
23094 +       {
23095 +               diepmsk_data_t msk = {.d32 = 0 };
23096 +               msk.b.txfifoundrn = 1;
23097 +               if (core_if->multiproc_int_enable) {
23098 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->
23099 +                                        diepeachintmsk[0], msk.d32, msk.d32);
23100 +               } else {
23101 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,
23102 +                                        msk.d32, msk.d32);
23103 +               }
23104 +       }
23105 +
23106 +       if (core_if->multiproc_int_enable) {
23107 +               /* Set NAK on Babble */
23108 +               dctl_data_t dctl = {.d32 = 0 };
23109 +               dctl.b.nakonbble = 1;
23110 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
23111 +       }
23112 +
23113 +       if (core_if->snpsid >= OTG_CORE_REV_2_94a) {
23114 +               dctl_data_t dctl = {.d32 = 0 };
23115 +               dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
23116 +               dctl.b.sftdiscon = 0;
23117 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
23118 +       }
23119 +}
23120 +
23121 +/**
23122 + * This function enables the Host mode interrupts.
23123 + *
23124 + * @param core_if Programming view of DWC_otg controller
23125 + */
23126 +void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if)
23127 +{
23128 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23129 +       gintmsk_data_t intr_mask = {.d32 = 0 };
23130 +
23131 +       DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if);
23132 +
23133 +       /* Disable all interrupts. */
23134 +       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
23135 +
23136 +       /* Clear any pending interrupts. */
23137 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
23138 +
23139 +       /* Enable the common interrupts */
23140 +       dwc_otg_enable_common_interrupts(core_if);
23141 +
23142 +       /*
23143 +        * Enable host mode interrupts without disturbing common
23144 +        * interrupts.
23145 +        */
23146 +
23147 +       intr_mask.b.disconnect = 1;
23148 +       intr_mask.b.portintr = 1;
23149 +       intr_mask.b.hcintr = 1;
23150 +
23151 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
23152 +}
23153 +
23154 +/**
23155 + * This function disables the Host Mode interrupts.
23156 + *
23157 + * @param core_if Programming view of DWC_otg controller
23158 + */
23159 +void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if)
23160 +{
23161 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23162 +       gintmsk_data_t intr_mask = {.d32 = 0 };
23163 +
23164 +       DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);
23165 +
23166 +       /*
23167 +        * Disable host mode interrupts without disturbing common
23168 +        * interrupts.
23169 +        */
23170 +       intr_mask.b.sofintr = 1;
23171 +       intr_mask.b.portintr = 1;
23172 +       intr_mask.b.hcintr = 1;
23173 +       intr_mask.b.ptxfempty = 1;
23174 +       intr_mask.b.nptxfempty = 1;
23175 +
23176 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0);
23177 +}
23178 +
23179 +/**
23180 + * This function initializes the DWC_otg controller registers for
23181 + * host mode.
23182 + *
23183 + * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
23184 + * request queues. Host channels are reset to ensure that they are ready for
23185 + * performing transfers.
23186 + *
23187 + * @param core_if Programming view of DWC_otg controller
23188 + *
23189 + */
23190 +void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if)
23191 +{
23192 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23193 +       dwc_otg_host_if_t *host_if = core_if->host_if;
23194 +       dwc_otg_core_params_t *params = core_if->core_params;
23195 +       hprt0_data_t hprt0 = {.d32 = 0 };
23196 +       fifosize_data_t nptxfifosize;
23197 +       fifosize_data_t ptxfifosize;
23198 +       uint16_t rxfsiz, nptxfsiz, hptxfsiz;
23199 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
23200 +       int i;
23201 +       hcchar_data_t hcchar;
23202 +       hcfg_data_t hcfg;
23203 +       hfir_data_t hfir;
23204 +       dwc_otg_hc_regs_t *hc_regs;
23205 +       int num_channels;
23206 +       gotgctl_data_t gotgctl = {.d32 = 0 };
23207 +
23208 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
23209 +
23210 +       /* Restart the Phy Clock */
23211 +       DWC_WRITE_REG32(core_if->pcgcctl, 0);
23212 +
23213 +       /* Initialize Host Configuration Register */
23214 +       init_fslspclksel(core_if);
23215 +       if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
23216 +               hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
23217 +               hcfg.b.fslssupp = 1;
23218 +               DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
23219 +
23220 +       }
23221 +
23222 +       /* This bit allows dynamic reloading of the HFIR register
23223 +        * during runtime. This bit needs to be programmed during 
23224 +        * initial configuration and its value must not be changed
23225 +        * during runtime.*/
23226 +       if (core_if->core_params->reload_ctl == 1) {
23227 +               hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
23228 +               hfir.b.hfirrldctrl = 1;
23229 +               DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
23230 +       }
23231 +
23232 +       if (core_if->core_params->dma_desc_enable) {
23233 +               uint8_t op_mode = core_if->hwcfg2.b.op_mode;
23234 +               if (!
23235 +                   (core_if->hwcfg4.b.desc_dma
23236 +                    && (core_if->snpsid >= OTG_CORE_REV_2_90a)
23237 +                    && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
23238 +                        || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
23239 +                        || (op_mode ==
23240 +                            DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG)
23241 +                        || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)
23242 +                        || (op_mode ==
23243 +                            DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
23244 +
23245 +                       DWC_ERROR("Host can't operate in Descriptor DMA mode.\n"
23246 +                                 "Either core version is below 2.90a or "
23247 +                                 "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
23248 +                                 "To run the driver in Buffer DMA host mode set dma_desc_enable "
23249 +                                 "module parameter to 0.\n");
23250 +                       return;
23251 +               }
23252 +               hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
23253 +               hcfg.b.descdma = 1;
23254 +               DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
23255 +       }
23256 +
23257 +       /* Configure data FIFO sizes */
23258 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
23259 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
23260 +                           core_if->total_fifo_size);
23261 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
23262 +                           params->host_rx_fifo_size);
23263 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
23264 +                           params->host_nperio_tx_fifo_size);
23265 +               DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n",
23266 +                           params->host_perio_tx_fifo_size);
23267 +
23268 +               /* Rx FIFO */
23269 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
23270 +                           DWC_READ_REG32(&global_regs->grxfsiz));
23271 +               DWC_WRITE_REG32(&global_regs->grxfsiz,
23272 +                               params->host_rx_fifo_size);
23273 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
23274 +                           DWC_READ_REG32(&global_regs->grxfsiz));
23275 +
23276 +               /* Non-periodic Tx FIFO */
23277 +               DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
23278 +                           DWC_READ_REG32(&global_regs->gnptxfsiz));
23279 +               nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
23280 +               nptxfifosize.b.startaddr = params->host_rx_fifo_size;
23281 +               DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
23282 +               DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
23283 +                           DWC_READ_REG32(&global_regs->gnptxfsiz));
23284 +
23285 +               /* Periodic Tx FIFO */
23286 +               DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",
23287 +                           DWC_READ_REG32(&global_regs->hptxfsiz));
23288 +               ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
23289 +               ptxfifosize.b.startaddr =
23290 +                   nptxfifosize.b.startaddr + nptxfifosize.b.depth;
23291 +               DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32);
23292 +               DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",
23293 +                           DWC_READ_REG32(&global_regs->hptxfsiz));
23294 +               
23295 +               if (core_if->en_multiple_tx_fifo
23296 +                   && core_if->snpsid <= OTG_CORE_REV_2_94a) {
23297 +                       /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */
23298 +                       gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
23299 +                       rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
23300 +                       nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
23301 +                       hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16);
23302 +                       gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz;
23303 +                       DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
23304 +               }
23305 +       }
23306 +
23307 +       /* TODO - check this */
23308 +       /* Clear Host Set HNP Enable in the OTG Control Register */
23309 +       gotgctl.b.hstsethnpen = 1;
23310 +       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
23311 +       /* Make sure the FIFOs are flushed. */
23312 +       dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ );
23313 +       dwc_otg_flush_rx_fifo(core_if);
23314 +
23315 +       /* Clear Host Set HNP Enable in the OTG Control Register */
23316 +       gotgctl.b.hstsethnpen = 1;
23317 +       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
23318 +
23319 +       if (!core_if->core_params->dma_desc_enable) {
23320 +               /* Flush out any leftover queued requests. */
23321 +               num_channels = core_if->core_params->host_channels;
23322 +
23323 +               for (i = 0; i < num_channels; i++) {
23324 +                       hc_regs = core_if->host_if->hc_regs[i];
23325 +                       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23326 +                       hcchar.b.chen = 0;
23327 +                       hcchar.b.chdis = 1;
23328 +                       hcchar.b.epdir = 0;
23329 +                       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23330 +               }
23331 +
23332 +               /* Halt all channels to put them into a known state. */
23333 +               for (i = 0; i < num_channels; i++) {
23334 +                       int count = 0;
23335 +                       hc_regs = core_if->host_if->hc_regs[i];
23336 +                       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23337 +                       hcchar.b.chen = 1;
23338 +                       hcchar.b.chdis = 1;
23339 +                       hcchar.b.epdir = 0;
23340 +                       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23341 +                       DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
23342 +                       do {
23343 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23344 +                               if (++count > 1000) {
23345 +                                       DWC_ERROR
23346 +                                           ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
23347 +                                            __func__, i, hcchar.d32, &hc_regs->hcchar);
23348 +                                       break;
23349 +                               }
23350 +                               dwc_udelay(1);
23351 +                       } while (hcchar.b.chen);
23352 +               }
23353 +       }
23354 +
23355 +       /* Turn on the vbus power. */
23356 +       DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state);
23357 +       if (core_if->op_state == A_HOST) {
23358 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
23359 +               DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr);
23360 +               if (hprt0.b.prtpwr == 0) {
23361 +                       hprt0.b.prtpwr = 1;
23362 +                       DWC_WRITE_REG32(host_if->hprt0, hprt0.d32);
23363 +               }
23364 +       }
23365 +
23366 +       dwc_otg_enable_host_interrupts(core_if);
23367 +}
23368 +
23369 +/**
23370 + * Prepares a host channel for transferring packets to/from a specific
23371 + * endpoint. The HCCHARn register is set up with the characteristics specified
23372 + * in _hc. Host channel interrupts that may need to be serviced while this
23373 + * transfer is in progress are enabled.
23374 + *
23375 + * @param core_if Programming view of DWC_otg controller
23376 + * @param hc Information needed to initialize the host channel
23377 + */
23378 +void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23379 +{
23380 +       uint32_t intr_enable;
23381 +       hcintmsk_data_t hc_intr_mask;
23382 +       gintmsk_data_t gintmsk = {.d32 = 0 };
23383 +       hcchar_data_t hcchar;
23384 +       hcsplt_data_t hcsplt;
23385 +
23386 +       uint8_t hc_num = hc->hc_num;
23387 +       dwc_otg_host_if_t *host_if = core_if->host_if;
23388 +       dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
23389 +
23390 +       /* Clear old interrupt conditions for this host channel. */
23391 +       hc_intr_mask.d32 = 0xFFFFFFFF;
23392 +       hc_intr_mask.b.reserved14_31 = 0;
23393 +       DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32);
23394 +
23395 +       /* Enable channel interrupts required for this transfer. */
23396 +       hc_intr_mask.d32 = 0;
23397 +       hc_intr_mask.b.chhltd = 1;
23398 +       if (core_if->dma_enable) {
23399 +               /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */
23400 +               if (!core_if->dma_desc_enable)
23401 +                       hc_intr_mask.b.ahberr = 1;
23402 +               else {
23403 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23404 +                               hc_intr_mask.b.xfercompl = 1;
23405 +               }
23406 +
23407 +               if (hc->error_state && !hc->do_split &&
23408 +                   hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
23409 +                       hc_intr_mask.b.ack = 1;
23410 +                       if (hc->ep_is_in) {
23411 +                               hc_intr_mask.b.datatglerr = 1;
23412 +                               if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23413 +                                       hc_intr_mask.b.nak = 1;
23414 +                               }
23415 +                       }
23416 +               }
23417 +       } else {
23418 +               switch (hc->ep_type) {
23419 +               case DWC_OTG_EP_TYPE_CONTROL:
23420 +               case DWC_OTG_EP_TYPE_BULK:
23421 +                       hc_intr_mask.b.xfercompl = 1;
23422 +                       hc_intr_mask.b.stall = 1;
23423 +                       hc_intr_mask.b.xacterr = 1;
23424 +                       hc_intr_mask.b.datatglerr = 1;
23425 +                       if (hc->ep_is_in) {
23426 +                               hc_intr_mask.b.bblerr = 1;
23427 +                       } else {
23428 +                               hc_intr_mask.b.nak = 1;
23429 +                               hc_intr_mask.b.nyet = 1;
23430 +                               if (hc->do_ping) {
23431 +                                       hc_intr_mask.b.ack = 1;
23432 +                               }
23433 +                       }
23434 +
23435 +                       if (hc->do_split) {
23436 +                               hc_intr_mask.b.nak = 1;
23437 +                               if (hc->complete_split) {
23438 +                                       hc_intr_mask.b.nyet = 1;
23439 +                               } else {
23440 +                                       hc_intr_mask.b.ack = 1;
23441 +                               }
23442 +                       }
23443 +
23444 +                       if (hc->error_state) {
23445 +                               hc_intr_mask.b.ack = 1;
23446 +                       }
23447 +                       break;
23448 +               case DWC_OTG_EP_TYPE_INTR:
23449 +                       hc_intr_mask.b.xfercompl = 1;
23450 +                       hc_intr_mask.b.nak = 1;
23451 +                       hc_intr_mask.b.stall = 1;
23452 +                       hc_intr_mask.b.xacterr = 1;
23453 +                       hc_intr_mask.b.datatglerr = 1;
23454 +                       hc_intr_mask.b.frmovrun = 1;
23455 +
23456 +                       if (hc->ep_is_in) {
23457 +                               hc_intr_mask.b.bblerr = 1;
23458 +                       }
23459 +                       if (hc->error_state) {
23460 +                               hc_intr_mask.b.ack = 1;
23461 +                       }
23462 +                       if (hc->do_split) {
23463 +                               if (hc->complete_split) {
23464 +                                       hc_intr_mask.b.nyet = 1;
23465 +                               } else {
23466 +                                       hc_intr_mask.b.ack = 1;
23467 +                               }
23468 +                       }
23469 +                       break;
23470 +               case DWC_OTG_EP_TYPE_ISOC:
23471 +                       hc_intr_mask.b.xfercompl = 1;
23472 +                       hc_intr_mask.b.frmovrun = 1;
23473 +                       hc_intr_mask.b.ack = 1;
23474 +
23475 +                       if (hc->ep_is_in) {
23476 +                               hc_intr_mask.b.xacterr = 1;
23477 +                               hc_intr_mask.b.bblerr = 1;
23478 +                       }
23479 +                       break;
23480 +               }
23481 +       }
23482 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32);
23483 +
23484 +       /* Enable the top level host channel interrupt. */
23485 +       intr_enable = (1 << hc_num);
23486 +       DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
23487 +
23488 +       /* Make sure host channel interrupts are enabled. */
23489 +       gintmsk.b.hcintr = 1;
23490 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
23491 +
23492 +       /*
23493 +        * Program the HCCHARn register with the endpoint characteristics for
23494 +        * the current transfer.
23495 +        */
23496 +       hcchar.d32 = 0;
23497 +       hcchar.b.devaddr = hc->dev_addr;
23498 +       hcchar.b.epnum = hc->ep_num;
23499 +       hcchar.b.epdir = hc->ep_is_in;
23500 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
23501 +       hcchar.b.eptype = hc->ep_type;
23502 +       hcchar.b.mps = hc->max_packet;
23503 +
23504 +       DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
23505 +
23506 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n",
23507 +                    __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum);
23508 +       DWC_DEBUGPL(DBG_HCDV, "  Is In %d, Is Low Speed %d, EP Type %d, "
23509 +                                "Max Pkt %d, Multi Cnt %d\n",
23510 +                    hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype,
23511 +                    hcchar.b.mps, hcchar.b.multicnt);
23512 +
23513 +       /*
23514 +        * Program the HCSPLIT register for SPLITs
23515 +        */
23516 +       hcsplt.d32 = 0;
23517 +       if (hc->do_split) {
23518 +               DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n",
23519 +                           hc->hc_num,
23520 +                           hc->complete_split ? "CSPLIT" : "SSPLIT");
23521 +               hcsplt.b.compsplt = hc->complete_split;
23522 +               hcsplt.b.xactpos = hc->xact_pos;
23523 +               hcsplt.b.hubaddr = hc->hub_addr;
23524 +               hcsplt.b.prtaddr = hc->port_addr;
23525 +               DWC_DEBUGPL(DBG_HCDV, "\t  comp split %d\n", hc->complete_split);
23526 +               DWC_DEBUGPL(DBG_HCDV, "\t  xact pos %d\n", hc->xact_pos);
23527 +               DWC_DEBUGPL(DBG_HCDV, "\t  hub addr %d\n", hc->hub_addr);
23528 +               DWC_DEBUGPL(DBG_HCDV, "\t  port addr %d\n", hc->port_addr);
23529 +               DWC_DEBUGPL(DBG_HCDV, "\t  is_in %d\n", hc->ep_is_in);
23530 +               DWC_DEBUGPL(DBG_HCDV, "\t  Max Pkt: %d\n", hcchar.b.mps);
23531 +               DWC_DEBUGPL(DBG_HCDV, "\t  xferlen: %d\n", hc->xfer_len);
23532 +       }
23533 +       DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
23534 +
23535 +}
23536 +
23537 +/**
23538 + * Attempts to halt a host channel. This function should only be called in
23539 + * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
23540 + * normal circumstances in DMA mode, the controller halts the channel when the
23541 + * transfer is complete or a condition occurs that requires application
23542 + * intervention.
23543 + *
23544 + * In slave mode, checks for a free request queue entry, then sets the Channel
23545 + * Enable and Channel Disable bits of the Host Channel Characteristics
23546 + * register of the specified channel to intiate the halt. If there is no free
23547 + * request queue entry, sets only the Channel Disable bit of the HCCHARn
23548 + * register to flush requests for this channel. In the latter case, sets a
23549 + * flag to indicate that the host channel needs to be halted when a request
23550 + * queue slot is open.
23551 + *
23552 + * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
23553 + * HCCHARn register. The controller ensures there is space in the request
23554 + * queue before submitting the halt request.
23555 + *
23556 + * Some time may elapse before the core flushes any posted requests for this
23557 + * host channel and halts. The Channel Halted interrupt handler completes the
23558 + * deactivation of the host channel.
23559 + *
23560 + * @param core_if Controller register interface.
23561 + * @param hc Host channel to halt.
23562 + * @param halt_status Reason for halting the channel.
23563 + */
23564 +void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if,
23565 +                    dwc_hc_t * hc, dwc_otg_halt_status_e halt_status)
23566 +{
23567 +       gnptxsts_data_t nptxsts;
23568 +       hptxsts_data_t hptxsts;
23569 +       hcchar_data_t hcchar;
23570 +       dwc_otg_hc_regs_t *hc_regs;
23571 +       dwc_otg_core_global_regs_t *global_regs;
23572 +       dwc_otg_host_global_regs_t *host_global_regs;
23573 +
23574 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23575 +       global_regs = core_if->core_global_regs;
23576 +       host_global_regs = core_if->host_if->host_global_regs;
23577 +
23578 +       DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS),
23579 +                  "halt_status = %d\n", halt_status);
23580 +
23581 +       if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
23582 +           halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
23583 +               /*
23584 +                * Disable all channel interrupts except Ch Halted. The QTD
23585 +                * and QH state associated with this transfer has been cleared
23586 +                * (in the case of URB_DEQUEUE), so the channel needs to be
23587 +                * shut down carefully to prevent crashes.
23588 +                */
23589 +               hcintmsk_data_t hcintmsk;
23590 +               hcintmsk.d32 = 0;
23591 +               hcintmsk.b.chhltd = 1;
23592 +               DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32);
23593 +
23594 +               /*
23595 +                * Make sure no other interrupts besides halt are currently
23596 +                * pending. Handling another interrupt could cause a crash due
23597 +                * to the QTD and QH state.
23598 +                */
23599 +               DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32);
23600 +
23601 +               /*
23602 +                * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
23603 +                * even if the channel was already halted for some other
23604 +                * reason.
23605 +                */
23606 +               hc->halt_status = halt_status;
23607 +
23608 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23609 +               if (hcchar.b.chen == 0) {
23610 +                       /*
23611 +                        * The channel is either already halted or it hasn't
23612 +                        * started yet. In DMA mode, the transfer may halt if
23613 +                        * it finishes normally or a condition occurs that
23614 +                        * requires driver intervention. Don't want to halt
23615 +                        * the channel again. In either Slave or DMA mode,
23616 +                        * it's possible that the transfer has been assigned
23617 +                        * to a channel, but not started yet when an URB is
23618 +                        * dequeued. Don't want to halt a channel that hasn't
23619 +                        * started yet.
23620 +                        */
23621 +                       return;
23622 +               }
23623 +       }
23624 +       if (hc->halt_pending) {
23625 +               /*
23626 +                * A halt has already been issued for this channel. This might
23627 +                * happen when a transfer is aborted by a higher level in
23628 +                * the stack.
23629 +                */
23630 +#ifdef DEBUG
23631 +               DWC_PRINTF
23632 +                   ("*** %s: Channel %d, _hc->halt_pending already set ***\n",
23633 +                    __func__, hc->hc_num);
23634 +
23635 +#endif
23636 +               return;
23637 +       }
23638 +
23639 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23640 +
23641 +       /* No need to set the bit in DDMA for disabling the channel */
23642 +       //TODO check it everywhere channel is disabled          
23643 +       if (!core_if->core_params->dma_desc_enable)
23644 +               hcchar.b.chen = 1;
23645 +       hcchar.b.chdis = 1;
23646 +
23647 +       if (!core_if->dma_enable) {
23648 +               /* Check for space in the request queue to issue the halt. */
23649 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
23650 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
23651 +                       nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
23652 +                       if (nptxsts.b.nptxqspcavail == 0) {
23653 +                               hcchar.b.chen = 0;
23654 +                       }
23655 +               } else {
23656 +                       hptxsts.d32 =
23657 +                           DWC_READ_REG32(&host_global_regs->hptxsts);
23658 +                       if ((hptxsts.b.ptxqspcavail == 0)
23659 +                           || (core_if->queuing_high_bandwidth)) {
23660 +                               hcchar.b.chen = 0;
23661 +                       }
23662 +               }
23663 +       }
23664 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23665 +
23666 +       hc->halt_status = halt_status;
23667 +
23668 +       if (hcchar.b.chen) {
23669 +               hc->halt_pending = 1;
23670 +               hc->halt_on_queue = 0;
23671 +       } else {
23672 +               hc->halt_on_queue = 1;
23673 +       }
23674 +
23675 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23676 +       DWC_DEBUGPL(DBG_HCDV, "  hcchar: 0x%08x\n", hcchar.d32);
23677 +       DWC_DEBUGPL(DBG_HCDV, "  halt_pending: %d\n", hc->halt_pending);
23678 +       DWC_DEBUGPL(DBG_HCDV, "  halt_on_queue: %d\n", hc->halt_on_queue);
23679 +       DWC_DEBUGPL(DBG_HCDV, "  halt_status: %d\n", hc->halt_status);
23680 +
23681 +       return;
23682 +}
23683 +
23684 +/**
23685 + * Clears the transfer state for a host channel. This function is normally
23686 + * called after a transfer is done and the host channel is being released.
23687 + *
23688 + * @param core_if Programming view of DWC_otg controller.
23689 + * @param hc Identifies the host channel to clean up.
23690 + */
23691 +void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23692 +{
23693 +       dwc_otg_hc_regs_t *hc_regs;
23694 +
23695 +       hc->xfer_started = 0;
23696 +
23697 +       /*
23698 +        * Clear channel interrupt enables and any unhandled channel interrupt
23699 +        * conditions.
23700 +        */
23701 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23702 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0);
23703 +       DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF);
23704 +#ifdef DEBUG
23705 +       DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]);
23706 +#endif
23707 +}
23708 +
23709 +/**
23710 + * Sets the channel property that indicates in which frame a periodic transfer
23711 + * should occur. This is always set to the _next_ frame. This function has no
23712 + * effect on non-periodic transfers.
23713 + *
23714 + * @param core_if Programming view of DWC_otg controller.
23715 + * @param hc Identifies the host channel to set up and its properties.
23716 + * @param hcchar Current value of the HCCHAR register for the specified host
23717 + * channel.
23718 + */
23719 +static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if,
23720 +                                        dwc_hc_t * hc, hcchar_data_t * hcchar)
23721 +{
23722 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23723 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23724 +               hfnum_data_t hfnum;
23725 +               hfnum.d32 =
23726 +                   DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum);
23727 +
23728 +               /* 1 if _next_ frame is odd, 0 if it's even */
23729 +               hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
23730 +#ifdef DEBUG
23731 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split
23732 +                   && !hc->complete_split) {
23733 +                       switch (hfnum.b.frnum & 0x7) {
23734 +                       case 7:
23735 +                               core_if->hfnum_7_samples++;
23736 +                               core_if->hfnum_7_frrem_accum += hfnum.b.frrem;
23737 +                               break;
23738 +                       case 0:
23739 +                               core_if->hfnum_0_samples++;
23740 +                               core_if->hfnum_0_frrem_accum += hfnum.b.frrem;
23741 +                               break;
23742 +                       default:
23743 +                               core_if->hfnum_other_samples++;
23744 +                               core_if->hfnum_other_frrem_accum +=
23745 +                                   hfnum.b.frrem;
23746 +                               break;
23747 +                       }
23748 +               }
23749 +#endif
23750 +       }
23751 +}
23752 +
23753 +#ifdef DEBUG
23754 +void hc_xfer_timeout(void *ptr)
23755 +{
23756 +       hc_xfer_info_t *xfer_info = NULL;
23757 +       int hc_num = 0;
23758 +
23759 +       if (ptr)
23760 +               xfer_info = (hc_xfer_info_t *) ptr;
23761 +
23762 +       if (!xfer_info->hc) {
23763 +               DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc);
23764 +               return;
23765 +       }
23766 +
23767 +       hc_num = xfer_info->hc->hc_num;
23768 +       DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);
23769 +       DWC_WARN("      start_hcchar_val 0x%08x\n",
23770 +                xfer_info->core_if->start_hcchar_val[hc_num]);
23771 +}
23772 +#endif
23773 +
23774 +void ep_xfer_timeout(void *ptr)
23775 +{
23776 +       ep_xfer_info_t *xfer_info = NULL;
23777 +       int ep_num = 0;
23778 +       dctl_data_t dctl = {.d32 = 0 };
23779 +       gintsts_data_t gintsts = {.d32 = 0 };
23780 +       gintmsk_data_t gintmsk = {.d32 = 0 };
23781 +
23782 +       if (ptr)
23783 +               xfer_info = (ep_xfer_info_t *) ptr;
23784 +
23785 +       if (!xfer_info->ep) {
23786 +               DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep);
23787 +               return;
23788 +       }
23789 +
23790 +       ep_num = xfer_info->ep->num;
23791 +       DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num);
23792 +       /* Put the sate to 2 as it was time outed */
23793 +       xfer_info->state = 2;
23794 +
23795 +       dctl.d32 =
23796 +           DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl);
23797 +       gintsts.d32 =
23798 +           DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts);
23799 +       gintmsk.d32 =
23800 +           DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk);
23801 +
23802 +       if (!gintmsk.b.goutnakeff) {
23803 +               /* Unmask it */
23804 +               gintmsk.b.goutnakeff = 1;
23805 +               DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk,
23806 +                               gintmsk.d32);
23807 +
23808 +       }
23809 +
23810 +       if (!gintsts.b.goutnakeff) {
23811 +               dctl.b.sgoutnak = 1;
23812 +       }
23813 +       DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl,
23814 +                       dctl.d32);
23815 +
23816 +}
23817 +
23818 +void set_pid_isoc(dwc_hc_t * hc)
23819 +{
23820 +       /* Set up the initial PID for the transfer. */
23821 +       if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {
23822 +               if (hc->ep_is_in) {
23823 +                       if (hc->multi_count == 1) {
23824 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23825 +                       } else if (hc->multi_count == 2) {
23826 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
23827 +                       } else {
23828 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA2;
23829 +                       }
23830 +               } else {
23831 +                       if (hc->multi_count == 1) {
23832 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23833 +                       } else {
23834 +                               hc->data_pid_start = DWC_OTG_HC_PID_MDATA;
23835 +                       }
23836 +               }
23837 +       } else {
23838 +               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23839 +       }
23840 +}
23841 +
23842 +/**
23843 + * This function does the setup for a data transfer for a host channel and
23844 + * starts the transfer. May be called in either Slave mode or DMA mode. In
23845 + * Slave mode, the caller must ensure that there is sufficient space in the
23846 + * request queue and Tx Data FIFO.
23847 + *
23848 + * For an OUT transfer in Slave mode, it loads a data packet into the
23849 + * appropriate FIFO. If necessary, additional data packets will be loaded in
23850 + * the Host ISR.
23851 + *
23852 + * For an IN transfer in Slave mode, a data packet is requested. The data
23853 + * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
23854 + * additional data packets are requested in the Host ISR.
23855 + *
23856 + * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
23857 + * register along with a packet count of 1 and the channel is enabled. This
23858 + * causes a single PING transaction to occur. Other fields in HCTSIZ are
23859 + * simply set to 0 since no data transfer occurs in this case.
23860 + *
23861 + * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
23862 + * all the information required to perform the subsequent data transfer. In
23863 + * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
23864 + * controller performs the entire PING protocol, then starts the data
23865 + * transfer.
23866 + *
23867 + * @param core_if Programming view of DWC_otg controller.
23868 + * @param hc Information needed to initialize the host channel. The xfer_len
23869 + * value may be reduced to accommodate the max widths of the XferSize and
23870 + * PktCnt fields in the HCTSIZn register. The multi_count value may be changed
23871 + * to reflect the final xfer_len value.
23872 + */
23873 +void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23874 +{
23875 +       hcchar_data_t hcchar;
23876 +       hctsiz_data_t hctsiz;
23877 +       uint16_t num_packets;
23878 +       uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size;
23879 +       uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count;
23880 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23881 +
23882 +       hctsiz.d32 = 0;
23883 +
23884 +       if (hc->do_ping) {
23885 +               if (!core_if->dma_enable) {
23886 +                       dwc_otg_hc_do_ping(core_if, hc);
23887 +                       hc->xfer_started = 1;
23888 +                       return;
23889 +               } else {
23890 +                       hctsiz.b.dopng = 1;
23891 +               }
23892 +       }
23893 +
23894 +       if (hc->do_split) {
23895 +               num_packets = 1;
23896 +
23897 +               if (hc->complete_split && !hc->ep_is_in) {
23898 +                       /* For CSPLIT OUT Transfer, set the size to 0 so the
23899 +                        * core doesn't expect any data written to the FIFO */
23900 +                       hc->xfer_len = 0;
23901 +               } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
23902 +                       hc->xfer_len = hc->max_packet;
23903 +               } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
23904 +                       hc->xfer_len = 188;
23905 +               }
23906 +
23907 +               hctsiz.b.xfersize = hc->xfer_len;
23908 +       } else {
23909 +               /*
23910 +                * Ensure that the transfer length and packet count will fit
23911 +                * in the widths allocated for them in the HCTSIZn register.
23912 +                */
23913 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23914 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23915 +                       /*
23916 +                        * Make sure the transfer size is no larger than one
23917 +                        * (micro)frame's worth of data. (A check was done
23918 +                        * when the periodic transfer was accepted to ensure
23919 +                        * that a (micro)frame's worth of data can be
23920 +                        * programmed into a channel.)
23921 +                        */
23922 +                       uint32_t max_periodic_len =
23923 +                           hc->multi_count * hc->max_packet;
23924 +                       if (hc->xfer_len > max_periodic_len) {
23925 +                               hc->xfer_len = max_periodic_len;
23926 +                       } else {
23927 +                       }
23928 +               } else if (hc->xfer_len > max_hc_xfer_size) {
23929 +                       /* Make sure that xfer_len is a multiple of max packet size. */
23930 +                       hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;
23931 +               }
23932 +
23933 +               if (hc->xfer_len > 0) {
23934 +                       num_packets =
23935 +                           (hc->xfer_len + hc->max_packet -
23936 +                            1) / hc->max_packet;
23937 +                       if (num_packets > max_hc_pkt_count) {
23938 +                               num_packets = max_hc_pkt_count;
23939 +                               hc->xfer_len = num_packets * hc->max_packet;
23940 +                       }
23941 +               } else {
23942 +                       /* Need 1 packet for transfer length of 0. */
23943 +                       num_packets = 1;
23944 +               }
23945 +
23946 +               if (hc->ep_is_in) {
23947 +                       /* Always program an integral # of max packets for IN transfers. */
23948 +                       hc->xfer_len = num_packets * hc->max_packet;
23949 +               }
23950 +
23951 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23952 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23953 +                       /*
23954 +                        * Make sure that the multi_count field matches the
23955 +                        * actual transfer length.
23956 +                        */
23957 +                       hc->multi_count = num_packets;
23958 +               }
23959 +
23960 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23961 +                       set_pid_isoc(hc);
23962 +
23963 +               hctsiz.b.xfersize = hc->xfer_len;
23964 +       }
23965 +
23966 +       hc->start_pkt_count = num_packets;
23967 +       hctsiz.b.pktcnt = num_packets;
23968 +       hctsiz.b.pid = hc->data_pid_start;
23969 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23970 +
23971 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23972 +       DWC_DEBUGPL(DBG_HCDV, "  Xfer Size: %d\n", hctsiz.b.xfersize);
23973 +       DWC_DEBUGPL(DBG_HCDV, "  Num Pkts: %d\n", hctsiz.b.pktcnt);
23974 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
23975 +
23976 +       if (core_if->dma_enable) {
23977 +               dwc_dma_t dma_addr;
23978 +               if (hc->align_buff) {
23979 +                       dma_addr = hc->align_buff;
23980 +               } else {
23981 +                       dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff);
23982 +               }
23983 +               DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr);
23984 +       }
23985 +
23986 +       /* Start the split */
23987 +       if (hc->do_split) {
23988 +               hcsplt_data_t hcsplt;
23989 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
23990 +               hcsplt.b.spltena = 1;
23991 +               DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32);
23992 +       }
23993 +
23994 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23995 +       hcchar.b.multicnt = hc->multi_count;
23996 +       hc_set_even_odd_frame(core_if, hc, &hcchar);
23997 +#ifdef DEBUG
23998 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
23999 +       if (hcchar.b.chdis) {
24000 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
24001 +                        __func__, hc->hc_num, hcchar.d32);
24002 +       }
24003 +#endif
24004 +
24005 +       /* Set host channel enable after all other setup is complete. */
24006 +       hcchar.b.chen = 1;
24007 +       hcchar.b.chdis = 0;
24008 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24009 +
24010 +       hc->xfer_started = 1;
24011 +       hc->requests++;
24012 +
24013 +       if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) {
24014 +               /* Load OUT packet into the appropriate Tx FIFO. */
24015 +               dwc_otg_hc_write_packet(core_if, hc);
24016 +       }
24017 +#ifdef DEBUG
24018 +       if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
24019 +                DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n",
24020 +                            hc->hc_num, core_if);//GRAYG
24021 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
24022 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
24023 +
24024 +               /* Start a timer for this transfer. */
24025 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
24026 +       }
24027 +#endif
24028 +}
24029 +
24030 +/**
24031 + * This function does the setup for a data transfer for a host channel
24032 + * and starts the transfer in Descriptor DMA mode.
24033 + *
24034 + * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.
24035 + * Sets PID and NTD values. For periodic transfers
24036 + * initializes SCHED_INFO field with micro-frame bitmap.
24037 + *
24038 + * Initializes HCDMA register with descriptor list address and CTD value
24039 + * then starts the transfer via enabling the channel.
24040 + *
24041 + * @param core_if Programming view of DWC_otg controller.
24042 + * @param hc Information needed to initialize the host channel.
24043 + */
24044 +void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24045 +{
24046 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24047 +       hcchar_data_t hcchar;
24048 +       hctsiz_data_t hctsiz;
24049 +       hcdma_data_t hcdma;
24050 +
24051 +       hctsiz.d32 = 0;
24052 +
24053 +       if (hc->do_ping)
24054 +               hctsiz.b_ddma.dopng = 1;
24055 +
24056 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
24057 +               set_pid_isoc(hc);
24058 +
24059 +       /* Packet Count and Xfer Size are not used in Descriptor DMA mode */
24060 +       hctsiz.b_ddma.pid = hc->data_pid_start;
24061 +       hctsiz.b_ddma.ntd = hc->ntd - 1;        /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */
24062 +       hctsiz.b_ddma.schinfo = hc->schinfo;    /* Non-zero only for high-speed interrupt endpoints */
24063 +
24064 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24065 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
24066 +       DWC_DEBUGPL(DBG_HCDV, "  NTD: %d\n", hctsiz.b_ddma.ntd);
24067 +
24068 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
24069 +
24070 +       hcdma.d32 = 0;
24071 +       hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11;
24072 +
24073 +       /* Always start from first descriptor. */
24074 +       hcdma.b.ctd = 0;
24075 +       DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32);
24076 +
24077 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24078 +       hcchar.b.multicnt = hc->multi_count;
24079 +
24080 +#ifdef DEBUG
24081 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
24082 +       if (hcchar.b.chdis) {
24083 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
24084 +                        __func__, hc->hc_num, hcchar.d32);
24085 +       }
24086 +#endif
24087 +
24088 +       /* Set host channel enable after all other setup is complete. */
24089 +       hcchar.b.chen = 1;
24090 +       hcchar.b.chdis = 0;
24091 +
24092 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24093 +
24094 +       hc->xfer_started = 1;
24095 +       hc->requests++;
24096 +
24097 +#ifdef DEBUG
24098 +       if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR)
24099 +           && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) {
24100 +                DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n",
24101 +                            hc->hc_num, core_if);//GRAYG
24102 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
24103 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
24104 +               /* Start a timer for this transfer. */
24105 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
24106 +       }
24107 +#endif
24108 +
24109 +}
24110 +
24111 +/**
24112 + * This function continues a data transfer that was started by previous call
24113 + * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is
24114 + * sufficient space in the request queue and Tx Data FIFO. This function
24115 + * should only be called in Slave mode. In DMA mode, the controller acts
24116 + * autonomously to complete transfers programmed to a host channel.
24117 + *
24118 + * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
24119 + * if there is any data remaining to be queued. For an IN transfer, another
24120 + * data packet is always requested. For the SETUP phase of a control transfer,
24121 + * this function does nothing.
24122 + *
24123 + * @return 1 if a new request is queued, 0 if no more requests are required
24124 + * for this transfer.
24125 + */
24126 +int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24127 +{
24128 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24129 +
24130 +       if (hc->do_split) {
24131 +               /* SPLITs always queue just once per channel */
24132 +               return 0;
24133 +       } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
24134 +               /* SETUPs are queued only once since they can't be NAKed. */
24135 +               return 0;
24136 +       } else if (hc->ep_is_in) {
24137 +               /*
24138 +                * Always queue another request for other IN transfers. If
24139 +                * back-to-back INs are issued and NAKs are received for both,
24140 +                * the driver may still be processing the first NAK when the
24141 +                * second NAK is received. When the interrupt handler clears
24142 +                * the NAK interrupt for the first NAK, the second NAK will
24143 +                * not be seen. So we can't depend on the NAK interrupt
24144 +                * handler to requeue a NAKed request. Instead, IN requests
24145 +                * are issued each time this function is called. When the
24146 +                * transfer completes, the extra requests for the channel will
24147 +                * be flushed.
24148 +                */
24149 +               hcchar_data_t hcchar;
24150 +               dwc_otg_hc_regs_t *hc_regs =
24151 +                   core_if->host_if->hc_regs[hc->hc_num];
24152 +
24153 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24154 +               hc_set_even_odd_frame(core_if, hc, &hcchar);
24155 +               hcchar.b.chen = 1;
24156 +               hcchar.b.chdis = 0;
24157 +               DWC_DEBUGPL(DBG_HCDV, "  IN xfer: hcchar = 0x%08x\n",
24158 +                           hcchar.d32);
24159 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24160 +               hc->requests++;
24161 +               return 1;
24162 +       } else {
24163 +               /* OUT transfers. */
24164 +               if (hc->xfer_count < hc->xfer_len) {
24165 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
24166 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
24167 +                               hcchar_data_t hcchar;
24168 +                               dwc_otg_hc_regs_t *hc_regs;
24169 +                               hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24170 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24171 +                               hc_set_even_odd_frame(core_if, hc, &hcchar);
24172 +                       }
24173 +
24174 +                       /* Load OUT packet into the appropriate Tx FIFO. */
24175 +                       dwc_otg_hc_write_packet(core_if, hc);
24176 +                       hc->requests++;
24177 +                       return 1;
24178 +               } else {
24179 +                       return 0;
24180 +               }
24181 +       }
24182 +}
24183 +
24184 +/**
24185 + * Starts a PING transfer. This function should only be called in Slave mode.
24186 + * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
24187 + */
24188 +void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24189 +{
24190 +       hcchar_data_t hcchar;
24191 +       hctsiz_data_t hctsiz;
24192 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24193 +
24194 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24195 +
24196 +       hctsiz.d32 = 0;
24197 +       hctsiz.b.dopng = 1;
24198 +       hctsiz.b.pktcnt = 1;
24199 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
24200 +
24201 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24202 +       hcchar.b.chen = 1;
24203 +       hcchar.b.chdis = 0;
24204 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24205 +}
24206 +
24207 +/*
24208 + * This function writes a packet into the Tx FIFO associated with the Host
24209 + * Channel. For a channel associated with a non-periodic EP, the non-periodic
24210 + * Tx FIFO is written. For a channel associated with a periodic EP, the
24211 + * periodic Tx FIFO is written. This function should only be called in Slave
24212 + * mode.
24213 + *
24214 + * Upon return the xfer_buff and xfer_count fields in _hc are incremented by
24215 + * then number of bytes written to the Tx FIFO.
24216 + */
24217 +void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24218 +{
24219 +       uint32_t i;
24220 +       uint32_t remaining_count;
24221 +       uint32_t byte_count;
24222 +       uint32_t dword_count;
24223 +
24224 +       uint32_t *data_buff = (uint32_t *) (hc->xfer_buff);
24225 +       uint32_t *data_fifo = core_if->data_fifo[hc->hc_num];
24226 +
24227 +       remaining_count = hc->xfer_len - hc->xfer_count;
24228 +       if (remaining_count > hc->max_packet) {
24229 +               byte_count = hc->max_packet;
24230 +       } else {
24231 +               byte_count = remaining_count;
24232 +       }
24233 +
24234 +       dword_count = (byte_count + 3) / 4;
24235 +
24236 +       if ((((unsigned long)data_buff) & 0x3) == 0) {
24237 +               /* xfer_buff is DWORD aligned. */
24238 +               for (i = 0; i < dword_count; i++, data_buff++) {
24239 +                       DWC_WRITE_REG32(data_fifo, *data_buff);
24240 +               }
24241 +       } else {
24242 +               /* xfer_buff is not DWORD aligned. */
24243 +               for (i = 0; i < dword_count; i++, data_buff++) {
24244 +                       uint32_t data;
24245 +                       data =
24246 +                           (data_buff[0] | data_buff[1] << 8 | data_buff[2] <<
24247 +                            16 | data_buff[3] << 24);
24248 +                       DWC_WRITE_REG32(data_fifo, data);
24249 +               }
24250 +       }
24251 +
24252 +       hc->xfer_count += byte_count;
24253 +       hc->xfer_buff += byte_count;
24254 +}
24255 +
24256 +/**
24257 + * Gets the current USB frame number. This is the frame number from the last
24258 + * SOF packet.
24259 + */
24260 +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if)
24261 +{
24262 +       dsts_data_t dsts;
24263 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
24264 +
24265 +       /* read current frame/microframe number from DSTS register */
24266 +       return dsts.b.soffn;
24267 +}
24268 +
24269 +/**
24270 + * Calculates and gets the frame Interval value of HFIR register according PHY 
24271 + * type and speed.The application can modify a value of HFIR register only after
24272 + * the Port Enable bit of the Host Port Control and Status register 
24273 + * (HPRT.PrtEnaPort) has been set.
24274 +*/
24275 +
24276 +uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if)
24277 +{
24278 +       gusbcfg_data_t usbcfg;
24279 +       hwcfg2_data_t hwcfg2;
24280 +       hprt0_data_t hprt0;
24281 +       int clock = 60;         // default value
24282 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
24283 +       hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
24284 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
24285 +       if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
24286 +               clock = 60;
24287 +       if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3)
24288 +               clock = 48;
24289 +       if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24290 +           !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
24291 +               clock = 30;
24292 +       if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24293 +           !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
24294 +               clock = 60;
24295 +       if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24296 +           !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
24297 +               clock = 48;
24298 +       if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2)
24299 +               clock = 48;
24300 +       if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1)
24301 +               clock = 48;
24302 +       if (hprt0.b.prtspd == 0)
24303 +               /* High speed case */
24304 +               return 125 * clock;
24305 +       else
24306 +               /* FS/LS case */
24307 +               return 1000 * clock;
24308 +}
24309 +
24310 +/**
24311 + * This function reads a setup packet from the Rx FIFO into the destination
24312 + * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
24313 + * Interrupt routine when a SETUP packet has been received in Slave mode.
24314 + *
24315 + * @param core_if Programming view of DWC_otg controller.
24316 + * @param dest Destination buffer for packet data.
24317 + */
24318 +void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
24319 +{
24320 +       device_grxsts_data_t status;
24321 +       /* Get the 8 bytes of a setup transaction data */
24322 +
24323 +       /* Pop 2 DWORDS off the receive data FIFO into memory */
24324 +       dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
24325 +       dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
24326 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
24327 +               status.d32 =
24328 +                   DWC_READ_REG32(&core_if->core_global_regs->grxstsp);
24329 +               DWC_DEBUGPL(DBG_ANY,
24330 +                           "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n",
24331 +                           status.b.epnum, status.b.bcnt, status.b.pktsts,
24332 +                           status.b.fn, status.b.fn);
24333 +       }
24334 +}
24335 +
24336 +/**
24337 + * This function enables EP0 OUT to receive SETUP packets and configures EP0
24338 + * IN for transmitting packets. It is normally called when the
24339 + * "Enumeration Done" interrupt occurs.
24340 + *
24341 + * @param core_if Programming view of DWC_otg controller.
24342 + * @param ep The EP0 data.
24343 + */
24344 +void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24345 +{
24346 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24347 +       dsts_data_t dsts;
24348 +       depctl_data_t diepctl;
24349 +       depctl_data_t doepctl;
24350 +       dctl_data_t dctl = {.d32 = 0 };
24351 +
24352 +       ep->stp_rollover = 0;
24353 +       /* Read the Device Status and Endpoint 0 Control registers */
24354 +       dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
24355 +       diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
24356 +       doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
24357 +
24358 +       /* Set the MPS of the IN EP based on the enumeration speed */
24359 +       switch (dsts.b.enumspd) {
24360 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
24361 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
24362 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
24363 +               diepctl.b.mps = DWC_DEP0CTL_MPS_64;
24364 +               break;
24365 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
24366 +               diepctl.b.mps = DWC_DEP0CTL_MPS_8;
24367 +               break;
24368 +       }
24369 +
24370 +       DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
24371 +
24372 +       /* Enable OUT EP for receive */
24373 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
24374 +       doepctl.b.epena = 1;
24375 +       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
24376 +       }
24377 +#ifdef VERBOSE
24378 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
24379 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
24380 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
24381 +                   DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
24382 +#endif
24383 +       dctl.b.cgnpinnak = 1;
24384 +
24385 +       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
24386 +       DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n",
24387 +                   DWC_READ_REG32(&dev_if->dev_global_regs->dctl));
24388 +
24389 +}
24390 +
24391 +/**
24392 + * This function activates an EP.  The Device EP control register for
24393 + * the EP is configured as defined in the ep structure. Note: This
24394 + * function is not used for EP0.
24395 + *
24396 + * @param core_if Programming view of DWC_otg controller.
24397 + * @param ep The EP to activate.
24398 + */
24399 +void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24400 +{
24401 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24402 +       depctl_data_t depctl;
24403 +       volatile uint32_t *addr;
24404 +       daint_data_t daintmsk = {.d32 = 0 };
24405 +       dcfg_data_t dcfg;
24406 +       uint8_t i;
24407 +
24408 +       DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num,
24409 +                   (ep->is_in ? "IN" : "OUT"));
24410 +
24411 +#ifdef DWC_UTE_PER_IO
24412 +       ep->xiso_frame_num = 0xFFFFFFFF;
24413 +       ep->xiso_active_xfers = 0;
24414 +       ep->xiso_queued_xfers = 0;
24415 +#endif
24416 +       /* Read DEPCTLn register */
24417 +       if (ep->is_in == 1) {
24418 +               addr = &dev_if->in_ep_regs[ep->num]->diepctl;
24419 +               daintmsk.ep.in = 1 << ep->num;
24420 +       } else {
24421 +               addr = &dev_if->out_ep_regs[ep->num]->doepctl;
24422 +               daintmsk.ep.out = 1 << ep->num;
24423 +       }
24424 +
24425 +       /* If the EP is already active don't change the EP Control
24426 +        * register. */
24427 +       depctl.d32 = DWC_READ_REG32(addr);
24428 +       if (!depctl.b.usbactep) {
24429 +               depctl.b.mps = ep->maxpacket;
24430 +               depctl.b.eptype = ep->type;
24431 +               depctl.b.txfnum = ep->tx_fifo_num;
24432 +
24433 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24434 +                       depctl.b.setd0pid = 1;  // ???
24435 +               } else {
24436 +                       depctl.b.setd0pid = 1;
24437 +               }
24438 +               depctl.b.usbactep = 1;
24439 +
24440 +               /* Update nextep_seq array and EPMSCNT in DCFG*/
24441 +               if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) {       // NP IN EP
24442 +                       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24443 +                               if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq)
24444 +                               break;
24445 +                       }
24446 +                       core_if->nextep_seq[i] = ep->num;       
24447 +                       core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq;
24448 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
24449 +                       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
24450 +                       dcfg.b.epmscnt++;
24451 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
24452 +
24453 +                       DWC_DEBUGPL(DBG_PCDV,
24454 +                                   "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24455 +                               __func__, core_if->first_in_nextep_seq);
24456 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24457 +                               DWC_DEBUGPL(DBG_PCDV, "%2d\n",
24458 +                                           core_if->nextep_seq[i]);
24459 +                       }
24460 +
24461 +               }
24462 +
24463 +
24464 +               DWC_WRITE_REG32(addr, depctl.d32);
24465 +               DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr));
24466 +       }
24467 +
24468 +       /* Enable the Interrupt for this EP */
24469 +       if (core_if->multiproc_int_enable) {
24470 +               if (ep->is_in == 1) {
24471 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
24472 +                       diepmsk.b.xfercompl = 1;
24473 +                       diepmsk.b.timeout = 1;
24474 +                       diepmsk.b.epdisabled = 1;
24475 +                       diepmsk.b.ahberr = 1;
24476 +                       diepmsk.b.intknepmis = 1;
24477 +                       if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
24478 +                               diepmsk.b.intknepmis = 0; 
24479 +                       diepmsk.b.txfifoundrn = 1;      //?????
24480 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24481 +                               diepmsk.b.nak = 1;
24482 +                       }
24483 +
24484 +                       
24485 +                       
24486 +/*
24487 +                       if (core_if->dma_desc_enable) {
24488 +                               diepmsk.b.bna = 1;
24489 +                       }
24490 +*/
24491 +/*                     
24492 +                       if (core_if->dma_enable) {
24493 +                               doepmsk.b.nak = 1;
24494 +                       }
24495 +*/
24496 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->
24497 +                                       diepeachintmsk[ep->num], diepmsk.d32);
24498 +
24499 +               } else {
24500 +                       doepmsk_data_t doepmsk = {.d32 = 0 };
24501 +                       doepmsk.b.xfercompl = 1;
24502 +                       doepmsk.b.ahberr = 1;
24503 +                       doepmsk.b.epdisabled = 1;
24504 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24505 +                               doepmsk.b.outtknepdis = 1;
24506 +
24507 +/*                     
24508 +
24509 +                       if (core_if->dma_desc_enable) {
24510 +                               doepmsk.b.bna = 1;
24511 +                       }
24512 +*/
24513 +/*                     
24514 +                       doepmsk.b.babble = 1;
24515 +                       doepmsk.b.nyet = 1;
24516 +                       doepmsk.b.nak = 1;
24517 +*/
24518 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->
24519 +                                       doepeachintmsk[ep->num], doepmsk.d32);
24520 +               }
24521 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk,
24522 +                                0, daintmsk.d32);
24523 +       } else {
24524 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24525 +                       if (ep->is_in) {
24526 +                               diepmsk_data_t diepmsk = {.d32 = 0 };
24527 +                               diepmsk.b.nak = 1;
24528 +                               DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32);
24529 +                       } else {
24530 +                               doepmsk_data_t doepmsk = {.d32 = 0 };
24531 +                               doepmsk.b.outtknepdis = 1;
24532 +                               DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32);
24533 +                       }
24534 +               }
24535 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,
24536 +                                0, daintmsk.d32);
24537 +       }
24538 +
24539 +       DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n",
24540 +                   DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk));
24541 +
24542 +       ep->stall_clear_flag = 0;
24543 +
24544 +       return;
24545 +}
24546 +
24547 +/**
24548 + * This function deactivates an EP. This is done by clearing the USB Active
24549 + * EP bit in the Device EP control register. Note: This function is not used
24550 + * for EP0. EP0 cannot be deactivated.
24551 + *
24552 + * @param core_if Programming view of DWC_otg controller.
24553 + * @param ep The EP to deactivate.
24554 + */
24555 +void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24556 +{
24557 +       depctl_data_t depctl = {.d32 = 0 };
24558 +       volatile uint32_t *addr;
24559 +       daint_data_t daintmsk = {.d32 = 0 };
24560 +       dcfg_data_t dcfg;
24561 +       uint8_t i = 0;
24562 +
24563 +#ifdef DWC_UTE_PER_IO
24564 +       ep->xiso_frame_num = 0xFFFFFFFF;
24565 +       ep->xiso_active_xfers = 0;
24566 +       ep->xiso_queued_xfers = 0;
24567 +#endif
24568 +
24569 +       /* Read DEPCTLn register */
24570 +       if (ep->is_in == 1) {
24571 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
24572 +               daintmsk.ep.in = 1 << ep->num;
24573 +       } else {
24574 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
24575 +               daintmsk.ep.out = 1 << ep->num;
24576 +       }
24577 +
24578 +       depctl.d32 = DWC_READ_REG32(addr);
24579 +
24580 +       depctl.b.usbactep = 0;
24581 +       
24582 +       /* Update nextep_seq array and EPMSCNT in DCFG*/
24583 +       if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN
24584 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24585 +                       if (core_if->nextep_seq[i] == ep->num)
24586 +                       break;
24587 +               }
24588 +               core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];  
24589 +               if (core_if->first_in_nextep_seq == ep->num)
24590 +                       core_if->first_in_nextep_seq = i;
24591 +               core_if->nextep_seq[ep->num] = 0xff;
24592 +               depctl.b.nextep = 0;
24593 +               dcfg.d32 =
24594 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
24595 +               dcfg.b.epmscnt--;
24596 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
24597 +                               dcfg.d32);
24598 +
24599 +               DWC_DEBUGPL(DBG_PCDV,
24600 +                           "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24601 +                               __func__, core_if->first_in_nextep_seq);
24602 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24603 +                               DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
24604 +                       }
24605 +       }
24606 +               
24607 +       if (ep->is_in == 1)
24608 +               depctl.b.txfnum = 0;
24609 +
24610 +       if (core_if->dma_desc_enable)
24611 +               depctl.b.epdis = 1;
24612 +
24613 +       DWC_WRITE_REG32(addr, depctl.d32);
24614 +       depctl.d32 = DWC_READ_REG32(addr);
24615 +       if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC
24616 +           && depctl.b.epena) {
24617 +               depctl_data_t depctl = {.d32 = 0};
24618 +               if (ep->is_in) {
24619 +                       diepint_data_t diepint = {.d32 = 0};
24620 +                       
24621 +                       depctl.b.snak = 1;
24622 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24623 +                                       diepctl, depctl.d32);
24624 +                       do {
24625 +                               dwc_udelay(10);
24626 +                               diepint.d32 =
24627 +                                   DWC_READ_REG32(&core_if->
24628 +                                                  dev_if->in_ep_regs[ep->num]->
24629 +                                                  diepint);
24630 +                       } while (!diepint.b.inepnakeff); 
24631 +                       diepint.b.inepnakeff = 1;
24632 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24633 +                                       diepint, diepint.d32);
24634 +                       depctl.d32 = 0;
24635 +                       depctl.b.epdis = 1;
24636 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24637 +                                       diepctl, depctl.d32);
24638 +                       do {
24639 +                               dwc_udelay(10);
24640 +                               diepint.d32 =
24641 +                                   DWC_READ_REG32(&core_if->
24642 +                                                  dev_if->in_ep_regs[ep->num]->
24643 +                                                  diepint);
24644 +                       } while (!diepint.b.epdisabled); 
24645 +                       diepint.b.epdisabled = 1;
24646 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24647 +                                       diepint, diepint.d32);
24648 +               } else {
24649 +                       dctl_data_t dctl = {.d32 = 0};
24650 +                       gintmsk_data_t gintsts = {.d32 = 0};
24651 +                       doepint_data_t doepint = {.d32 = 0};
24652 +                       dctl.b.sgoutnak = 1;
24653 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
24654 +                                        dctl, 0, dctl.d32);
24655 +                       do {
24656 +                               dwc_udelay(10);
24657 +                               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
24658 +                       } while (!gintsts.b.goutnakeff); 
24659 +                       gintsts.d32 = 0;
24660 +                       gintsts.b.goutnakeff = 1;
24661 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
24662 +
24663 +                       depctl.d32 = 0;
24664 +                       depctl.b.epdis = 1;
24665 +                       depctl.b.snak = 1;
24666 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32);
24667 +                       do 
24668 +                       {
24669 +                               dwc_udelay(10);
24670 +                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
24671 +                                                                                       out_ep_regs[ep->num]->doepint);
24672 +                       } while (!doepint.b.epdisabled); 
24673 +
24674 +                       doepint.b.epdisabled = 1;
24675 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32);
24676 +
24677 +                       dctl.d32 = 0;
24678 +                       dctl.b.cgoutnak = 1;
24679 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
24680 +               }               
24681 +       }
24682 +
24683 +       /* Disable the Interrupt for this EP */
24684 +       if (core_if->multiproc_int_enable) {
24685 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
24686 +                                daintmsk.d32, 0);
24687 +
24688 +               if (ep->is_in == 1) {
24689 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24690 +                                       diepeachintmsk[ep->num], 0);
24691 +               } else {
24692 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24693 +                                       doepeachintmsk[ep->num], 0);
24694 +               }
24695 +       } else {
24696 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk,
24697 +                                daintmsk.d32, 0);
24698 +       }
24699 +
24700 +}
24701 +
24702 +/**
24703 + * This function initializes dma descriptor chain.
24704 + *
24705 + * @param core_if Programming view of DWC_otg controller.
24706 + * @param ep The EP to start the transfer on.
24707 + */
24708 +static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24709 +{
24710 +       dwc_otg_dev_dma_desc_t *dma_desc;
24711 +       uint32_t offset;
24712 +       uint32_t xfer_est;
24713 +       int i;
24714 +       unsigned maxxfer_local, total_len;
24715 +       
24716 +       if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR && 
24717 +                                       (ep->maxpacket%4)) {
24718 +               maxxfer_local = ep->maxpacket;
24719 +               total_len = ep->xfer_len;
24720 +       } else {
24721 +               maxxfer_local = ep->maxxfer;
24722 +               total_len = ep->total_len;
24723 +       }
24724 +
24725 +       ep->desc_cnt = (total_len / maxxfer_local) +
24726 +            ((total_len % maxxfer_local) ? 1 : 0);
24727 +
24728 +       if (!ep->desc_cnt)
24729 +               ep->desc_cnt = 1;
24730 +
24731 +       if (ep->desc_cnt > MAX_DMA_DESC_CNT)
24732 +               ep->desc_cnt = MAX_DMA_DESC_CNT;
24733 +
24734 +       dma_desc = ep->desc_addr;
24735 +       if (maxxfer_local == ep->maxpacket) {
24736 +               if ((total_len % maxxfer_local) &&
24737 +                               (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) {
24738 +                       xfer_est = (ep->desc_cnt - 1) * maxxfer_local +
24739 +                                       (total_len % maxxfer_local);
24740 +               } else
24741 +                       xfer_est = ep->desc_cnt * maxxfer_local;
24742 +       } else
24743 +               xfer_est = total_len;
24744 +       offset = 0;
24745 +       for (i = 0; i < ep->desc_cnt; ++i) {
24746 +               /** DMA Descriptor Setup */
24747 +               if (xfer_est > maxxfer_local) {
24748 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
24749 +                       dma_desc->status.b.l = 0;
24750 +                       dma_desc->status.b.ioc = 0;
24751 +                       dma_desc->status.b.sp = 0;
24752 +                       dma_desc->status.b.bytes = maxxfer_local;
24753 +                       dma_desc->buf = ep->dma_addr + offset;
24754 +                       dma_desc->status.b.sts = 0;
24755 +                       dma_desc->status.b.bs = BS_HOST_READY;
24756 +
24757 +                       xfer_est -= maxxfer_local;
24758 +                       offset += maxxfer_local;
24759 +               } else {
24760 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
24761 +                       dma_desc->status.b.l = 1;
24762 +                       dma_desc->status.b.ioc = 1;
24763 +                       if (ep->is_in) {
24764 +                               dma_desc->status.b.sp =
24765 +                                   (xfer_est %
24766 +                                    ep->maxpacket) ? 1 : ((ep->
24767 +                                                           sent_zlp) ? 1 : 0);
24768 +                               dma_desc->status.b.bytes = xfer_est;
24769 +                       } else {
24770 +                               if (maxxfer_local == ep->maxpacket)
24771 +                                       dma_desc->status.b.bytes = xfer_est;
24772 +                               else    
24773 +                                       dma_desc->status.b.bytes =
24774 +                                               xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
24775 +                       }
24776 +
24777 +                       dma_desc->buf = ep->dma_addr + offset;
24778 +                       dma_desc->status.b.sts = 0;
24779 +                       dma_desc->status.b.bs = BS_HOST_READY;
24780 +               }
24781 +               dma_desc++;
24782 +       }
24783 +}
24784 +/**
24785 + * This function is called when to write ISOC data into appropriate dedicated 
24786 + * periodic FIFO.
24787 + */
24788 +static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
24789 +{
24790 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24791 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
24792 +       dtxfsts_data_t txstatus = {.d32 = 0 };
24793 +       uint32_t len = 0;
24794 +       int epnum = dwc_ep->num;
24795 +       int dwords;
24796 +
24797 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
24798 +
24799 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
24800 +
24801 +       len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24802 +
24803 +       if (len > dwc_ep->maxpacket) {
24804 +               len = dwc_ep->maxpacket;
24805 +       }
24806 +
24807 +       dwords = (len + 3) / 4;
24808 +
24809 +       /* While there is space in the queue and space in the FIFO and
24810 +        * More data to tranfer, Write packets to the Tx FIFO */
24811 +       txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24812 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
24813 +
24814 +       while (txstatus.b.txfspcavail > dwords &&
24815 +              dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) {
24816 +               /* Write the FIFO */
24817 +               dwc_otg_ep_write_packet(core_if, dwc_ep, 0);
24818 +
24819 +               len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24820 +               if (len > dwc_ep->maxpacket) {
24821 +                       len = dwc_ep->maxpacket;
24822 +               }
24823 +
24824 +               dwords = (len + 3) / 4;
24825 +               txstatus.d32 =
24826 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24827 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
24828 +                           txstatus.d32);
24829 +       }
24830 +
24831 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
24832 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
24833 +
24834 +       return 1;
24835 +}
24836 +/**
24837 + * This function does the setup for a data transfer for an EP and
24838 + * starts the transfer. For an IN transfer, the packets will be
24839 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
24840 + * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.
24841 + *
24842 + * @param core_if Programming view of DWC_otg controller.
24843 + * @param ep The EP to start the transfer on.
24844 + */
24845 +
24846 +void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24847 +{
24848 +       depctl_data_t depctl;
24849 +       deptsiz_data_t deptsiz;
24850 +       gintmsk_data_t intr_mask = {.d32 = 0 };
24851 +
24852 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
24853 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
24854 +                   "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n",
24855 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
24856 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff,
24857 +                   ep->total_len);
24858 +       /* IN endpoint */
24859 +       if (ep->is_in == 1) {
24860 +               dwc_otg_dev_in_ep_regs_t *in_regs =
24861 +                   core_if->dev_if->in_ep_regs[ep->num];
24862 +
24863 +               gnptxsts_data_t gtxstatus;
24864 +
24865 +               gtxstatus.d32 =
24866 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
24867 +
24868 +               if (core_if->en_multiple_tx_fifo == 0
24869 +                   && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) {
24870 +#ifdef DEBUG
24871 +                       DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32);
24872 +#endif
24873 +                       return;
24874 +               }
24875 +
24876 +               depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
24877 +               deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
24878 +
24879 +               if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24880 +                       ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24881 +                               ep->maxxfer : (ep->total_len - ep->xfer_len);
24882 +               else 
24883 +                       ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?
24884 +                                MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24885 +
24886 +
24887 +               /* Zero Length Packet? */
24888 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
24889 +                       deptsiz.b.xfersize = 0;
24890 +                       deptsiz.b.pktcnt = 1;
24891 +               } else {
24892 +                       /* Program the transfer size and packet count
24893 +                        *      as follows: xfersize = N * maxpacket +
24894 +                        *      short_packet pktcnt = N + (short_packet
24895 +                        *      exist ? 1 : 0) 
24896 +                        */
24897 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24898 +                       deptsiz.b.pktcnt =
24899 +                           (ep->xfer_len - ep->xfer_count - 1 +
24900 +                            ep->maxpacket) / ep->maxpacket;
24901 +                       if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24902 +                               deptsiz.b.pktcnt = MAX_PKT_CNT;
24903 +                               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
24904 +                       } 
24905 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC) 
24906 +                               deptsiz.b.mc = deptsiz.b.pktcnt;
24907 +               }
24908 +
24909 +               /* Write the DMA register */
24910 +               if (core_if->dma_enable) {
24911 +                       if (core_if->dma_desc_enable == 0) {
24912 +                               if (ep->type != DWC_OTG_EP_TYPE_ISOC)
24913 +                                       deptsiz.b.mc = 1;
24914 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
24915 +                                               deptsiz.d32);
24916 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
24917 +                                               (uint32_t) ep->dma_addr);
24918 +                       } else {
24919 +#ifdef DWC_UTE_CFI
24920 +                               /* The descriptor chain should be already initialized by now */
24921 +                               if (ep->buff_mode != BM_STANDARD) {
24922 +                                       DWC_WRITE_REG32(&in_regs->diepdma,
24923 +                                                       ep->descs_dma_addr);
24924 +                               } else {
24925 +#endif
24926 +                                       init_dma_desc_chain(core_if, ep);
24927 +                               /** DIEPDMAn Register write */
24928 +                                       DWC_WRITE_REG32(&in_regs->diepdma,
24929 +                                                       ep->dma_desc_addr);
24930 +#ifdef DWC_UTE_CFI
24931 +                               }
24932 +#endif
24933 +                       }
24934 +               } else {
24935 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
24936 +                       if (ep->type != DWC_OTG_EP_TYPE_ISOC) {
24937 +                               /**
24938 +                                * Enable the Non-Periodic Tx FIFO empty interrupt,
24939 +                                * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
24940 +                                * the data will be written into the fifo by the ISR.
24941 +                                */
24942 +                               if (core_if->en_multiple_tx_fifo == 0) {
24943 +                                       intr_mask.b.nptxfempty = 1;
24944 +                                       DWC_MODIFY_REG32
24945 +                                           (&core_if->core_global_regs->gintmsk,
24946 +                                            intr_mask.d32, intr_mask.d32);
24947 +                               } else {
24948 +                                       /* Enable the Tx FIFO Empty Interrupt for this EP */
24949 +                                       if (ep->xfer_len > 0) {
24950 +                                               uint32_t fifoemptymsk = 0;
24951 +                                               fifoemptymsk = 1 << ep->num;
24952 +                                               DWC_MODIFY_REG32
24953 +                                                   (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
24954 +                                                    0, fifoemptymsk);
24955 +
24956 +                                       }
24957 +                               }
24958 +                       }  else {
24959 +                                        write_isoc_tx_fifo(core_if, ep);
24960 +                       }
24961 +               }
24962 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
24963 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
24964 +               
24965 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24966 +                       dsts_data_t dsts = {.d32 = 0};
24967 +                       if (ep->bInterval == 1) {
24968 +                               dsts.d32 =
24969 +                                   DWC_READ_REG32(&core_if->dev_if->
24970 +                                                  dev_global_regs->dsts);
24971 +                               ep->frame_num = dsts.b.soffn + ep->bInterval;
24972 +                               if (ep->frame_num > 0x3FFF) {
24973 +                                       ep->frm_overrun = 1;
24974 +                                       ep->frame_num &= 0x3FFF;
24975 +                               } else 
24976 +                                       ep->frm_overrun = 0;
24977 +                               if (ep->frame_num & 0x1) {
24978 +                                       depctl.b.setd1pid = 1;
24979 +                               } else {
24980 +                                       depctl.b.setd0pid = 1;
24981 +                               }
24982 +                       }
24983 +               }
24984 +               /* EP enable, IN data in FIFO */
24985 +               depctl.b.cnak = 1;
24986 +               depctl.b.epena = 1;
24987 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
24988 +
24989 +       } else {
24990 +               /* OUT endpoint */
24991 +               dwc_otg_dev_out_ep_regs_t *out_regs =
24992 +                   core_if->dev_if->out_ep_regs[ep->num];
24993 +
24994 +               depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
24995 +               deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
24996 +
24997 +               if (!core_if->dma_desc_enable) {        
24998 +                       if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24999 +                               ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
25000 +                               ep->maxxfer : (ep->total_len - ep->xfer_len);
25001 +                else
25002 +                                       ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len 
25003 +                                       - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
25004 +               }
25005 +
25006 +               /* Program the transfer size and packet count as follows:
25007 +                *
25008 +                *      pktcnt = N                                                                                
25009 +                *      xfersize = N * maxpacket
25010 +                */
25011 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
25012 +                       /* Zero Length Packet */
25013 +                       deptsiz.b.xfersize = ep->maxpacket;
25014 +                       deptsiz.b.pktcnt = 1;
25015 +               } else {
25016 +                       deptsiz.b.pktcnt =
25017 +                           (ep->xfer_len - ep->xfer_count +
25018 +                            (ep->maxpacket - 1)) / ep->maxpacket;
25019 +                       if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
25020 +                               deptsiz.b.pktcnt = MAX_PKT_CNT;
25021 +                       }
25022 +                       if (!core_if->dma_desc_enable) {
25023 +                               ep->xfer_len =
25024 +                                       deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
25025 +                       }
25026 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
25027 +               }
25028 +
25029 +               DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",
25030 +                           ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);
25031 +
25032 +               if (core_if->dma_enable) {
25033 +                       if (!core_if->dma_desc_enable) {
25034 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25035 +                                               deptsiz.d32);
25036 +
25037 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25038 +                                               (uint32_t) ep->dma_addr);
25039 +                       } else {
25040 +#ifdef DWC_UTE_CFI
25041 +                               /* The descriptor chain should be already initialized by now */
25042 +                               if (ep->buff_mode != BM_STANDARD) {
25043 +                                       DWC_WRITE_REG32(&out_regs->doepdma,
25044 +                                                       ep->descs_dma_addr);
25045 +                               } else {
25046 +#endif
25047 +                                       /** This is used for interrupt out transfers*/
25048 +                                       if (!ep->xfer_len)
25049 +                                               ep->xfer_len = ep->total_len;
25050 +                                       init_dma_desc_chain(core_if, ep);
25051 +
25052 +                                       if (core_if->core_params->dev_out_nak) {
25053 +                                               if (ep->type == DWC_OTG_EP_TYPE_BULK) {
25054 +                                                       deptsiz.b.pktcnt = (ep->total_len +
25055 +                                                               (ep->maxpacket - 1)) / ep->maxpacket;
25056 +                                                       deptsiz.b.xfersize = ep->total_len;
25057 +                                                       /* Remember initial value of doeptsiz */
25058 +                                                       core_if->start_doeptsiz_val[ep->num] = deptsiz.d32;
25059 +                                                       DWC_WRITE_REG32(&out_regs->doeptsiz,
25060 +                                                               deptsiz.d32);                                                                                                   
25061 +                                               }
25062 +                                       }
25063 +                               /** DOEPDMAn Register write */
25064 +                                       DWC_WRITE_REG32(&out_regs->doepdma,
25065 +                                                       ep->dma_desc_addr);
25066 +#ifdef DWC_UTE_CFI
25067 +                               }
25068 +#endif
25069 +                       }
25070 +               } else {
25071 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25072 +               }
25073 +
25074 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
25075 +                       dsts_data_t dsts = {.d32 = 0};
25076 +                       if (ep->bInterval == 1) {
25077 +                               dsts.d32 =
25078 +                                   DWC_READ_REG32(&core_if->dev_if->
25079 +                                                  dev_global_regs->dsts);
25080 +                               ep->frame_num = dsts.b.soffn + ep->bInterval;
25081 +                               if (ep->frame_num > 0x3FFF) {
25082 +                                       ep->frm_overrun = 1;
25083 +                                       ep->frame_num &= 0x3FFF;
25084 +                               } else 
25085 +                                       ep->frm_overrun = 0;
25086 +
25087 +                               if (ep->frame_num & 0x1) {
25088 +                                       depctl.b.setd1pid = 1;
25089 +                               } else {
25090 +                                       depctl.b.setd0pid = 1;
25091 +                               }
25092 +                       }
25093 +               }
25094 +
25095 +               /* EP enable */
25096 +               depctl.b.cnak = 1;
25097 +               depctl.b.epena = 1;
25098 +
25099 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25100 +
25101 +               DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
25102 +                           DWC_READ_REG32(&out_regs->doepctl),
25103 +                           DWC_READ_REG32(&out_regs->doeptsiz));
25104 +               DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
25105 +                           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
25106 +                                          daintmsk),
25107 +                           DWC_READ_REG32(&core_if->core_global_regs->
25108 +                                          gintmsk));
25109 +
25110 +               /* Timer is scheduling only for out bulk transfers for 
25111 +                * "Device DDMA OUT NAK Enhancement" feature to inform user 
25112 +                * about received data payload in case of timeout 
25113 +                */
25114 +               if (core_if->core_params->dev_out_nak) {
25115 +                       if (ep->type == DWC_OTG_EP_TYPE_BULK) {
25116 +                               core_if->ep_xfer_info[ep->num].core_if = core_if;
25117 +                               core_if->ep_xfer_info[ep->num].ep = ep;
25118 +                               core_if->ep_xfer_info[ep->num].state = 1;
25119 +
25120 +                               /* Start a timer for this transfer. */
25121 +                               DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000);
25122 +                       }
25123 +               }
25124 +       }
25125 +}
25126 +
25127 +/**
25128 + * This function setup a zero length transfer in Buffer DMA and
25129 + * Slave modes for usb requests with zero field set
25130 + *
25131 + * @param core_if Programming view of DWC_otg controller.
25132 + * @param ep The EP to start the transfer on.
25133 + *
25134 + */
25135 +void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25136 +{
25137 +
25138 +       depctl_data_t depctl;
25139 +       deptsiz_data_t deptsiz;
25140 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25141 +
25142 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
25143 +       DWC_PRINTF("zero length transfer is called\n");
25144 +
25145 +       /* IN endpoint */
25146 +       if (ep->is_in == 1) {
25147 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25148 +                   core_if->dev_if->in_ep_regs[ep->num];
25149 +
25150 +               depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
25151 +               deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
25152 +
25153 +               deptsiz.b.xfersize = 0;
25154 +               deptsiz.b.pktcnt = 1;
25155 +
25156 +               /* Write the DMA register */
25157 +               if (core_if->dma_enable) {
25158 +                       if (core_if->dma_desc_enable == 0) {
25159 +                               deptsiz.b.mc = 1;
25160 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
25161 +                                               deptsiz.d32);
25162 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25163 +                                               (uint32_t) ep->dma_addr);
25164 +                       }
25165 +               } else {
25166 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25167 +                       /**
25168 +                        * Enable the Non-Periodic Tx FIFO empty interrupt,
25169 +                        * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
25170 +                        * the data will be written into the fifo by the ISR.
25171 +                        */
25172 +                       if (core_if->en_multiple_tx_fifo == 0) {
25173 +                               intr_mask.b.nptxfempty = 1;
25174 +                               DWC_MODIFY_REG32(&core_if->
25175 +                                                core_global_regs->gintmsk,
25176 +                                                intr_mask.d32, intr_mask.d32);
25177 +                       } else {
25178 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25179 +                               if (ep->xfer_len > 0) {
25180 +                                       uint32_t fifoemptymsk = 0;
25181 +                                       fifoemptymsk = 1 << ep->num;
25182 +                                       DWC_MODIFY_REG32(&core_if->
25183 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25184 +                                                        0, fifoemptymsk);
25185 +                               }
25186 +                       }
25187 +               }
25188 +
25189 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25190 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25191 +               /* EP enable, IN data in FIFO */
25192 +               depctl.b.cnak = 1;
25193 +               depctl.b.epena = 1;
25194 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25195 +
25196 +       } else {
25197 +               /* OUT endpoint */
25198 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25199 +                   core_if->dev_if->out_ep_regs[ep->num];
25200 +
25201 +               depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
25202 +               deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
25203 +
25204 +               /* Zero Length Packet */
25205 +               deptsiz.b.xfersize = ep->maxpacket;
25206 +               deptsiz.b.pktcnt = 1;
25207 +
25208 +               if (core_if->dma_enable) {
25209 +                       if (!core_if->dma_desc_enable) {
25210 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25211 +                                               deptsiz.d32);
25212 +
25213 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25214 +                                               (uint32_t) ep->dma_addr);
25215 +                       }
25216 +               } else {
25217 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25218 +               }
25219 +
25220 +               /* EP enable */
25221 +               depctl.b.cnak = 1;
25222 +               depctl.b.epena = 1;
25223 +
25224 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25225 +
25226 +       }
25227 +}
25228 +
25229 +/**
25230 + * This function does the setup for a data transfer for EP0 and starts
25231 + * the transfer.  For an IN transfer, the packets will be loaded into
25232 + * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
25233 + * unloaded from the Rx FIFO in the ISR.
25234 + *
25235 + * @param core_if Programming view of DWC_otg controller.
25236 + * @param ep The EP0 data.
25237 + */
25238 +void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25239 +{
25240 +       depctl_data_t depctl;
25241 +       deptsiz0_data_t deptsiz;
25242 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25243 +       dwc_otg_dev_dma_desc_t *dma_desc;
25244 +
25245 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
25246 +                   "xfer_buff=%p start_xfer_buff=%p \n",
25247 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
25248 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff);
25249 +
25250 +       ep->total_len = ep->xfer_len;
25251 +
25252 +       /* IN endpoint */
25253 +       if (ep->is_in == 1) {
25254 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25255 +                   core_if->dev_if->in_ep_regs[0];
25256 +
25257 +               gnptxsts_data_t gtxstatus;
25258 +
25259 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25260 +                       depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25261 +                       if (depctl.b.epena)
25262 +                               return;
25263 +               }
25264 +
25265 +               gtxstatus.d32 =
25266 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25267 +
25268 +               /* If dedicated FIFO every time flush fifo before enable ep*/
25269 +               if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a)
25270 +                       dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
25271 +
25272 +               if (core_if->en_multiple_tx_fifo == 0
25273 +                   && gtxstatus.b.nptxqspcavail == 0
25274 +                   && !core_if->dma_enable) {
25275 +#ifdef DEBUG
25276 +                       deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25277 +                       DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n",
25278 +                                   DWC_READ_REG32(&in_regs->diepctl));
25279 +                       DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",
25280 +                                   deptsiz.d32,
25281 +                                   deptsiz.b.xfersize, deptsiz.b.pktcnt);
25282 +                       DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n",
25283 +                                  gtxstatus.d32);
25284 +#endif
25285 +                       return;
25286 +               }
25287 +
25288 +               depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25289 +               deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25290 +
25291 +               /* Zero Length Packet? */
25292 +               if (ep->xfer_len == 0) {
25293 +                       deptsiz.b.xfersize = 0;
25294 +                       deptsiz.b.pktcnt = 1;
25295 +               } else {
25296 +                       /* Program the transfer size and packet count
25297 +                        *      as follows: xfersize = N * maxpacket +
25298 +                        *      short_packet pktcnt = N + (short_packet
25299 +                        *      exist ? 1 : 0) 
25300 +                        */
25301 +                       if (ep->xfer_len > ep->maxpacket) {
25302 +                               ep->xfer_len = ep->maxpacket;
25303 +                               deptsiz.b.xfersize = ep->maxpacket;
25304 +                       } else {
25305 +                               deptsiz.b.xfersize = ep->xfer_len;
25306 +                       }
25307 +                       deptsiz.b.pktcnt = 1;
25308 +
25309 +               }
25310 +               DWC_DEBUGPL(DBG_PCDV,
25311 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25312 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25313 +                           deptsiz.d32);
25314 +
25315 +               /* Write the DMA register */
25316 +               if (core_if->dma_enable) {
25317 +                       if (core_if->dma_desc_enable == 0) {
25318 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
25319 +                                               deptsiz.d32);
25320 +
25321 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25322 +                                               (uint32_t) ep->dma_addr);
25323 +                       } else {
25324 +                               dma_desc = core_if->dev_if->in_desc_addr;
25325 +
25326 +                               /** DMA Descriptor Setup */
25327 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
25328 +                               dma_desc->status.b.l = 1;
25329 +                               dma_desc->status.b.ioc = 1;
25330 +                               dma_desc->status.b.sp =
25331 +                                   (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25332 +                               dma_desc->status.b.bytes = ep->xfer_len;
25333 +                               dma_desc->buf = ep->dma_addr;
25334 +                               dma_desc->status.b.sts = 0;
25335 +                               dma_desc->status.b.bs = BS_HOST_READY;
25336 +
25337 +                               /** DIEPDMA0 Register write */
25338 +                               DWC_WRITE_REG32(&in_regs->diepdma,
25339 +                                               core_if->
25340 +                                               dev_if->dma_in_desc_addr);
25341 +                       }
25342 +               } else {
25343 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25344 +               }
25345 +
25346 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25347 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25348 +               /* EP enable, IN data in FIFO */
25349 +               depctl.b.cnak = 1;
25350 +               depctl.b.epena = 1;
25351 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25352 +
25353 +               /**
25354 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
25355 +                * data will be written into the fifo by the ISR.
25356 +                */
25357 +               if (!core_if->dma_enable) {
25358 +                       if (core_if->en_multiple_tx_fifo == 0) {
25359 +                               intr_mask.b.nptxfempty = 1;
25360 +                               DWC_MODIFY_REG32(&core_if->
25361 +                                                core_global_regs->gintmsk,
25362 +                                                intr_mask.d32, intr_mask.d32);
25363 +                       } else {
25364 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25365 +                               if (ep->xfer_len > 0) {
25366 +                                       uint32_t fifoemptymsk = 0;
25367 +                                       fifoemptymsk |= 1 << ep->num;
25368 +                                       DWC_MODIFY_REG32(&core_if->
25369 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25370 +                                                        0, fifoemptymsk);
25371 +                               }
25372 +                       }
25373 +               }
25374 +       } else {
25375 +               /* OUT endpoint */
25376 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25377 +                   core_if->dev_if->out_ep_regs[0];
25378 +
25379 +               depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25380 +               deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25381 +
25382 +               /* Program the transfer size and packet count as follows:
25383 +                *      xfersize = N * (maxpacket + 4 - (maxpacket % 4))
25384 +                *      pktcnt = N                                                                                      */
25385 +               /* Zero Length Packet */
25386 +               deptsiz.b.xfersize = ep->maxpacket;
25387 +               deptsiz.b.pktcnt = 1;
25388 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a)
25389 +                       deptsiz.b.supcnt = 3;
25390 +
25391 +               DWC_DEBUGPL(DBG_PCDV, "len=%d  xfersize=%d pktcnt=%d\n",
25392 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt);
25393 +
25394 +               if (core_if->dma_enable) {
25395 +                       if (!core_if->dma_desc_enable) {
25396 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25397 +                                               deptsiz.d32);
25398 +
25399 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25400 +                                               (uint32_t) ep->dma_addr);
25401 +                       } else {
25402 +                               dma_desc = core_if->dev_if->out_desc_addr;
25403 +
25404 +                               /** DMA Descriptor Setup */
25405 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
25406 +                               if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25407 +                                       dma_desc->status.b.mtrf = 0;
25408 +                                       dma_desc->status.b.sr = 0;
25409 +                               }
25410 +                               dma_desc->status.b.l = 1;
25411 +                               dma_desc->status.b.ioc = 1;
25412 +                               dma_desc->status.b.bytes = ep->maxpacket;
25413 +                               dma_desc->buf = ep->dma_addr;
25414 +                               dma_desc->status.b.sts = 0;
25415 +                               dma_desc->status.b.bs = BS_HOST_READY;
25416 +
25417 +                               /** DOEPDMA0 Register write */
25418 +                               DWC_WRITE_REG32(&out_regs->doepdma,
25419 +                                               core_if->dev_if->
25420 +                                               dma_out_desc_addr);
25421 +                       }
25422 +               } else {
25423 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25424 +               }
25425 +
25426 +               /* EP enable */
25427 +               depctl.b.cnak = 1;
25428 +               depctl.b.epena = 1;
25429 +               DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
25430 +       }
25431 +}
25432 +
25433 +/**
25434 + * This function continues control IN transfers started by
25435 + * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
25436 + * single packet.  NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
25437 + * bit for the packet count.
25438 + *
25439 + * @param core_if Programming view of DWC_otg controller.
25440 + * @param ep The EP0 data.
25441 + */
25442 +void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25443 +{
25444 +       depctl_data_t depctl;
25445 +       deptsiz0_data_t deptsiz;
25446 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25447 +       dwc_otg_dev_dma_desc_t *dma_desc;
25448 +
25449 +       if (ep->is_in == 1) {
25450 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25451 +                   core_if->dev_if->in_ep_regs[0];
25452 +               gnptxsts_data_t tx_status = {.d32 = 0 };
25453 +
25454 +               tx_status.d32 =
25455 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25456 +               /** @todo Should there be check for room in the Tx
25457 +                * Status Queue.  If not remove the code above this comment. */
25458 +
25459 +               depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25460 +               deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25461 +
25462 +               /* Program the transfer size and packet count
25463 +                *      as follows: xfersize = N * maxpacket +
25464 +                *      short_packet pktcnt = N + (short_packet
25465 +                *      exist ? 1 : 0) 
25466 +                */
25467 +
25468 +               if (core_if->dma_desc_enable == 0) {
25469 +                       deptsiz.b.xfersize =
25470 +                           (ep->total_len - ep->xfer_count) >
25471 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
25472 +                                                            ep->xfer_count);
25473 +                       deptsiz.b.pktcnt = 1;
25474 +                       if (core_if->dma_enable == 0) {
25475 +                               ep->xfer_len += deptsiz.b.xfersize;
25476 +                       } else {
25477 +                               ep->xfer_len = deptsiz.b.xfersize;
25478 +                       }
25479 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25480 +               } else {
25481 +                       ep->xfer_len =
25482 +                           (ep->total_len - ep->xfer_count) >
25483 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
25484 +                                                            ep->xfer_count);
25485 +
25486 +                       dma_desc = core_if->dev_if->in_desc_addr;
25487 +
25488 +                       /** DMA Descriptor Setup */
25489 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
25490 +                       dma_desc->status.b.l = 1;
25491 +                       dma_desc->status.b.ioc = 1;
25492 +                       dma_desc->status.b.sp =
25493 +                           (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25494 +                       dma_desc->status.b.bytes = ep->xfer_len;
25495 +                       dma_desc->buf = ep->dma_addr;
25496 +                       dma_desc->status.b.sts = 0;
25497 +                       dma_desc->status.b.bs = BS_HOST_READY;
25498 +
25499 +                       /** DIEPDMA0 Register write */
25500 +                       DWC_WRITE_REG32(&in_regs->diepdma,
25501 +                                       core_if->dev_if->dma_in_desc_addr);
25502 +               }
25503 +
25504 +               DWC_DEBUGPL(DBG_PCDV,
25505 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25506 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25507 +                           deptsiz.d32);
25508 +
25509 +               /* Write the DMA register */
25510 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25511 +                       if (core_if->dma_desc_enable == 0)
25512 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25513 +                                               (uint32_t) ep->dma_addr);
25514 +               }
25515 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25516 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25517 +               /* EP enable, IN data in FIFO */
25518 +               depctl.b.cnak = 1;
25519 +               depctl.b.epena = 1;
25520 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25521 +
25522 +               /**
25523 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
25524 +                * data will be written into the fifo by the ISR.
25525 +                */
25526 +               if (!core_if->dma_enable) {
25527 +                       if (core_if->en_multiple_tx_fifo == 0) {
25528 +                               /* First clear it from GINTSTS */
25529 +                               intr_mask.b.nptxfempty = 1;
25530 +                               DWC_MODIFY_REG32(&core_if->
25531 +                                                core_global_regs->gintmsk,
25532 +                                                intr_mask.d32, intr_mask.d32);
25533 +
25534 +                       } else {
25535 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25536 +                               if (ep->xfer_len > 0) {
25537 +                                       uint32_t fifoemptymsk = 0;
25538 +                                       fifoemptymsk |= 1 << ep->num;
25539 +                                       DWC_MODIFY_REG32(&core_if->
25540 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25541 +                                                        0, fifoemptymsk);
25542 +                               }
25543 +                       }
25544 +               }
25545 +       } else {
25546 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25547 +                   core_if->dev_if->out_ep_regs[0];
25548 +
25549 +               depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25550 +               deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25551 +
25552 +               /* Program the transfer size and packet count
25553 +                *      as follows: xfersize = N * maxpacket +
25554 +                *      short_packet pktcnt = N + (short_packet
25555 +                *      exist ? 1 : 0) 
25556 +                */
25557 +               deptsiz.b.xfersize = ep->maxpacket;
25558 +               deptsiz.b.pktcnt = 1;
25559 +
25560 +               if (core_if->dma_desc_enable == 0) {
25561 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25562 +               } else {
25563 +                       dma_desc = core_if->dev_if->out_desc_addr;
25564 +
25565 +                       /** DMA Descriptor Setup */
25566 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
25567 +                       dma_desc->status.b.l = 1;
25568 +                       dma_desc->status.b.ioc = 1;
25569 +                       dma_desc->status.b.bytes = ep->maxpacket;
25570 +                       dma_desc->buf = ep->dma_addr;
25571 +                       dma_desc->status.b.sts = 0;
25572 +                       dma_desc->status.b.bs = BS_HOST_READY;
25573 +
25574 +                       /** DOEPDMA0 Register write */
25575 +                       DWC_WRITE_REG32(&out_regs->doepdma,
25576 +                                       core_if->dev_if->dma_out_desc_addr);
25577 +               }
25578 +
25579 +               DWC_DEBUGPL(DBG_PCDV,
25580 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25581 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25582 +                           deptsiz.d32);
25583 +
25584 +               /* Write the DMA register */
25585 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25586 +                       if (core_if->dma_desc_enable == 0)
25587 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25588 +                                               (uint32_t) ep->dma_addr);
25589 +
25590 +               }
25591 +
25592 +               /* EP enable, IN data in FIFO */
25593 +               depctl.b.cnak = 1;
25594 +               depctl.b.epena = 1;
25595 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25596 +
25597 +       }
25598 +}
25599 +
25600 +#ifdef DEBUG
25601 +void dump_msg(const u8 * buf, unsigned int length)
25602 +{
25603 +       unsigned int start, num, i;
25604 +       char line[52], *p;
25605 +
25606 +       if (length >= 512)
25607 +               return;
25608 +       start = 0;
25609 +       while (length > 0) {
25610 +               num = length < 16u ? length : 16u;
25611 +               p = line;
25612 +               for (i = 0; i < num; ++i) {
25613 +                       if (i == 8)
25614 +                               *p++ = ' ';
25615 +                       DWC_SPRINTF(p, " %02x", buf[i]);
25616 +                       p += 3;
25617 +               }
25618 +               *p = 0;
25619 +               DWC_PRINTF("%6x: %s\n", start, line);
25620 +               buf += num;
25621 +               start += num;
25622 +               length -= num;
25623 +       }
25624 +}
25625 +#else
25626 +static inline void dump_msg(const u8 * buf, unsigned int length)
25627 +{
25628 +}
25629 +#endif
25630 +
25631 +/**
25632 + * This function writes a packet into the Tx FIFO associated with the
25633 + * EP. For non-periodic EPs the non-periodic Tx FIFO is written.  For
25634 + * periodic EPs the periodic Tx FIFO associated with the EP is written
25635 + * with all packets for the next micro-frame.
25636 + *
25637 + * @param core_if Programming view of DWC_otg controller.
25638 + * @param ep The EP to write packet for.
25639 + * @param dma Indicates if DMA is being used.
25640 + */
25641 +void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
25642 +                            int dma)
25643 +{
25644 +       /**
25645 +        * The buffer is padded to DWORD on a per packet basis in
25646 +        * slave/dma mode if the MPS is not DWORD aligned. The last
25647 +        * packet, if short, is also padded to a multiple of DWORD.
25648 +        *
25649 +        * ep->xfer_buff always starts DWORD aligned in memory and is a
25650 +        * multiple of DWORD in length
25651 +        *
25652 +        * ep->xfer_len can be any number of bytes
25653 +        *
25654 +        * ep->xfer_count is a multiple of ep->maxpacket until the last
25655 +        *      packet
25656 +        *
25657 +        * FIFO access is DWORD */
25658 +
25659 +       uint32_t i;
25660 +       uint32_t byte_count;
25661 +       uint32_t dword_count;
25662 +       uint32_t *fifo;
25663 +       uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
25664 +
25665 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if,
25666 +                   ep);
25667 +       if (ep->xfer_count >= ep->xfer_len) {
25668 +               DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num);
25669 +               return;
25670 +       }
25671 +
25672 +       /* Find the byte length of the packet either short packet or MPS */
25673 +       if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) {
25674 +               byte_count = ep->xfer_len - ep->xfer_count;
25675 +       } else {
25676 +               byte_count = ep->maxpacket;
25677 +       }
25678 +
25679 +       /* Find the DWORD length, padded by extra bytes as neccessary if MPS
25680 +        * is not a multiple of DWORD */
25681 +       dword_count = (byte_count + 3) / 4;
25682 +
25683 +#ifdef VERBOSE
25684 +       dump_msg(ep->xfer_buff, byte_count);
25685 +#endif
25686 +
25687 +       /**@todo NGS Where are the Periodic Tx FIFO addresses
25688 +        * intialized?  What should this be? */
25689 +
25690 +       fifo = core_if->data_fifo[ep->num];
25691 +
25692 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n",
25693 +                   fifo, data_buff, *data_buff, byte_count);
25694 +
25695 +       if (!dma) {
25696 +               for (i = 0; i < dword_count; i++, data_buff++) {
25697 +                       DWC_WRITE_REG32(fifo, *data_buff);
25698 +               }
25699 +       }
25700 +
25701 +       ep->xfer_count += byte_count;
25702 +       ep->xfer_buff += byte_count;
25703 +       ep->dma_addr += byte_count;
25704 +}
25705 +
25706 +/**
25707 + * Set the EP STALL.
25708 + *
25709 + * @param core_if Programming view of DWC_otg controller.
25710 + * @param ep The EP to set the stall on.
25711 + */
25712 +void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25713 +{
25714 +       depctl_data_t depctl;
25715 +       volatile uint32_t *depctl_addr;
25716 +
25717 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25718 +                   (ep->is_in ? "IN" : "OUT"));
25719 +
25720 +       if (ep->is_in == 1) {
25721 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25722 +               depctl.d32 = DWC_READ_REG32(depctl_addr);
25723 +
25724 +               /* set the disable and stall bits */
25725 +               if (depctl.b.epena) {
25726 +                       depctl.b.epdis = 1;
25727 +               }
25728 +               depctl.b.stall = 1;
25729 +               DWC_WRITE_REG32(depctl_addr, depctl.d32);
25730 +       } else {
25731 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25732 +               depctl.d32 = DWC_READ_REG32(depctl_addr);
25733 +
25734 +               /* set the stall bit */
25735 +               depctl.b.stall = 1;
25736 +               DWC_WRITE_REG32(depctl_addr, depctl.d32);
25737 +       }
25738 +
25739 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25740 +
25741 +       return;
25742 +}
25743 +
25744 +/**
25745 + * Clear the EP STALL.
25746 + *
25747 + * @param core_if Programming view of DWC_otg controller.
25748 + * @param ep The EP to clear stall from.
25749 + */
25750 +void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25751 +{
25752 +       depctl_data_t depctl;
25753 +       volatile uint32_t *depctl_addr;
25754 +
25755 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25756 +                   (ep->is_in ? "IN" : "OUT"));
25757 +
25758 +       if (ep->is_in == 1) {
25759 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25760 +       } else {
25761 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25762 +       }
25763 +
25764 +       depctl.d32 = DWC_READ_REG32(depctl_addr);
25765 +
25766 +       /* clear the stall bits */
25767 +       depctl.b.stall = 0;
25768 +
25769 +       /*
25770 +        * USB Spec 9.4.5: For endpoints using data toggle, regardless
25771 +        * of whether an endpoint has the Halt feature set, a
25772 +        * ClearFeature(ENDPOINT_HALT) request always results in the
25773 +        * data toggle being reinitialized to DATA0.
25774 +        */
25775 +       if (ep->type == DWC_OTG_EP_TYPE_INTR ||
25776 +           ep->type == DWC_OTG_EP_TYPE_BULK) {
25777 +               depctl.b.setd0pid = 1;  /* DATA0 */
25778 +       }
25779 +
25780 +       DWC_WRITE_REG32(depctl_addr, depctl.d32);
25781 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25782 +       return;
25783 +}
25784 +
25785 +/**
25786 + * This function reads a packet from the Rx FIFO into the destination
25787 + * buffer. To read SETUP data use dwc_otg_read_setup_packet.
25788 + *
25789 + * @param core_if Programming view of DWC_otg controller.
25790 + * @param dest   Destination buffer for the packet.
25791 + * @param bytes  Number of bytes to copy to the destination.
25792 + */
25793 +void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
25794 +                        uint8_t * dest, uint16_t bytes)
25795 +{
25796 +       int i;
25797 +       int word_count = (bytes + 3) / 4;
25798 +
25799 +       volatile uint32_t *fifo = core_if->data_fifo[0];
25800 +       uint32_t *data_buff = (uint32_t *) dest;
25801 +
25802 +       /**
25803 +        * @todo Account for the case where _dest is not dword aligned. This
25804 +        * requires reading data from the FIFO into a uint32_t temp buffer,
25805 +        * then moving it into the data buffer.
25806 +        */
25807 +
25808 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__,
25809 +                   core_if, dest, bytes);
25810 +
25811 +       for (i = 0; i < word_count; i++, data_buff++) {
25812 +               *data_buff = DWC_READ_REG32(fifo);
25813 +       }
25814 +
25815 +       return;
25816 +}
25817 +
25818 +/**
25819 + * This functions reads the device registers and prints them
25820 + *
25821 + * @param core_if Programming view of DWC_otg controller.
25822 + */
25823 +void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if)
25824 +{
25825 +       int i;
25826 +       volatile uint32_t *addr;
25827 +
25828 +       DWC_PRINTF("Device Global Registers\n");
25829 +       addr = &core_if->dev_if->dev_global_regs->dcfg;
25830 +       DWC_PRINTF("DCFG                 @0x%08lX : 0x%08X\n",
25831 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25832 +       addr = &core_if->dev_if->dev_global_regs->dctl;
25833 +       DWC_PRINTF("DCTL                 @0x%08lX : 0x%08X\n",
25834 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25835 +       addr = &core_if->dev_if->dev_global_regs->dsts;
25836 +       DWC_PRINTF("DSTS                 @0x%08lX : 0x%08X\n",
25837 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25838 +       addr = &core_if->dev_if->dev_global_regs->diepmsk;
25839 +       DWC_PRINTF("DIEPMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25840 +                  DWC_READ_REG32(addr));
25841 +       addr = &core_if->dev_if->dev_global_regs->doepmsk;
25842 +       DWC_PRINTF("DOEPMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25843 +                  DWC_READ_REG32(addr));
25844 +       addr = &core_if->dev_if->dev_global_regs->daint;
25845 +       DWC_PRINTF("DAINT        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25846 +                  DWC_READ_REG32(addr));
25847 +       addr = &core_if->dev_if->dev_global_regs->daintmsk;
25848 +       DWC_PRINTF("DAINTMSK     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25849 +                  DWC_READ_REG32(addr));
25850 +       addr = &core_if->dev_if->dev_global_regs->dtknqr1;
25851 +       DWC_PRINTF("DTKNQR1      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25852 +                  DWC_READ_REG32(addr));
25853 +       if (core_if->hwcfg2.b.dev_token_q_depth > 6) {
25854 +               addr = &core_if->dev_if->dev_global_regs->dtknqr2;
25855 +               DWC_PRINTF("DTKNQR2      @0x%08lX : 0x%08X\n",
25856 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25857 +       }
25858 +
25859 +       addr = &core_if->dev_if->dev_global_regs->dvbusdis;
25860 +       DWC_PRINTF("DVBUSID      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25861 +                  DWC_READ_REG32(addr));
25862 +
25863 +       addr = &core_if->dev_if->dev_global_regs->dvbuspulse;
25864 +       DWC_PRINTF("DVBUSPULSE  @0x%08lX : 0x%08X\n",
25865 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25866 +
25867 +       addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl;
25868 +       DWC_PRINTF("DTKNQR3_DTHRCTL      @0x%08lX : 0x%08X\n",
25869 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25870 +
25871 +       if (core_if->hwcfg2.b.dev_token_q_depth > 22) {
25872 +               addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25873 +               DWC_PRINTF("DTKNQR4      @0x%08lX : 0x%08X\n",
25874 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25875 +       }
25876 +
25877 +       addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25878 +       DWC_PRINTF("FIFOEMPMSK   @0x%08lX : 0x%08X\n", (unsigned long)addr,
25879 +                  DWC_READ_REG32(addr));
25880 +
25881 +       if (core_if->hwcfg2.b.multi_proc_int) {
25882 +
25883 +               addr = &core_if->dev_if->dev_global_regs->deachint;
25884 +               DWC_PRINTF("DEACHINT     @0x%08lX : 0x%08X\n",
25885 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25886 +               addr = &core_if->dev_if->dev_global_regs->deachintmsk;
25887 +               DWC_PRINTF("DEACHINTMSK  @0x%08lX : 0x%08X\n",
25888 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25889 +
25890 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25891 +                       addr =
25892 +                           &core_if->dev_if->
25893 +                           dev_global_regs->diepeachintmsk[i];
25894 +                       DWC_PRINTF("DIEPEACHINTMSK[%d]   @0x%08lX : 0x%08X\n",
25895 +                                  i, (unsigned long)addr,
25896 +                                  DWC_READ_REG32(addr));
25897 +               }
25898 +
25899 +               for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25900 +                       addr =
25901 +                           &core_if->dev_if->
25902 +                           dev_global_regs->doepeachintmsk[i];
25903 +                       DWC_PRINTF("DOEPEACHINTMSK[%d]   @0x%08lX : 0x%08X\n",
25904 +                                  i, (unsigned long)addr,
25905 +                                  DWC_READ_REG32(addr));
25906 +               }
25907 +       }
25908 +
25909 +       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25910 +               DWC_PRINTF("Device IN EP %d Registers\n", i);
25911 +               addr = &core_if->dev_if->in_ep_regs[i]->diepctl;
25912 +               DWC_PRINTF("DIEPCTL      @0x%08lX : 0x%08X\n",
25913 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25914 +               addr = &core_if->dev_if->in_ep_regs[i]->diepint;
25915 +               DWC_PRINTF("DIEPINT      @0x%08lX : 0x%08X\n",
25916 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25917 +               addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz;
25918 +               DWC_PRINTF("DIETSIZ      @0x%08lX : 0x%08X\n",
25919 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25920 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdma;
25921 +               DWC_PRINTF("DIEPDMA      @0x%08lX : 0x%08X\n",
25922 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25923 +               addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts;
25924 +               DWC_PRINTF("DTXFSTS      @0x%08lX : 0x%08X\n",
25925 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25926 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdmab;
25927 +               DWC_PRINTF("DIEPDMAB     @0x%08lX : 0x%08X\n",
25928 +                          (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ );
25929 +       }
25930 +
25931 +       for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25932 +               DWC_PRINTF("Device OUT EP %d Registers\n", i);
25933 +               addr = &core_if->dev_if->out_ep_regs[i]->doepctl;
25934 +               DWC_PRINTF("DOEPCTL      @0x%08lX : 0x%08X\n",
25935 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25936 +               addr = &core_if->dev_if->out_ep_regs[i]->doepint;
25937 +               DWC_PRINTF("DOEPINT      @0x%08lX : 0x%08X\n",
25938 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25939 +               addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz;
25940 +               DWC_PRINTF("DOETSIZ      @0x%08lX : 0x%08X\n",
25941 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25942 +               addr = &core_if->dev_if->out_ep_regs[i]->doepdma;
25943 +               DWC_PRINTF("DOEPDMA      @0x%08lX : 0x%08X\n",
25944 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25945 +               if (core_if->dma_enable) {      /* Don't access this register in SLAVE mode */
25946 +                       addr = &core_if->dev_if->out_ep_regs[i]->doepdmab;
25947 +                       DWC_PRINTF("DOEPDMAB     @0x%08lX : 0x%08X\n",
25948 +                                  (unsigned long)addr, DWC_READ_REG32(addr));
25949 +               }
25950 +
25951 +       }
25952 +}
25953 +
25954 +/**
25955 + * This functions reads the SPRAM and prints its content
25956 + *
25957 + * @param core_if Programming view of DWC_otg controller.
25958 + */
25959 +void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if)
25960 +{
25961 +       volatile uint8_t *addr, *start_addr, *end_addr;
25962 +
25963 +       DWC_PRINTF("SPRAM Data:\n");
25964 +       start_addr = (void *)core_if->core_global_regs;
25965 +       DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr);
25966 +       start_addr += 0x00028000;
25967 +       end_addr = (void *)core_if->core_global_regs;
25968 +       end_addr += 0x000280e0;
25969 +
25970 +       for (addr = start_addr; addr < end_addr; addr += 16) {
25971 +               DWC_PRINTF
25972 +                   ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",
25973 +                    (unsigned long)addr, addr[0], addr[1], addr[2], addr[3],
25974 +                    addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],
25975 +                    addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]
25976 +                   );
25977 +       }
25978 +
25979 +       return;
25980 +}
25981 +
25982 +/**
25983 + * This function reads the host registers and prints them
25984 + *
25985 + * @param core_if Programming view of DWC_otg controller.
25986 + */
25987 +void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if)
25988 +{
25989 +       int i;
25990 +       volatile uint32_t *addr;
25991 +
25992 +       DWC_PRINTF("Host Global Registers\n");
25993 +       addr = &core_if->host_if->host_global_regs->hcfg;
25994 +       DWC_PRINTF("HCFG                 @0x%08lX : 0x%08X\n",
25995 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25996 +       addr = &core_if->host_if->host_global_regs->hfir;
25997 +       DWC_PRINTF("HFIR                 @0x%08lX : 0x%08X\n",
25998 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25999 +       addr = &core_if->host_if->host_global_regs->hfnum;
26000 +       DWC_PRINTF("HFNUM        @0x%08lX : 0x%08X\n", (unsigned long)addr,
26001 +                  DWC_READ_REG32(addr));
26002 +       addr = &core_if->host_if->host_global_regs->hptxsts;
26003 +       DWC_PRINTF("HPTXSTS      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26004 +                  DWC_READ_REG32(addr));
26005 +       addr = &core_if->host_if->host_global_regs->haint;
26006 +       DWC_PRINTF("HAINT        @0x%08lX : 0x%08X\n", (unsigned long)addr,
26007 +                  DWC_READ_REG32(addr));
26008 +       addr = &core_if->host_if->host_global_regs->haintmsk;
26009 +       DWC_PRINTF("HAINTMSK     @0x%08lX : 0x%08X\n", (unsigned long)addr,
26010 +                  DWC_READ_REG32(addr));
26011 +       if (core_if->dma_desc_enable) {
26012 +               addr = &core_if->host_if->host_global_regs->hflbaddr;
26013 +               DWC_PRINTF("HFLBADDR     @0x%08lX : 0x%08X\n",
26014 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26015 +       }
26016 +
26017 +       addr = core_if->host_if->hprt0;
26018 +       DWC_PRINTF("HPRT0        @0x%08lX : 0x%08X\n", (unsigned long)addr,
26019 +                  DWC_READ_REG32(addr));
26020 +
26021 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
26022 +               DWC_PRINTF("Host Channel %d Specific Registers\n", i);
26023 +               addr = &core_if->host_if->hc_regs[i]->hcchar;
26024 +               DWC_PRINTF("HCCHAR       @0x%08lX : 0x%08X\n",
26025 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26026 +               addr = &core_if->host_if->hc_regs[i]->hcsplt;
26027 +               DWC_PRINTF("HCSPLT       @0x%08lX : 0x%08X\n",
26028 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26029 +               addr = &core_if->host_if->hc_regs[i]->hcint;
26030 +               DWC_PRINTF("HCINT        @0x%08lX : 0x%08X\n",
26031 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26032 +               addr = &core_if->host_if->hc_regs[i]->hcintmsk;
26033 +               DWC_PRINTF("HCINTMSK     @0x%08lX : 0x%08X\n",
26034 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26035 +               addr = &core_if->host_if->hc_regs[i]->hctsiz;
26036 +               DWC_PRINTF("HCTSIZ       @0x%08lX : 0x%08X\n",
26037 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26038 +               addr = &core_if->host_if->hc_regs[i]->hcdma;
26039 +               DWC_PRINTF("HCDMA        @0x%08lX : 0x%08X\n",
26040 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26041 +               if (core_if->dma_desc_enable) {
26042 +                       addr = &core_if->host_if->hc_regs[i]->hcdmab;
26043 +                       DWC_PRINTF("HCDMAB       @0x%08lX : 0x%08X\n",
26044 +                                  (unsigned long)addr, DWC_READ_REG32(addr));
26045 +               }
26046 +
26047 +       }
26048 +       return;
26049 +}
26050 +
26051 +/**
26052 + * This function reads the core global registers and prints them
26053 + *
26054 + * @param core_if Programming view of DWC_otg controller.
26055 + */
26056 +void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if)
26057 +{
26058 +       int i, ep_num;
26059 +       volatile uint32_t *addr;
26060 +       char *txfsiz;
26061 +
26062 +       DWC_PRINTF("Core Global Registers\n");
26063 +       addr = &core_if->core_global_regs->gotgctl;
26064 +       DWC_PRINTF("GOTGCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26065 +                  DWC_READ_REG32(addr));
26066 +       addr = &core_if->core_global_regs->gotgint;
26067 +       DWC_PRINTF("GOTGINT      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26068 +                  DWC_READ_REG32(addr));
26069 +       addr = &core_if->core_global_regs->gahbcfg;
26070 +       DWC_PRINTF("GAHBCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26071 +                  DWC_READ_REG32(addr));
26072 +       addr = &core_if->core_global_regs->gusbcfg;
26073 +       DWC_PRINTF("GUSBCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26074 +                  DWC_READ_REG32(addr));
26075 +       addr = &core_if->core_global_regs->grstctl;
26076 +       DWC_PRINTF("GRSTCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26077 +                  DWC_READ_REG32(addr));
26078 +       addr = &core_if->core_global_regs->gintsts;
26079 +       DWC_PRINTF("GINTSTS      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26080 +                  DWC_READ_REG32(addr));
26081 +       addr = &core_if->core_global_regs->gintmsk;
26082 +       DWC_PRINTF("GINTMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26083 +                  DWC_READ_REG32(addr));
26084 +       addr = &core_if->core_global_regs->grxstsr;
26085 +       DWC_PRINTF("GRXSTSR      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26086 +                  DWC_READ_REG32(addr));
26087 +       addr = &core_if->core_global_regs->grxfsiz;
26088 +       DWC_PRINTF("GRXFSIZ      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26089 +                  DWC_READ_REG32(addr));
26090 +       addr = &core_if->core_global_regs->gnptxfsiz;
26091 +       DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
26092 +                  DWC_READ_REG32(addr));
26093 +       addr = &core_if->core_global_regs->gnptxsts;
26094 +       DWC_PRINTF("GNPTXSTS     @0x%08lX : 0x%08X\n", (unsigned long)addr,
26095 +                  DWC_READ_REG32(addr));
26096 +       addr = &core_if->core_global_regs->gi2cctl;
26097 +       DWC_PRINTF("GI2CCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26098 +                  DWC_READ_REG32(addr));
26099 +       addr = &core_if->core_global_regs->gpvndctl;
26100 +       DWC_PRINTF("GPVNDCTL     @0x%08lX : 0x%08X\n", (unsigned long)addr,
26101 +                  DWC_READ_REG32(addr));
26102 +       addr = &core_if->core_global_regs->ggpio;
26103 +       DWC_PRINTF("GGPIO        @0x%08lX : 0x%08X\n", (unsigned long)addr,
26104 +                  DWC_READ_REG32(addr));
26105 +       addr = &core_if->core_global_regs->guid;
26106 +       DWC_PRINTF("GUID                 @0x%08lX : 0x%08X\n",
26107 +                  (unsigned long)addr, DWC_READ_REG32(addr));
26108 +       addr = &core_if->core_global_regs->gsnpsid;
26109 +       DWC_PRINTF("GSNPSID      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26110 +                  DWC_READ_REG32(addr));
26111 +       addr = &core_if->core_global_regs->ghwcfg1;
26112 +       DWC_PRINTF("GHWCFG1      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26113 +                  DWC_READ_REG32(addr));
26114 +       addr = &core_if->core_global_regs->ghwcfg2;
26115 +       DWC_PRINTF("GHWCFG2      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26116 +                  DWC_READ_REG32(addr));
26117 +       addr = &core_if->core_global_regs->ghwcfg3;
26118 +       DWC_PRINTF("GHWCFG3      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26119 +                  DWC_READ_REG32(addr));
26120 +       addr = &core_if->core_global_regs->ghwcfg4;
26121 +       DWC_PRINTF("GHWCFG4      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26122 +                  DWC_READ_REG32(addr));
26123 +       addr = &core_if->core_global_regs->glpmcfg;
26124 +       DWC_PRINTF("GLPMCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26125 +                  DWC_READ_REG32(addr));
26126 +       addr = &core_if->core_global_regs->gpwrdn;
26127 +       DWC_PRINTF("GPWRDN       @0x%08lX : 0x%08X\n", (unsigned long)addr,
26128 +                  DWC_READ_REG32(addr));
26129 +       addr = &core_if->core_global_regs->gdfifocfg;
26130 +       DWC_PRINTF("GDFIFOCFG    @0x%08lX : 0x%08X\n", (unsigned long)addr,
26131 +                  DWC_READ_REG32(addr));
26132 +       addr = &core_if->core_global_regs->adpctl;
26133 +       DWC_PRINTF("ADPCTL       @0x%08lX : 0x%08X\n", (unsigned long)addr,
26134 +                  dwc_otg_adp_read_reg(core_if));
26135 +       addr = &core_if->core_global_regs->hptxfsiz;
26136 +       DWC_PRINTF("HPTXFSIZ     @0x%08lX : 0x%08X\n", (unsigned long)addr,
26137 +                  DWC_READ_REG32(addr));
26138 +
26139 +       if (core_if->en_multiple_tx_fifo == 0) {
26140 +               ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep;
26141 +               txfsiz = "DPTXFSIZ";
26142 +       } else {
26143 +               ep_num = core_if->hwcfg4.b.num_in_eps;
26144 +               txfsiz = "DIENPTXF";
26145 +       }
26146 +       for (i = 0; i < ep_num; i++) {
26147 +               addr = &core_if->core_global_regs->dtxfsiz[i];
26148 +               DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1,
26149 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26150 +       }
26151 +       addr = core_if->pcgcctl;
26152 +       DWC_PRINTF("PCGCCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26153 +                  DWC_READ_REG32(addr));
26154 +}
26155 +
26156 +/**
26157 + * Flush a Tx FIFO.
26158 + *
26159 + * @param core_if Programming view of DWC_otg controller.
26160 + * @param num Tx FIFO to flush.
26161 + */
26162 +void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
26163 +{
26164 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26165 +       volatile grstctl_t greset = {.d32 = 0 };
26166 +       int count = 0;
26167 +
26168 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num);
26169 +
26170 +       greset.b.txfflsh = 1;
26171 +       greset.b.txfnum = num;
26172 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26173 +
26174 +       do {
26175 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26176 +               if (++count > 10000) {
26177 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
26178 +                                __func__, greset.d32,
26179 +                                DWC_READ_REG32(&global_regs->gnptxsts));
26180 +                       break;
26181 +               }
26182 +               dwc_udelay(1);
26183 +       } while (greset.b.txfflsh == 1);
26184 +
26185 +       /* Wait for 3 PHY Clocks */
26186 +       dwc_udelay(1);
26187 +}
26188 +
26189 +/**
26190 + * Flush Rx FIFO.
26191 + *
26192 + * @param core_if Programming view of DWC_otg controller.
26193 + */
26194 +void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
26195 +{
26196 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26197 +       volatile grstctl_t greset = {.d32 = 0 };
26198 +       int count = 0;
26199 +
26200 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__);
26201 +       /*
26202 +        *
26203 +        */
26204 +       greset.b.rxfflsh = 1;
26205 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26206 +
26207 +       do {
26208 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26209 +               if (++count > 10000) {
26210 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__,
26211 +                                greset.d32);
26212 +                       break;
26213 +               }
26214 +               dwc_udelay(1);
26215 +       } while (greset.b.rxfflsh == 1);
26216 +
26217 +       /* Wait for 3 PHY Clocks */
26218 +       dwc_udelay(1);
26219 +}
26220 +
26221 +/**
26222 + * Do core a soft reset of the core.  Be careful with this because it
26223 + * resets all the internal state machines of the core.
26224 + */
26225 +void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
26226 +{
26227 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26228 +       volatile grstctl_t greset = {.d32 = 0 };
26229 +       int count = 0;
26230 +
26231 +       DWC_DEBUGPL(DBG_CILV, "%s\n", __func__);
26232 +       /* Wait for AHB master IDLE state. */
26233 +       do {
26234 +               dwc_udelay(10);
26235 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26236 +               if (++count > 100000) {
26237 +                       DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
26238 +                                greset.d32);
26239 +                       return;
26240 +               }
26241 +       }
26242 +       while (greset.b.ahbidle == 0);
26243 +
26244 +       /* Core Soft Reset */
26245 +       count = 0;
26246 +       greset.b.csftrst = 1;
26247 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26248 +       do {
26249 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26250 +               if (++count > 10000) {
26251 +                       DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n",
26252 +                                __func__, greset.d32);
26253 +                       break;
26254 +               }
26255 +               dwc_udelay(1);
26256 +       }
26257 +       while (greset.b.csftrst == 1);
26258 +
26259 +       /* Wait for 3 PHY Clocks */
26260 +       dwc_mdelay(100);
26261 +}
26262 +
26263 +uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if)
26264 +{
26265 +       return (dwc_otg_mode(_core_if) != DWC_HOST_MODE);
26266 +}
26267 +
26268 +uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if)
26269 +{
26270 +       return (dwc_otg_mode(_core_if) == DWC_HOST_MODE);
26271 +}
26272 +
26273 +/**
26274 + * Register HCD callbacks. The callbacks are used to start and stop
26275 + * the HCD for interrupt processing.
26276 + *
26277 + * @param core_if Programming view of DWC_otg controller.
26278 + * @param cb the HCD callback structure.
26279 + * @param p pointer to be passed to callback function (usb_hcd*).
26280 + */
26281 +void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if,
26282 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
26283 +{
26284 +       core_if->hcd_cb = cb;
26285 +       cb->p = p;
26286 +}
26287 +
26288 +/**
26289 + * Register PCD callbacks. The callbacks are used to start and stop
26290 + * the PCD for interrupt processing.
26291 + *
26292 + * @param core_if Programming view of DWC_otg controller.
26293 + * @param cb the PCD callback structure.
26294 + * @param p pointer to be passed to callback function (pcd*).
26295 + */
26296 +void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if,
26297 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
26298 +{
26299 +       core_if->pcd_cb = cb;
26300 +       cb->p = p;
26301 +}
26302 +
26303 +#ifdef DWC_EN_ISOC
26304 +
26305 +/**
26306 + * This function writes isoc data per 1 (micro)frame into tx fifo
26307 + *
26308 + * @param core_if Programming view of DWC_otg controller.
26309 + * @param ep The EP to start the transfer on.
26310 + *
26311 + */
26312 +void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
26313 +{
26314 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
26315 +       dtxfsts_data_t txstatus = {.d32 = 0 };
26316 +       uint32_t len = 0;
26317 +       uint32_t dwords;
26318 +
26319 +       ep->xfer_len = ep->data_per_frame;
26320 +       ep->xfer_count = 0;
26321 +
26322 +       ep_regs = core_if->dev_if->in_ep_regs[ep->num];
26323 +
26324 +       len = ep->xfer_len - ep->xfer_count;
26325 +
26326 +       if (len > ep->maxpacket) {
26327 +               len = ep->maxpacket;
26328 +       }
26329 +
26330 +       dwords = (len + 3) / 4;
26331 +
26332 +       /* While there is space in the queue and space in the FIFO and
26333 +        * More data to tranfer, Write packets to the Tx FIFO */
26334 +       txstatus.d32 =
26335 +           DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts);
26336 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32);
26337 +
26338 +       while (txstatus.b.txfspcavail > dwords &&
26339 +              ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) {
26340 +               /* Write the FIFO */
26341 +               dwc_otg_ep_write_packet(core_if, ep, 0);
26342 +
26343 +               len = ep->xfer_len - ep->xfer_count;
26344 +               if (len > ep->maxpacket) {
26345 +                       len = ep->maxpacket;
26346 +               }
26347 +
26348 +               dwords = (len + 3) / 4;
26349 +               txstatus.d32 =
26350 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
26351 +                                  dtxfsts);
26352 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num,
26353 +                           txstatus.d32);
26354 +       }
26355 +}
26356 +
26357 +/**
26358 + * This function initializes a descriptor chain for Isochronous transfer
26359 + *
26360 + * @param core_if Programming view of DWC_otg controller.
26361 + * @param ep The EP to start the transfer on.
26362 + *
26363 + */
26364 +void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
26365 +                                      dwc_ep_t * ep)
26366 +{
26367 +       deptsiz_data_t deptsiz = {.d32 = 0 };
26368 +       depctl_data_t depctl = {.d32 = 0 };
26369 +       dsts_data_t dsts = {.d32 = 0 };
26370 +       volatile uint32_t *addr;
26371 +
26372 +       if (ep->is_in) {
26373 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
26374 +       } else {
26375 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
26376 +       }
26377 +
26378 +       ep->xfer_len = ep->data_per_frame;
26379 +       ep->xfer_count = 0;
26380 +       ep->xfer_buff = ep->cur_pkt_addr;
26381 +       ep->dma_addr = ep->cur_pkt_dma_addr;
26382 +
26383 +       if (ep->is_in) {
26384 +               /* Program the transfer size and packet count
26385 +                *      as follows: xfersize = N * maxpacket +
26386 +                *      short_packet pktcnt = N + (short_packet
26387 +                *      exist ? 1 : 0) 
26388 +                */
26389 +               deptsiz.b.xfersize = ep->xfer_len;
26390 +               deptsiz.b.pktcnt =
26391 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
26392 +               deptsiz.b.mc = deptsiz.b.pktcnt;
26393 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz,
26394 +                               deptsiz.d32);
26395 +
26396 +               /* Write the DMA register */
26397 +               if (core_if->dma_enable) {
26398 +                       DWC_WRITE_REG32(&
26399 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
26400 +                                        diepdma), (uint32_t) ep->dma_addr);
26401 +               }
26402 +       } else {
26403 +               deptsiz.b.pktcnt =
26404 +                   (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;
26405 +               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
26406 +
26407 +               DWC_WRITE_REG32(&core_if->dev_if->
26408 +                               out_ep_regs[ep->num]->doeptsiz, deptsiz.d32);
26409 +
26410 +               if (core_if->dma_enable) {
26411 +                       DWC_WRITE_REG32(&
26412 +                                       (core_if->dev_if->
26413 +                                        out_ep_regs[ep->num]->doepdma),
26414 +                                       (uint32_t) ep->dma_addr);
26415 +               }
26416 +       }
26417 +
26418 +       /** Enable endpoint, clear nak  */
26419 +
26420 +       depctl.d32 = 0;
26421 +       if (ep->bInterval == 1) {
26422 +               dsts.d32 =
26423 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
26424 +               ep->next_frame = dsts.b.soffn + ep->bInterval;
26425 +
26426 +               if (ep->next_frame & 0x1) {
26427 +                       depctl.b.setd1pid = 1;
26428 +               } else {
26429 +                       depctl.b.setd0pid = 1;
26430 +               }
26431 +       } else {
26432 +               ep->next_frame += ep->bInterval;
26433 +
26434 +               if (ep->next_frame & 0x1) {
26435 +                       depctl.b.setd1pid = 1;
26436 +               } else {
26437 +                       depctl.b.setd0pid = 1;
26438 +               }
26439 +       }
26440 +       depctl.b.epena = 1;
26441 +       depctl.b.cnak = 1;
26442 +
26443 +       DWC_MODIFY_REG32(addr, 0, depctl.d32);
26444 +       depctl.d32 = DWC_READ_REG32(addr);
26445 +
26446 +       if (ep->is_in && core_if->dma_enable == 0) {
26447 +               write_isoc_frame_data(core_if, ep);
26448 +       }
26449 +
26450 +}
26451 +#endif /* DWC_EN_ISOC */
26452 +
26453 +static void dwc_otg_set_uninitialized(int32_t * p, int size)
26454 +{
26455 +       int i;
26456 +       for (i = 0; i < size; i++) {
26457 +               p[i] = -1;
26458 +       }
26459 +}
26460 +
26461 +static int dwc_otg_param_initialized(int32_t val)
26462 +{
26463 +       return val != -1;
26464 +}
26465 +
26466 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
26467 +{
26468 +       int i;
26469 +       core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params));
26470 +       if (!core_if->core_params) {
26471 +               return -DWC_E_NO_MEMORY;
26472 +       }
26473 +       dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
26474 +                                 sizeof(*core_if->core_params) /
26475 +                                 sizeof(int32_t));
26476 +       DWC_PRINTF("Setting default values for core params\n");
26477 +       dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
26478 +       dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
26479 +       dwc_otg_set_param_dma_desc_enable(core_if,
26480 +                                         dwc_param_dma_desc_enable_default);
26481 +       dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
26482 +       dwc_otg_set_param_dma_burst_size(core_if,
26483 +                                        dwc_param_dma_burst_size_default);
26484 +       dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
26485 +                                                      dwc_param_host_support_fs_ls_low_power_default);
26486 +       dwc_otg_set_param_enable_dynamic_fifo(core_if,
26487 +                                             dwc_param_enable_dynamic_fifo_default);
26488 +       dwc_otg_set_param_data_fifo_size(core_if,
26489 +                                        dwc_param_data_fifo_size_default);
26490 +       dwc_otg_set_param_dev_rx_fifo_size(core_if,
26491 +                                          dwc_param_dev_rx_fifo_size_default);
26492 +       dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
26493 +                                                 dwc_param_dev_nperio_tx_fifo_size_default);
26494 +       dwc_otg_set_param_host_rx_fifo_size(core_if,
26495 +                                           dwc_param_host_rx_fifo_size_default);
26496 +       dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
26497 +                                                  dwc_param_host_nperio_tx_fifo_size_default);
26498 +       dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
26499 +                                                 dwc_param_host_perio_tx_fifo_size_default);
26500 +       dwc_otg_set_param_max_transfer_size(core_if,
26501 +                                           dwc_param_max_transfer_size_default);
26502 +       dwc_otg_set_param_max_packet_count(core_if,
26503 +                                          dwc_param_max_packet_count_default);
26504 +       dwc_otg_set_param_host_channels(core_if,
26505 +                                       dwc_param_host_channels_default);
26506 +       dwc_otg_set_param_dev_endpoints(core_if,
26507 +                                       dwc_param_dev_endpoints_default);
26508 +       dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
26509 +       dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
26510 +       dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
26511 +                                                   dwc_param_host_ls_low_power_phy_clk_default);
26512 +       dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
26513 +       dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
26514 +                                           dwc_param_phy_ulpi_ext_vbus_default);
26515 +       dwc_otg_set_param_phy_utmi_width(core_if,
26516 +                                        dwc_param_phy_utmi_width_default);
26517 +       dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
26518 +       dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
26519 +       dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
26520 +       dwc_otg_set_param_en_multiple_tx_fifo(core_if,
26521 +                                             dwc_param_en_multiple_tx_fifo_default);
26522 +       for (i = 0; i < 15; i++) {
26523 +               dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
26524 +                                                        dwc_param_dev_perio_tx_fifo_size_default,
26525 +                                                        i);
26526 +       }
26527 +
26528 +       for (i = 0; i < 15; i++) {
26529 +               dwc_otg_set_param_dev_tx_fifo_size(core_if,
26530 +                                                  dwc_param_dev_tx_fifo_size_default,
26531 +                                                  i);
26532 +       }
26533 +       dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
26534 +       dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
26535 +       dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
26536 +       dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
26537 +       dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
26538 +       dwc_otg_set_param_tx_thr_length(core_if,
26539 +                                       dwc_param_tx_thr_length_default);
26540 +       dwc_otg_set_param_rx_thr_length(core_if,
26541 +                                       dwc_param_rx_thr_length_default);
26542 +       dwc_otg_set_param_ahb_thr_ratio(core_if,
26543 +                                       dwc_param_ahb_thr_ratio_default);
26544 +       dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default);
26545 +       dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default);
26546 +       dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default);
26547 +       dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default);
26548 +       dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default);
26549 +       dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default);
26550 +       dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default);
26551 +       DWC_PRINTF("Finished setting default values for core params\n");
26552 +
26553 +       return 0;
26554 +}
26555 +
26556 +uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if)
26557 +{
26558 +       return core_if->dma_enable;
26559 +}
26560 +
26561 +/* Checks if the parameter is outside of its valid range of values */
26562 +#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
26563 +               (((_param_) < (_low_)) || \
26564 +               ((_param_) > (_high_)))
26565 +
26566 +/* Parameter access functions */
26567 +int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val)
26568 +{
26569 +       int valid;
26570 +       int retval = 0;
26571 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
26572 +               DWC_WARN("Wrong value for otg_cap parameter\n");
26573 +               DWC_WARN("otg_cap parameter must be 0,1 or 2\n");
26574 +               retval = -DWC_E_INVALID;
26575 +               goto out;
26576 +       }
26577 +
26578 +       valid = 1;
26579 +       switch (val) {
26580 +       case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
26581 +               if (core_if->hwcfg2.b.op_mode !=
26582 +                   DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26583 +                       valid = 0;
26584 +               break;
26585 +       case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
26586 +               if ((core_if->hwcfg2.b.op_mode !=
26587 +                    DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26588 +                   && (core_if->hwcfg2.b.op_mode !=
26589 +                       DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26590 +                   && (core_if->hwcfg2.b.op_mode !=
26591 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26592 +                   && (core_if->hwcfg2.b.op_mode !=
26593 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
26594 +                       valid = 0;
26595 +               }
26596 +               break;
26597 +       case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
26598 +               /* always valid */
26599 +               break;
26600 +       }
26601 +       if (!valid) {
26602 +               if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
26603 +                       DWC_ERROR
26604 +                           ("%d invalid for otg_cap paremter. Check HW configuration.\n",
26605 +                            val);
26606 +               }
26607 +               val =
26608 +                   (((core_if->hwcfg2.b.op_mode ==
26609 +                      DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26610 +                     || (core_if->hwcfg2.b.op_mode ==
26611 +                         DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26612 +                     || (core_if->hwcfg2.b.op_mode ==
26613 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26614 +                     || (core_if->hwcfg2.b.op_mode ==
26615 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
26616 +                    DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
26617 +                    DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
26618 +               retval = -DWC_E_INVALID;
26619 +       }
26620 +
26621 +       core_if->core_params->otg_cap = val;
26622 +out:
26623 +       return retval;
26624 +}
26625 +
26626 +int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if)
26627 +{
26628 +       return core_if->core_params->otg_cap;
26629 +}
26630 +
26631 +int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val)
26632 +{
26633 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26634 +               DWC_WARN("Wrong value for opt parameter\n");
26635 +               return -DWC_E_INVALID;
26636 +       }
26637 +       core_if->core_params->opt = val;
26638 +       return 0;
26639 +}
26640 +
26641 +int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if)
26642 +{
26643 +       return core_if->core_params->opt;
26644 +}
26645 +
26646 +int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val)
26647 +{
26648 +       int retval = 0;
26649 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26650 +               DWC_WARN("Wrong value for dma enable\n");
26651 +               return -DWC_E_INVALID;
26652 +       }
26653 +
26654 +       if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
26655 +               if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
26656 +                       DWC_ERROR
26657 +                           ("%d invalid for dma_enable paremter. Check HW configuration.\n",
26658 +                            val);
26659 +               }
26660 +               val = 0;
26661 +               retval = -DWC_E_INVALID;
26662 +       }
26663 +
26664 +       core_if->core_params->dma_enable = val;
26665 +       if (val == 0) {
26666 +               dwc_otg_set_param_dma_desc_enable(core_if, 0);
26667 +       }
26668 +       return retval;
26669 +}
26670 +
26671 +int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if)
26672 +{
26673 +       return core_if->core_params->dma_enable;
26674 +}
26675 +
26676 +int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val)
26677 +{
26678 +       int retval = 0;
26679 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26680 +               DWC_WARN("Wrong value for dma_enable\n");
26681 +               DWC_WARN("dma_desc_enable must be 0 or 1\n");
26682 +               return -DWC_E_INVALID;
26683 +       }
26684 +
26685 +       if ((val == 1)
26686 +           && ((dwc_otg_get_param_dma_enable(core_if) == 0)
26687 +               || (core_if->hwcfg4.b.desc_dma == 0))) {
26688 +               if (dwc_otg_param_initialized
26689 +                   (core_if->core_params->dma_desc_enable)) {
26690 +                       DWC_ERROR
26691 +                           ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n",
26692 +                            val);
26693 +               }
26694 +               val = 0;
26695 +               retval = -DWC_E_INVALID;
26696 +       }
26697 +       core_if->core_params->dma_desc_enable = val;
26698 +       return retval;
26699 +}
26700 +
26701 +int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if)
26702 +{
26703 +       return core_if->core_params->dma_desc_enable;
26704 +}
26705 +
26706 +int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if,
26707 +                                                  int32_t val)
26708 +{
26709 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26710 +               DWC_WARN("Wrong value for host_support_fs_low_power\n");
26711 +               DWC_WARN("host_support_fs_low_power must be 0 or 1\n");
26712 +               return -DWC_E_INVALID;
26713 +       }
26714 +       core_if->core_params->host_support_fs_ls_low_power = val;
26715 +       return 0;
26716 +}
26717 +
26718 +int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
26719 +                                                      core_if)
26720 +{
26721 +       return core_if->core_params->host_support_fs_ls_low_power;
26722 +}
26723 +
26724 +int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
26725 +                                         int32_t val)
26726 +{
26727 +       int retval = 0;
26728 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26729 +               DWC_WARN("Wrong value for enable_dynamic_fifo\n");
26730 +               DWC_WARN("enable_dynamic_fifo must be 0 or 1\n");
26731 +               return -DWC_E_INVALID;
26732 +       }
26733 +
26734 +       if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
26735 +               if (dwc_otg_param_initialized
26736 +                   (core_if->core_params->enable_dynamic_fifo)) {
26737 +                       DWC_ERROR
26738 +                           ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
26739 +                            val);
26740 +               }
26741 +               val = 0;
26742 +               retval = -DWC_E_INVALID;
26743 +       }
26744 +       core_if->core_params->enable_dynamic_fifo = val;
26745 +       return retval;
26746 +}
26747 +
26748 +int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if)
26749 +{
26750 +       return core_if->core_params->enable_dynamic_fifo;
26751 +}
26752 +
26753 +int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26754 +{
26755 +       int retval = 0;
26756 +       if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
26757 +               DWC_WARN("Wrong value for data_fifo_size\n");
26758 +               DWC_WARN("data_fifo_size must be 32-32768\n");
26759 +               return -DWC_E_INVALID;
26760 +       }
26761 +
26762 +       if (val > core_if->hwcfg3.b.dfifo_depth) {
26763 +               if (dwc_otg_param_initialized
26764 +                   (core_if->core_params->data_fifo_size)) {
26765 +                       DWC_ERROR
26766 +                           ("%d invalid for data_fifo_size parameter. Check HW configuration.\n",
26767 +                            val);
26768 +               }
26769 +               val = core_if->hwcfg3.b.dfifo_depth;
26770 +               retval = -DWC_E_INVALID;
26771 +       }
26772 +
26773 +       core_if->core_params->data_fifo_size = val;
26774 +       return retval;
26775 +}
26776 +
26777 +int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if)
26778 +{
26779 +       return core_if->core_params->data_fifo_size;
26780 +}
26781 +
26782 +int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26783 +{
26784 +       int retval = 0;
26785 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26786 +               DWC_WARN("Wrong value for dev_rx_fifo_size\n");
26787 +               DWC_WARN("dev_rx_fifo_size must be 16-32768\n");
26788 +               return -DWC_E_INVALID;
26789 +       }
26790 +
26791 +       if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26792 +               if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
26793 +               DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val);
26794 +               }
26795 +               val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26796 +               retval = -DWC_E_INVALID;
26797 +       }
26798 +
26799 +       core_if->core_params->dev_rx_fifo_size = val;
26800 +       return retval;
26801 +}
26802 +
26803 +int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if)
26804 +{
26805 +       return core_if->core_params->dev_rx_fifo_size;
26806 +}
26807 +
26808 +int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26809 +                                             int32_t val)
26810 +{
26811 +       int retval = 0;
26812 +
26813 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26814 +               DWC_WARN("Wrong value for dev_nperio_tx_fifo\n");
26815 +               DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n");
26816 +               return -DWC_E_INVALID;
26817 +       }
26818 +
26819 +       if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26820 +               if (dwc_otg_param_initialized
26821 +                   (core_if->core_params->dev_nperio_tx_fifo_size)) {
26822 +                       DWC_ERROR
26823 +                           ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
26824 +                            val);
26825 +               }
26826 +               val =
26827 +                   (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26828 +                    16);
26829 +               retval = -DWC_E_INVALID;
26830 +       }
26831 +
26832 +       core_if->core_params->dev_nperio_tx_fifo_size = val;
26833 +       return retval;
26834 +}
26835 +
26836 +int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26837 +{
26838 +       return core_if->core_params->dev_nperio_tx_fifo_size;
26839 +}
26840 +
26841 +int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
26842 +                                       int32_t val)
26843 +{
26844 +       int retval = 0;
26845 +
26846 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26847 +               DWC_WARN("Wrong value for host_rx_fifo_size\n");
26848 +               DWC_WARN("host_rx_fifo_size must be 16-32768\n");
26849 +               return -DWC_E_INVALID;
26850 +       }
26851 +
26852 +       if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26853 +               if (dwc_otg_param_initialized
26854 +                   (core_if->core_params->host_rx_fifo_size)) {
26855 +                       DWC_ERROR
26856 +                           ("%d invalid for host_rx_fifo_size. Check HW configuration.\n",
26857 +                            val);
26858 +               }
26859 +               val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26860 +               retval = -DWC_E_INVALID;
26861 +       }
26862 +
26863 +       core_if->core_params->host_rx_fifo_size = val;
26864 +       return retval;
26865 +
26866 +}
26867 +
26868 +int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if)
26869 +{
26870 +       return core_if->core_params->host_rx_fifo_size;
26871 +}
26872 +
26873 +int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26874 +                                              int32_t val)
26875 +{
26876 +       int retval = 0;
26877 +
26878 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26879 +               DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n");
26880 +               DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n");
26881 +               return -DWC_E_INVALID;
26882 +       }
26883 +
26884 +       if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26885 +               if (dwc_otg_param_initialized
26886 +                   (core_if->core_params->host_nperio_tx_fifo_size)) {
26887 +                       DWC_ERROR
26888 +                           ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
26889 +                            val);
26890 +               }
26891 +               val =
26892 +                   (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26893 +                    16);
26894 +               retval = -DWC_E_INVALID;
26895 +       }
26896 +
26897 +       core_if->core_params->host_nperio_tx_fifo_size = val;
26898 +       return retval;
26899 +}
26900 +
26901 +int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26902 +{
26903 +       return core_if->core_params->host_nperio_tx_fifo_size;
26904 +}
26905 +
26906 +int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26907 +                                             int32_t val)
26908 +{
26909 +       int retval = 0;
26910 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26911 +               DWC_WARN("Wrong value for host_perio_tx_fifo_size\n");
26912 +               DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n");
26913 +               return -DWC_E_INVALID;
26914 +       }
26915 +
26916 +       if (val > ((core_if->hptxfsiz.d32) >> 16)) {
26917 +               if (dwc_otg_param_initialized
26918 +                   (core_if->core_params->host_perio_tx_fifo_size)) {
26919 +                       DWC_ERROR
26920 +                           ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
26921 +                            val);
26922 +               }
26923 +               val = (core_if->hptxfsiz.d32) >> 16;
26924 +               retval = -DWC_E_INVALID;
26925 +       }
26926 +
26927 +       core_if->core_params->host_perio_tx_fifo_size = val;
26928 +       return retval;
26929 +}
26930 +
26931 +int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26932 +{
26933 +       return core_if->core_params->host_perio_tx_fifo_size;
26934 +}
26935 +
26936 +int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
26937 +                                       int32_t val)
26938 +{
26939 +       int retval = 0;
26940 +
26941 +       if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
26942 +               DWC_WARN("Wrong value for max_transfer_size\n");
26943 +               DWC_WARN("max_transfer_size must be 2047-524288\n");
26944 +               return -DWC_E_INVALID;
26945 +       }
26946 +
26947 +       if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
26948 +               if (dwc_otg_param_initialized
26949 +                   (core_if->core_params->max_transfer_size)) {
26950 +                       DWC_ERROR
26951 +                           ("%d invalid for max_transfer_size. Check HW configuration.\n",
26952 +                            val);
26953 +               }
26954 +               val =
26955 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
26956 +                    1);
26957 +               retval = -DWC_E_INVALID;
26958 +       }
26959 +
26960 +       core_if->core_params->max_transfer_size = val;
26961 +       return retval;
26962 +}
26963 +
26964 +int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if)
26965 +{
26966 +       return core_if->core_params->max_transfer_size;
26967 +}
26968 +
26969 +int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val)
26970 +{
26971 +       int retval = 0;
26972 +
26973 +       if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
26974 +               DWC_WARN("Wrong value for max_packet_count\n");
26975 +               DWC_WARN("max_packet_count must be 15-511\n");
26976 +               return -DWC_E_INVALID;
26977 +       }
26978 +
26979 +       if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
26980 +               if (dwc_otg_param_initialized
26981 +                   (core_if->core_params->max_packet_count)) {
26982 +                       DWC_ERROR
26983 +                           ("%d invalid for max_packet_count. Check HW configuration.\n",
26984 +                            val);
26985 +               }
26986 +               val =
26987 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
26988 +               retval = -DWC_E_INVALID;
26989 +       }
26990 +
26991 +       core_if->core_params->max_packet_count = val;
26992 +       return retval;
26993 +}
26994 +
26995 +int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if)
26996 +{
26997 +       return core_if->core_params->max_packet_count;
26998 +}
26999 +
27000 +int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val)
27001 +{
27002 +       int retval = 0;
27003 +
27004 +       if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
27005 +               DWC_WARN("Wrong value for host_channels\n");
27006 +               DWC_WARN("host_channels must be 1-16\n");
27007 +               return -DWC_E_INVALID;
27008 +       }
27009 +
27010 +       if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
27011 +               if (dwc_otg_param_initialized
27012 +                   (core_if->core_params->host_channels)) {
27013 +                       DWC_ERROR
27014 +                           ("%d invalid for host_channels. Check HW configurations.\n",
27015 +                            val);
27016 +               }
27017 +               val = (core_if->hwcfg2.b.num_host_chan + 1);
27018 +               retval = -DWC_E_INVALID;
27019 +       }
27020 +
27021 +       core_if->core_params->host_channels = val;
27022 +       return retval;
27023 +}
27024 +
27025 +int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if)
27026 +{
27027 +       return core_if->core_params->host_channels;
27028 +}
27029 +
27030 +int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val)
27031 +{
27032 +       int retval = 0;
27033 +
27034 +       if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
27035 +               DWC_WARN("Wrong value for dev_endpoints\n");
27036 +               DWC_WARN("dev_endpoints must be 1-15\n");
27037 +               return -DWC_E_INVALID;
27038 +       }
27039 +
27040 +       if (val > (core_if->hwcfg2.b.num_dev_ep)) {
27041 +               if (dwc_otg_param_initialized
27042 +                   (core_if->core_params->dev_endpoints)) {
27043 +                       DWC_ERROR
27044 +                           ("%d invalid for dev_endpoints. Check HW configurations.\n",
27045 +                            val);
27046 +               }
27047 +               val = core_if->hwcfg2.b.num_dev_ep;
27048 +               retval = -DWC_E_INVALID;
27049 +       }
27050 +
27051 +       core_if->core_params->dev_endpoints = val;
27052 +       return retval;
27053 +}
27054 +
27055 +int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if)
27056 +{
27057 +       return core_if->core_params->dev_endpoints;
27058 +}
27059 +
27060 +int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val)
27061 +{
27062 +       int retval = 0;
27063 +       int valid = 0;
27064 +
27065 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
27066 +               DWC_WARN("Wrong value for phy_type\n");
27067 +               DWC_WARN("phy_type must be 0,1 or 2\n");
27068 +               return -DWC_E_INVALID;
27069 +       }
27070 +#ifndef NO_FS_PHY_HW_CHECKS
27071 +       if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
27072 +           ((core_if->hwcfg2.b.hs_phy_type == 1) ||
27073 +            (core_if->hwcfg2.b.hs_phy_type == 3))) {
27074 +               valid = 1;
27075 +       } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
27076 +                  ((core_if->hwcfg2.b.hs_phy_type == 2) ||
27077 +                   (core_if->hwcfg2.b.hs_phy_type == 3))) {
27078 +               valid = 1;
27079 +       } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
27080 +                  (core_if->hwcfg2.b.fs_phy_type == 1)) {
27081 +               valid = 1;
27082 +       }
27083 +       if (!valid) {
27084 +               if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
27085 +                       DWC_ERROR
27086 +                           ("%d invalid for phy_type. Check HW configurations.\n",
27087 +                            val);
27088 +               }
27089 +               if (core_if->hwcfg2.b.hs_phy_type) {
27090 +                       if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
27091 +                           (core_if->hwcfg2.b.hs_phy_type == 1)) {
27092 +                               val = DWC_PHY_TYPE_PARAM_UTMI;
27093 +                       } else {
27094 +                               val = DWC_PHY_TYPE_PARAM_ULPI;
27095 +                       }
27096 +               }
27097 +               retval = -DWC_E_INVALID;
27098 +       }
27099 +#endif
27100 +       core_if->core_params->phy_type = val;
27101 +       return retval;
27102 +}
27103 +
27104 +int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if)
27105 +{
27106 +       return core_if->core_params->phy_type;
27107 +}
27108 +
27109 +int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val)
27110 +{
27111 +       int retval = 0;
27112 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27113 +               DWC_WARN("Wrong value for speed parameter\n");
27114 +               DWC_WARN("max_speed parameter must be 0 or 1\n");
27115 +               return -DWC_E_INVALID;
27116 +       }
27117 +       if ((val == 0)
27118 +           && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
27119 +               if (dwc_otg_param_initialized(core_if->core_params->speed)) {
27120 +                       DWC_ERROR
27121 +                           ("%d invalid for speed paremter. Check HW configuration.\n",
27122 +                            val);
27123 +               }
27124 +               val =
27125 +                   (dwc_otg_get_param_phy_type(core_if) ==
27126 +                    DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
27127 +               retval = -DWC_E_INVALID;
27128 +       }
27129 +       core_if->core_params->speed = val;
27130 +       return retval;
27131 +}
27132 +
27133 +int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if)
27134 +{
27135 +       return core_if->core_params->speed;
27136 +}
27137 +
27138 +int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if,
27139 +                                               int32_t val)
27140 +{
27141 +       int retval = 0;
27142 +
27143 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27144 +               DWC_WARN
27145 +                   ("Wrong value for host_ls_low_power_phy_clk parameter\n");
27146 +               DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n");
27147 +               return -DWC_E_INVALID;
27148 +       }
27149 +
27150 +       if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
27151 +           && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
27152 +               if (dwc_otg_param_initialized
27153 +                   (core_if->core_params->host_ls_low_power_phy_clk)) {
27154 +                       DWC_ERROR
27155 +                           ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
27156 +                            val);
27157 +               }
27158 +               val =
27159 +                   (dwc_otg_get_param_phy_type(core_if) ==
27160 +                    DWC_PHY_TYPE_PARAM_FS) ?
27161 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
27162 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
27163 +               retval = -DWC_E_INVALID;
27164 +       }
27165 +
27166 +       core_if->core_params->host_ls_low_power_phy_clk = val;
27167 +       return retval;
27168 +}
27169 +
27170 +int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if)
27171 +{
27172 +       return core_if->core_params->host_ls_low_power_phy_clk;
27173 +}
27174 +
27175 +int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val)
27176 +{
27177 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27178 +               DWC_WARN("Wrong value for phy_ulpi_ddr\n");
27179 +               DWC_WARN("phy_upli_ddr must be 0 or 1\n");
27180 +               return -DWC_E_INVALID;
27181 +       }
27182 +
27183 +       core_if->core_params->phy_ulpi_ddr = val;
27184 +       return 0;
27185 +}
27186 +
27187 +int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if)
27188 +{
27189 +       return core_if->core_params->phy_ulpi_ddr;
27190 +}
27191 +
27192 +int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
27193 +                                       int32_t val)
27194 +{
27195 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27196 +               DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n");
27197 +               DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n");
27198 +               return -DWC_E_INVALID;
27199 +       }
27200 +
27201 +       core_if->core_params->phy_ulpi_ext_vbus = val;
27202 +       return 0;
27203 +}
27204 +
27205 +int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if)
27206 +{
27207 +       return core_if->core_params->phy_ulpi_ext_vbus;
27208 +}
27209 +
27210 +int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val)
27211 +{
27212 +       if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
27213 +               DWC_WARN("Wrong valaue for phy_utmi_width\n");
27214 +               DWC_WARN("phy_utmi_width must be 8 or 16\n");
27215 +               return -DWC_E_INVALID;
27216 +       }
27217 +
27218 +       core_if->core_params->phy_utmi_width = val;
27219 +       return 0;
27220 +}
27221 +
27222 +int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if)
27223 +{
27224 +       return core_if->core_params->phy_utmi_width;
27225 +}
27226 +
27227 +int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val)
27228 +{
27229 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27230 +               DWC_WARN("Wrong valaue for ulpi_fs_ls\n");
27231 +               DWC_WARN("ulpi_fs_ls must be 0 or 1\n");
27232 +               return -DWC_E_INVALID;
27233 +       }
27234 +
27235 +       core_if->core_params->ulpi_fs_ls = val;
27236 +       return 0;
27237 +}
27238 +
27239 +int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if)
27240 +{
27241 +       return core_if->core_params->ulpi_fs_ls;
27242 +}
27243 +
27244 +int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val)
27245 +{
27246 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27247 +               DWC_WARN("Wrong valaue for ts_dline\n");
27248 +               DWC_WARN("ts_dline must be 0 or 1\n");
27249 +               return -DWC_E_INVALID;
27250 +       }
27251 +
27252 +       core_if->core_params->ts_dline = val;
27253 +       return 0;
27254 +}
27255 +
27256 +int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if)
27257 +{
27258 +       return core_if->core_params->ts_dline;
27259 +}
27260 +
27261 +int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val)
27262 +{
27263 +       int retval = 0;
27264 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27265 +               DWC_WARN("Wrong valaue for i2c_enable\n");
27266 +               DWC_WARN("i2c_enable must be 0 or 1\n");
27267 +               return -DWC_E_INVALID;
27268 +       }
27269 +#ifndef NO_FS_PHY_HW_CHECK
27270 +       if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
27271 +               if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
27272 +                       DWC_ERROR
27273 +                           ("%d invalid for i2c_enable. Check HW configuration.\n",
27274 +                            val);
27275 +               }
27276 +               val = 0;
27277 +               retval = -DWC_E_INVALID;
27278 +       }
27279 +#endif
27280 +
27281 +       core_if->core_params->i2c_enable = val;
27282 +       return retval;
27283 +}
27284 +
27285 +int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if)
27286 +{
27287 +       return core_if->core_params->i2c_enable;
27288 +}
27289 +
27290 +int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
27291 +                                            int32_t val, int fifo_num)
27292 +{
27293 +       int retval = 0;
27294 +
27295 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27296 +               DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n");
27297 +               DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n");
27298 +               return -DWC_E_INVALID;
27299 +       }
27300 +
27301 +       if (val >
27302 +           (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27303 +               if (dwc_otg_param_initialized
27304 +                   (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
27305 +                       DWC_ERROR
27306 +                           ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
27307 +                            val, fifo_num);
27308 +               }
27309 +               val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27310 +               retval = -DWC_E_INVALID;
27311 +       }
27312 +
27313 +       core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
27314 +       return retval;
27315 +}
27316 +
27317 +int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
27318 +                                                int fifo_num)
27319 +{
27320 +       return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
27321 +}
27322 +
27323 +int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
27324 +                                         int32_t val)
27325 +{
27326 +       int retval = 0;
27327 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27328 +               DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n");
27329 +               DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n");
27330 +               return -DWC_E_INVALID;
27331 +       }
27332 +
27333 +       if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
27334 +               if (dwc_otg_param_initialized
27335 +                   (core_if->core_params->en_multiple_tx_fifo)) {
27336 +                       DWC_ERROR
27337 +                           ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
27338 +                            val);
27339 +               }
27340 +               val = 0;
27341 +               retval = -DWC_E_INVALID;
27342 +       }
27343 +
27344 +       core_if->core_params->en_multiple_tx_fifo = val;
27345 +       return retval;
27346 +}
27347 +
27348 +int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if)
27349 +{
27350 +       return core_if->core_params->en_multiple_tx_fifo;
27351 +}
27352 +
27353 +int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val,
27354 +                                      int fifo_num)
27355 +{
27356 +       int retval = 0;
27357 +
27358 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27359 +               DWC_WARN("Wrong value for dev_tx_fifo_size\n");
27360 +               DWC_WARN("dev_tx_fifo_size must be 4-768\n");
27361 +               return -DWC_E_INVALID;
27362 +       }
27363 +
27364 +       if (val >
27365 +           (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27366 +               if (dwc_otg_param_initialized
27367 +                   (core_if->core_params->dev_tx_fifo_size[fifo_num])) {
27368 +                       DWC_ERROR
27369 +                           ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
27370 +                            val, fifo_num);
27371 +               }
27372 +               val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27373 +               retval = -DWC_E_INVALID;
27374 +       }
27375 +
27376 +       core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
27377 +       return retval;
27378 +}
27379 +
27380 +int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
27381 +                                          int fifo_num)
27382 +{
27383 +       return core_if->core_params->dev_tx_fifo_size[fifo_num];
27384 +}
27385 +
27386 +int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27387 +{
27388 +       int retval = 0;
27389 +
27390 +       if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
27391 +               DWC_WARN("Wrong value for thr_ctl\n");
27392 +               DWC_WARN("thr_ctl must be 0-7\n");
27393 +               return -DWC_E_INVALID;
27394 +       }
27395 +
27396 +       if ((val != 0) &&
27397 +           (!dwc_otg_get_param_dma_enable(core_if) ||
27398 +            !core_if->hwcfg4.b.ded_fifo_en)) {
27399 +               if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
27400 +                       DWC_ERROR
27401 +                           ("%d invalid for parameter thr_ctl. Check HW configuration.\n",
27402 +                            val);
27403 +               }
27404 +               val = 0;
27405 +               retval = -DWC_E_INVALID;
27406 +       }
27407 +
27408 +       core_if->core_params->thr_ctl = val;
27409 +       return retval;
27410 +}
27411 +
27412 +int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if)
27413 +{
27414 +       return core_if->core_params->thr_ctl;
27415 +}
27416 +
27417 +int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val)
27418 +{
27419 +       int retval = 0;
27420 +
27421 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27422 +               DWC_WARN("Wrong value for lpm_enable\n");
27423 +               DWC_WARN("lpm_enable must be 0 or 1\n");
27424 +               return -DWC_E_INVALID;
27425 +       }
27426 +
27427 +       if (val && !core_if->hwcfg3.b.otg_lpm_en) {
27428 +               if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
27429 +                       DWC_ERROR
27430 +                           ("%d invalid for parameter lpm_enable. Check HW configuration.\n",
27431 +                            val);
27432 +               }
27433 +               val = 0;
27434 +               retval = -DWC_E_INVALID;
27435 +       }
27436 +
27437 +       core_if->core_params->lpm_enable = val;
27438 +       return retval;
27439 +}
27440 +
27441 +int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if)
27442 +{
27443 +       return core_if->core_params->lpm_enable;
27444 +}
27445 +
27446 +int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27447 +{
27448 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27449 +               DWC_WARN("Wrong valaue for tx_thr_length\n");
27450 +               DWC_WARN("tx_thr_length must be 8 - 128\n");
27451 +               return -DWC_E_INVALID;
27452 +       }
27453 +
27454 +       core_if->core_params->tx_thr_length = val;
27455 +       return 0;
27456 +}
27457 +
27458 +int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if)
27459 +{
27460 +       return core_if->core_params->tx_thr_length;
27461 +}
27462 +
27463 +int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27464 +{
27465 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27466 +               DWC_WARN("Wrong valaue for rx_thr_length\n");
27467 +               DWC_WARN("rx_thr_length must be 8 - 128\n");
27468 +               return -DWC_E_INVALID;
27469 +       }
27470 +
27471 +       core_if->core_params->rx_thr_length = val;
27472 +       return 0;
27473 +}
27474 +
27475 +int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if)
27476 +{
27477 +       return core_if->core_params->rx_thr_length;
27478 +}
27479 +
27480 +int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val)
27481 +{
27482 +       if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
27483 +           DWC_OTG_PARAM_TEST(val, 4, 4) &&
27484 +           DWC_OTG_PARAM_TEST(val, 8, 8) &&
27485 +           DWC_OTG_PARAM_TEST(val, 16, 16) &&
27486 +           DWC_OTG_PARAM_TEST(val, 32, 32) &&
27487 +           DWC_OTG_PARAM_TEST(val, 64, 64) &&
27488 +           DWC_OTG_PARAM_TEST(val, 128, 128) &&
27489 +           DWC_OTG_PARAM_TEST(val, 256, 256)) {
27490 +               DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val);
27491 +               return -DWC_E_INVALID;
27492 +       }
27493 +       core_if->core_params->dma_burst_size = val;
27494 +       return 0;
27495 +}
27496 +
27497 +int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if)
27498 +{
27499 +       return core_if->core_params->dma_burst_size;
27500 +}
27501 +
27502 +int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val)
27503 +{
27504 +       int retval = 0;
27505 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27506 +               DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val);
27507 +               return -DWC_E_INVALID;
27508 +       }
27509 +       if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
27510 +               if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
27511 +                       DWC_ERROR
27512 +                           ("%d invalid for parameter pti_enable. Check HW configuration.\n",
27513 +                            val);
27514 +               }
27515 +               retval = -DWC_E_INVALID;
27516 +               val = 0;
27517 +       }
27518 +       core_if->core_params->pti_enable = val;
27519 +       return retval;
27520 +}
27521 +
27522 +int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if)
27523 +{
27524 +       return core_if->core_params->pti_enable;
27525 +}
27526 +
27527 +int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val)
27528 +{
27529 +       int retval = 0;
27530 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27531 +               DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val);
27532 +               return -DWC_E_INVALID;
27533 +       }
27534 +       if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
27535 +               if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
27536 +                       DWC_ERROR
27537 +                           ("%d invalid for parameter mpi_enable. Check HW configuration.\n",
27538 +                            val);
27539 +               }
27540 +               retval = -DWC_E_INVALID;
27541 +               val = 0;
27542 +       }
27543 +       core_if->core_params->mpi_enable = val;
27544 +       return retval;
27545 +}
27546 +
27547 +int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if)
27548 +{
27549 +       return core_if->core_params->mpi_enable;
27550 +}
27551 +
27552 +int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val)
27553 +{
27554 +       int retval = 0;
27555 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27556 +               DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val);
27557 +               return -DWC_E_INVALID;
27558 +       }
27559 +       if (val && (core_if->hwcfg3.b.adp_supp == 0)) {
27560 +               if (dwc_otg_param_initialized
27561 +                   (core_if->core_params->adp_supp_enable)) {
27562 +                       DWC_ERROR
27563 +                           ("%d invalid for parameter adp_enable. Check HW configuration.\n",
27564 +                            val);
27565 +               }
27566 +               retval = -DWC_E_INVALID;
27567 +               val = 0;
27568 +       }
27569 +       core_if->core_params->adp_supp_enable = val;
27570 +       /*Set OTG version 2.0 in case of enabling ADP*/
27571 +       if (val)
27572 +               dwc_otg_set_param_otg_ver(core_if, 1);
27573 +
27574 +       return retval;
27575 +}
27576 +
27577 +int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if)
27578 +{
27579 +       return core_if->core_params->adp_supp_enable;
27580 +}
27581 +
27582 +int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val)
27583 +{
27584 +       int retval = 0;
27585 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27586 +               DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val);
27587 +               DWC_WARN("ic_usb_cap must be 0 or 1\n");
27588 +               return -DWC_E_INVALID;
27589 +       }
27590 +
27591 +       if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) {
27592 +               if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
27593 +                       DWC_ERROR
27594 +                           ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n",
27595 +                            val);
27596 +               }
27597 +               retval = -DWC_E_INVALID;
27598 +               val = 0;
27599 +       }
27600 +       core_if->core_params->ic_usb_cap = val;
27601 +       return retval;
27602 +}
27603 +
27604 +int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if)
27605 +{
27606 +       return core_if->core_params->ic_usb_cap;
27607 +}
27608 +
27609 +int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val)
27610 +{
27611 +       int retval = 0;
27612 +       int valid = 1;
27613 +
27614 +       if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27615 +               DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val);
27616 +               DWC_WARN("ahb_thr_ratio must be 0 - 3\n");
27617 +               return -DWC_E_INVALID;
27618 +       }
27619 +
27620 +       if (val
27621 +           && (core_if->snpsid < OTG_CORE_REV_2_81a
27622 +               || !dwc_otg_get_param_thr_ctl(core_if))) {
27623 +               valid = 0;
27624 +       } else if (val
27625 +                  && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) <
27626 +                      4)) {
27627 +               valid = 0;
27628 +       }
27629 +       if (valid == 0) {
27630 +               if (dwc_otg_param_initialized
27631 +                   (core_if->core_params->ahb_thr_ratio)) {
27632 +                       DWC_ERROR
27633 +                           ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n",
27634 +                            val);
27635 +               }
27636 +               retval = -DWC_E_INVALID;
27637 +               val = 0;
27638 +       }
27639 +
27640 +       core_if->core_params->ahb_thr_ratio = val;
27641 +       return retval;
27642 +}
27643 +
27644 +int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if)
27645 +{
27646 +       return core_if->core_params->ahb_thr_ratio;
27647 +}
27648 +
27649 +int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val)
27650 +{
27651 +       int retval = 0;
27652 +       int valid = 1;
27653 +       hwcfg4_data_t hwcfg4 = {.d32 = 0 };
27654 +       hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
27655 +
27656 +       if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27657 +               DWC_WARN("`%d' invalid for parameter `power_down'\n", val);
27658 +               DWC_WARN("power_down must be 0 - 2\n");
27659 +               return -DWC_E_INVALID;
27660 +       }
27661 +
27662 +       if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) {
27663 +               valid = 0;
27664 +       }
27665 +       if ((val == 3)
27666 +           && ((core_if->snpsid < OTG_CORE_REV_3_00a)
27667 +               || (hwcfg4.b.xhiber == 0))) {
27668 +               valid = 0;
27669 +       }
27670 +       if (valid == 0) {
27671 +               if (dwc_otg_param_initialized(core_if->core_params->power_down)) {
27672 +                       DWC_ERROR
27673 +                           ("%d invalid for parameter power_down. Check HW configuration.\n",
27674 +                            val);
27675 +               }
27676 +               retval = -DWC_E_INVALID;
27677 +               val = 0;
27678 +       }
27679 +       core_if->core_params->power_down = val;
27680 +       return retval;
27681 +}
27682 +
27683 +int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if)
27684 +{
27685 +       return core_if->core_params->power_down;
27686 +}
27687 +
27688 +int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27689 +{
27690 +       int retval = 0;
27691 +       int valid = 1;
27692 +
27693 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27694 +               DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val);
27695 +               DWC_WARN("reload_ctl must be 0 or 1\n");
27696 +               return -DWC_E_INVALID;
27697 +       }
27698 +
27699 +       if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) {
27700 +               valid = 0;
27701 +       }
27702 +       if (valid == 0) {
27703 +               if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) {
27704 +                       DWC_ERROR("%d invalid for parameter reload_ctl."
27705 +                                 "Check HW configuration.\n", val);
27706 +               }
27707 +               retval = -DWC_E_INVALID;
27708 +               val = 0;
27709 +       }
27710 +       core_if->core_params->reload_ctl = val;
27711 +       return retval;
27712 +}
27713 +
27714 +int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if)
27715 +{
27716 +       return core_if->core_params->reload_ctl;
27717 +}
27718 +
27719 +int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val)
27720 +{
27721 +       int retval = 0;
27722 +       int valid = 1;
27723 +
27724 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27725 +               DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val);
27726 +               DWC_WARN("dev_out_nak must be 0 or 1\n");
27727 +               return -DWC_E_INVALID;
27728 +       }
27729 +
27730 +       if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) ||
27731 +               !(core_if->core_params->dma_desc_enable))) {
27732 +               valid = 0;
27733 +       }
27734 +       if (valid == 0) {
27735 +               if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) {
27736 +                       DWC_ERROR("%d invalid for parameter dev_out_nak."
27737 +                               "Check HW configuration.\n", val);
27738 +               }
27739 +               retval = -DWC_E_INVALID;
27740 +               val = 0;
27741 +       }
27742 +       core_if->core_params->dev_out_nak = val;
27743 +       return retval;
27744 +}
27745 +
27746 +int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if)
27747 +{
27748 +       return core_if->core_params->dev_out_nak;
27749 +}
27750 +
27751 +int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val)
27752 +{
27753 +       int retval = 0;
27754 +       int valid = 1;
27755 +
27756 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27757 +               DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val);
27758 +               DWC_WARN("cont_on_bna must be 0 or 1\n");
27759 +               return -DWC_E_INVALID;
27760 +       }
27761 +
27762 +       if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) ||
27763 +               !(core_if->core_params->dma_desc_enable))) {
27764 +                       valid = 0;
27765 +       }
27766 +       if (valid == 0) {
27767 +               if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) {
27768 +                       DWC_ERROR("%d invalid for parameter cont_on_bna."
27769 +                               "Check HW configuration.\n", val);
27770 +               }
27771 +               retval = -DWC_E_INVALID;
27772 +               val = 0;
27773 +       }
27774 +       core_if->core_params->cont_on_bna = val;
27775 +       return retval;
27776 +}
27777 +
27778 +int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if)
27779 +{
27780 +       return core_if->core_params->cont_on_bna;
27781 +}
27782 +
27783 +int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val)
27784 +{
27785 +       int retval = 0;
27786 +       int valid = 1;
27787 +
27788 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27789 +               DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val);
27790 +               DWC_WARN("ahb_single must be 0 or 1\n");
27791 +               return -DWC_E_INVALID;
27792 +       }
27793 +
27794 +       if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
27795 +                       valid = 0;
27796 +       }
27797 +       if (valid == 0) {
27798 +               if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) {
27799 +                       DWC_ERROR("%d invalid for parameter ahb_single."
27800 +                               "Check HW configuration.\n", val);
27801 +               }
27802 +               retval = -DWC_E_INVALID;
27803 +               val = 0;
27804 +       }
27805 +       core_if->core_params->ahb_single = val;
27806 +       return retval;
27807 +}
27808 +
27809 +int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if)
27810 +{
27811 +       return core_if->core_params->ahb_single;
27812 +}
27813 +
27814 +int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val)
27815 +{
27816 +       int retval = 0;
27817 +
27818 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27819 +               DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val);
27820 +               DWC_WARN
27821 +                   ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n");
27822 +               return -DWC_E_INVALID;
27823 +       }
27824 +
27825 +       core_if->core_params->otg_ver = val;
27826 +       return retval;
27827 +}
27828 +
27829 +int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if)
27830 +{
27831 +       return core_if->core_params->otg_ver;
27832 +}
27833 +
27834 +uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if)
27835 +{
27836 +       gotgctl_data_t otgctl;
27837 +       otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27838 +       return otgctl.b.hstnegscs;
27839 +}
27840 +
27841 +uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if)
27842 +{
27843 +       gotgctl_data_t otgctl;
27844 +       otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27845 +       return otgctl.b.sesreqscs;
27846 +}
27847 +
27848 +void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val)
27849 +{
27850 +       if(core_if->otg_ver == 0) {
27851 +               gotgctl_data_t otgctl;
27852 +               otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27853 +               otgctl.b.hnpreq = val;
27854 +               DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32);
27855 +       } else {
27856 +               core_if->otg_sts = val;
27857 +       }
27858 +}
27859 +
27860 +uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if)
27861 +{
27862 +       return core_if->snpsid;
27863 +}
27864 +
27865 +uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if)
27866 +{
27867 +       gintsts_data_t gintsts;
27868 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
27869 +       return gintsts.b.curmode;
27870 +}
27871 +
27872 +uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if)
27873 +{
27874 +       gusbcfg_data_t usbcfg;
27875 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27876 +       return usbcfg.b.hnpcap;
27877 +}
27878 +
27879 +void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27880 +{
27881 +       gusbcfg_data_t usbcfg;
27882 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27883 +       usbcfg.b.hnpcap = val;
27884 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27885 +}
27886 +
27887 +uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if)
27888 +{
27889 +       gusbcfg_data_t usbcfg;
27890 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27891 +       return usbcfg.b.srpcap;
27892 +}
27893 +
27894 +void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27895 +{
27896 +       gusbcfg_data_t usbcfg;
27897 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27898 +       usbcfg.b.srpcap = val;
27899 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27900 +}
27901 +
27902 +uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if)
27903 +{
27904 +       dcfg_data_t dcfg;
27905 +       /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */
27906 +
27907 +        dcfg.d32 = -1; //GRAYG 
27908 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if);
27909 +        if (NULL == core_if)
27910 +                DWC_ERROR("reg request with NULL core_if\n");
27911 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__,
27912 +                    core_if, core_if->dev_if);
27913 +        if (NULL == core_if->dev_if)
27914 +                DWC_ERROR("reg request with NULL dev_if\n");
27915 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->"
27916 +                    "dev_global_regs(%p)\n", __func__,
27917 +                    core_if, core_if->dev_if,
27918 +                    core_if->dev_if->dev_global_regs);
27919 +        if (NULL == core_if->dev_if->dev_global_regs)
27920 +                DWC_ERROR("reg request with NULL dev_global_regs\n");
27921 +        else {
27922 +                DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->"
27923 +                            "dev_global_regs(%p)->dcfg = %p\n", __func__,
27924 +                            core_if, core_if->dev_if,
27925 +                            core_if->dev_if->dev_global_regs,
27926 +                            &core_if->dev_if->dev_global_regs->dcfg);
27927 +               dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27928 +        }
27929 +       return dcfg.b.devspd;
27930 +}
27931 +
27932 +void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val)
27933 +{
27934 +       dcfg_data_t dcfg;
27935 +       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27936 +       dcfg.b.devspd = val;
27937 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
27938 +}
27939 +
27940 +uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if)
27941 +{
27942 +       hprt0_data_t hprt0;
27943 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27944 +       return hprt0.b.prtconnsts;
27945 +}
27946 +
27947 +uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if)
27948 +{
27949 +       dsts_data_t dsts;
27950 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
27951 +       return dsts.b.enumspd;
27952 +}
27953 +
27954 +uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if)
27955 +{
27956 +       hprt0_data_t hprt0;
27957 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27958 +       return hprt0.b.prtpwr;
27959 +
27960 +}
27961 +
27962 +uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if)
27963 +{
27964 +       return core_if->hibernation_suspend;
27965 +}
27966 +
27967 +void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val)
27968 +{
27969 +       hprt0_data_t hprt0;
27970 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27971 +       hprt0.b.prtpwr = val;
27972 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27973 +}
27974 +
27975 +uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if)
27976 +{
27977 +       hprt0_data_t hprt0;
27978 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27979 +       return hprt0.b.prtsusp;
27980 +
27981 +}
27982 +
27983 +void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val)
27984 +{
27985 +       hprt0_data_t hprt0;
27986 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27987 +       hprt0.b.prtsusp = val;
27988 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27989 +}
27990 +
27991 +uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if)
27992 +{
27993 +       hfir_data_t hfir;
27994 +       hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27995 +       return hfir.b.frint;
27996 +
27997 +}
27998 +
27999 +void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val)
28000 +{
28001 +       hfir_data_t hfir;
28002 +       uint32_t fram_int;
28003 +       fram_int = calc_frame_interval(core_if);
28004 +       hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
28005 +       if (!core_if->core_params->reload_ctl) {
28006 +               DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is"
28007 +                        "not set to 1.\nShould load driver with reload_ctl=1"
28008 +                        " module parameter\n");
28009 +               return;
28010 +       }
28011 +       switch (fram_int) {
28012 +       case 3750:
28013 +               if ((val < 3350) || (val > 4150)) {
28014 +                       DWC_WARN("HFIR interval for HS core and 30 MHz"
28015 +                                "clock freq should be from 3350 to 4150\n");
28016 +                       return;
28017 +               }
28018 +               break;
28019 +       case 30000:
28020 +               if ((val < 26820) || (val > 33180)) {
28021 +                       DWC_WARN("HFIR interval for FS/LS core and 30 MHz"
28022 +                                "clock freq should be from 26820 to 33180\n");
28023 +                       return;
28024 +               }
28025 +               break;
28026 +       case 6000:
28027 +               if ((val < 5360) || (val > 6640)) {
28028 +                       DWC_WARN("HFIR interval for HS core and 48 MHz"
28029 +                                "clock freq should be from 5360 to 6640\n");
28030 +                       return;
28031 +               }
28032 +               break;
28033 +       case 48000:
28034 +               if ((val < 42912) || (val > 53088)) {
28035 +                       DWC_WARN("HFIR interval for FS/LS core and 48 MHz"
28036 +                                "clock freq should be from 42912 to 53088\n");
28037 +                       return;
28038 +               }
28039 +               break;
28040 +       case 7500:
28041 +               if ((val < 6700) || (val > 8300)) {
28042 +                       DWC_WARN("HFIR interval for HS core and 60 MHz"
28043 +                                "clock freq should be from 6700 to 8300\n");
28044 +                       return;
28045 +               }
28046 +               break;
28047 +       case 60000:
28048 +               if ((val < 53640) || (val > 65536)) {
28049 +                       DWC_WARN("HFIR interval for FS/LS core and 60 MHz"
28050 +                                "clock freq should be from 53640 to 65536\n");
28051 +                       return;
28052 +               }
28053 +               break;
28054 +       default:
28055 +               DWC_WARN("Unknown frame interval\n");
28056 +               return;
28057 +               break;
28058 +
28059 +       }
28060 +       hfir.b.frint = val;
28061 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32);
28062 +}
28063 +
28064 +uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if)
28065 +{
28066 +       hcfg_data_t hcfg;
28067 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
28068 +       return hcfg.b.modechtimen;
28069 +
28070 +}
28071 +
28072 +void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val)
28073 +{
28074 +       hcfg_data_t hcfg;
28075 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
28076 +       hcfg.b.modechtimen = val;
28077 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
28078 +}
28079 +
28080 +void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val)
28081 +{
28082 +       hprt0_data_t hprt0;
28083 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
28084 +       hprt0.b.prtres = val;
28085 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
28086 +}
28087 +
28088 +uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if)
28089 +{
28090 +       dctl_data_t dctl;
28091 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
28092 +       return dctl.b.rmtwkupsig;
28093 +}
28094 +
28095 +uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if)
28096 +{
28097 +       glpmcfg_data_t lpmcfg;
28098 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28099 +
28100 +       DWC_ASSERT(!
28101 +                  ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts),
28102 +                  "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n",
28103 +                  core_if->lx_state, lpmcfg.b.prt_sleep_sts);
28104 +
28105 +       return lpmcfg.b.prt_sleep_sts;
28106 +}
28107 +
28108 +uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if)
28109 +{
28110 +       glpmcfg_data_t lpmcfg;
28111 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28112 +       return lpmcfg.b.rem_wkup_en;
28113 +}
28114 +
28115 +uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if)
28116 +{
28117 +       glpmcfg_data_t lpmcfg;
28118 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28119 +       return lpmcfg.b.appl_resp;
28120 +}
28121 +
28122 +void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val)
28123 +{
28124 +       glpmcfg_data_t lpmcfg;
28125 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28126 +       lpmcfg.b.appl_resp = val;
28127 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28128 +}
28129 +
28130 +uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if)
28131 +{
28132 +       glpmcfg_data_t lpmcfg;
28133 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28134 +       return lpmcfg.b.hsic_connect;
28135 +}
28136 +
28137 +void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val)
28138 +{
28139 +       glpmcfg_data_t lpmcfg;
28140 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28141 +       lpmcfg.b.hsic_connect = val;
28142 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28143 +}
28144 +
28145 +uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if)
28146 +{
28147 +       glpmcfg_data_t lpmcfg;
28148 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28149 +       return lpmcfg.b.inv_sel_hsic;
28150 +
28151 +}
28152 +
28153 +void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val)
28154 +{
28155 +       glpmcfg_data_t lpmcfg;
28156 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28157 +       lpmcfg.b.inv_sel_hsic = val;
28158 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28159 +}
28160 +
28161 +uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if)
28162 +{
28163 +       return DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
28164 +}
28165 +
28166 +void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val)
28167 +{
28168 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val);
28169 +}
28170 +
28171 +uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if)
28172 +{
28173 +       return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
28174 +}
28175 +
28176 +void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val)
28177 +{
28178 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val);
28179 +}
28180 +
28181 +uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if)
28182 +{
28183 +       return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
28184 +}
28185 +
28186 +void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
28187 +{
28188 +       DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val);
28189 +}
28190 +
28191 +uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if)
28192 +{
28193 +       return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
28194 +}
28195 +
28196 +void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
28197 +{
28198 +       DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val);
28199 +}
28200 +
28201 +uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if)
28202 +{
28203 +       return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl);
28204 +}
28205 +
28206 +void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val)
28207 +{
28208 +       DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val);
28209 +}
28210 +
28211 +uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if)
28212 +{
28213 +       return DWC_READ_REG32(&core_if->core_global_regs->ggpio);
28214 +}
28215 +
28216 +void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val)
28217 +{
28218 +       DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val);
28219 +}
28220 +
28221 +uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if)
28222 +{
28223 +       return DWC_READ_REG32(core_if->host_if->hprt0);
28224 +
28225 +}
28226 +
28227 +void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val)
28228 +{
28229 +       DWC_WRITE_REG32(core_if->host_if->hprt0, val);
28230 +}
28231 +
28232 +uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if)
28233 +{
28234 +       return DWC_READ_REG32(&core_if->core_global_regs->guid);
28235 +}
28236 +
28237 +void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val)
28238 +{
28239 +       DWC_WRITE_REG32(&core_if->core_global_regs->guid, val);
28240 +}
28241 +
28242 +uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if)
28243 +{
28244 +       return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
28245 +}
28246 +
28247 +uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if)
28248 +{
28249 +       return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103);
28250 +}
28251 +
28252 +/**
28253 + * Start the SRP timer to detect when the SRP does not complete within
28254 + * 6 seconds.
28255 + *
28256 + * @param core_if the pointer to core_if strucure.
28257 + */
28258 +void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if)
28259 +{
28260 +       core_if->srp_timer_started = 1;
28261 +       DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ );
28262 +}
28263 +
28264 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if)
28265 +{
28266 +       uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl);
28267 +       gotgctl_data_t mem;
28268 +       gotgctl_data_t val;
28269 +
28270 +       val.d32 = DWC_READ_REG32(addr);
28271 +       if (val.b.sesreq) {
28272 +               DWC_ERROR("Session Request Already active!\n");
28273 +               return;
28274 +       }
28275 +
28276 +       DWC_INFO("Session Request Initated\n"); //NOTICE
28277 +       mem.d32 = DWC_READ_REG32(addr);
28278 +       mem.b.sesreq = 1;
28279 +       DWC_WRITE_REG32(addr, mem.d32);
28280 +
28281 +       /* Start the SRP timer */
28282 +       dwc_otg_pcd_start_srp_timer(core_if);
28283 +       return;
28284 +}
28285 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h
28286 new file mode 100644
28287 index 0000000..d367cd1
28288 --- /dev/null
28289 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h
28290 @@ -0,0 +1,1464 @@
28291 +/* ==========================================================================
28292 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
28293 + * $Revision: #123 $
28294 + * $Date: 2012/08/10 $
28295 + * $Change: 2047372 $
28296 + *
28297 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
28298 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
28299 + * otherwise expressly agreed to in writing between Synopsys and you.
28300 + *
28301 + * The Software IS NOT an item of Licensed Software or Licensed Product under
28302 + * any End User Software License Agreement or Agreement for Licensed Product
28303 + * with Synopsys or any supplement thereto. You are permitted to use and
28304 + * redistribute this Software in source and binary forms, with or without
28305 + * modification, provided that redistributions of source code must retain this
28306 + * notice. You may not view, use, disclose, copy or distribute this file or
28307 + * any information contained herein except pursuant to this license grant from
28308 + * Synopsys. If you do not agree with this notice, including the disclaimer
28309 + * below, then you are not authorized to use the Software.
28310 + *
28311 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
28312 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28313 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28314 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
28315 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28316 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28317 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28318 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28319 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28320 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28321 + * DAMAGE.
28322 + * ========================================================================== */
28323 +
28324 +#if !defined(__DWC_CIL_H__)
28325 +#define __DWC_CIL_H__
28326 +
28327 +#include "dwc_list.h"
28328 +#include "dwc_otg_dbg.h"
28329 +#include "dwc_otg_regs.h"
28330 +
28331 +#include "dwc_otg_core_if.h"
28332 +#include "dwc_otg_adp.h"
28333 +
28334 +/**
28335 + * @file
28336 + * This file contains the interface to the Core Interface Layer.
28337 + */
28338 +
28339 +#ifdef DWC_UTE_CFI
28340 +
28341 +#define MAX_DMA_DESCS_PER_EP   256
28342 +
28343 +/**
28344 + * Enumeration for the data buffer mode
28345 + */
28346 +typedef enum _data_buffer_mode {
28347 +       BM_STANDARD = 0,        /* data buffer is in normal mode */
28348 +       BM_SG = 1,              /* data buffer uses the scatter/gather mode */
28349 +       BM_CONCAT = 2,          /* data buffer uses the concatenation mode */
28350 +       BM_CIRCULAR = 3,        /* data buffer uses the circular DMA mode */
28351 +       BM_ALIGN = 4            /* data buffer is in buffer alignment mode */
28352 +} data_buffer_mode_e;
28353 +#endif //DWC_UTE_CFI
28354 +
28355 +/** Macros defined for DWC OTG HW Release version */
28356 +
28357 +#define OTG_CORE_REV_2_60a     0x4F54260A
28358 +#define OTG_CORE_REV_2_71a     0x4F54271A
28359 +#define OTG_CORE_REV_2_72a     0x4F54272A
28360 +#define OTG_CORE_REV_2_80a     0x4F54280A
28361 +#define OTG_CORE_REV_2_81a     0x4F54281A
28362 +#define OTG_CORE_REV_2_90a     0x4F54290A
28363 +#define OTG_CORE_REV_2_91a     0x4F54291A
28364 +#define OTG_CORE_REV_2_92a     0x4F54292A
28365 +#define OTG_CORE_REV_2_93a     0x4F54293A
28366 +#define OTG_CORE_REV_2_94a     0x4F54294A
28367 +#define OTG_CORE_REV_3_00a     0x4F54300A
28368 +
28369 +/**
28370 + * Information for each ISOC packet.
28371 + */
28372 +typedef struct iso_pkt_info {
28373 +       uint32_t offset;
28374 +       uint32_t length;
28375 +       int32_t status;
28376 +} iso_pkt_info_t;
28377 +
28378 +/**
28379 + * The <code>dwc_ep</code> structure represents the state of a single
28380 + * endpoint when acting in device mode. It contains the data items
28381 + * needed for an endpoint to be activated and transfer packets.
28382 + */
28383 +typedef struct dwc_ep {
28384 +       /** EP number used for register address lookup */
28385 +       uint8_t num;
28386 +       /** EP direction 0 = OUT */
28387 +       unsigned is_in:1;
28388 +       /** EP active. */
28389 +       unsigned active:1;
28390 +
28391 +       /**
28392 +        * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic 
28393 +        * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/
28394 +       unsigned tx_fifo_num:4;
28395 +       /** EP type: 0 - Control, 1 - ISOC,      2 - BULK,      3 - INTR */
28396 +       unsigned type:2;
28397 +#define DWC_OTG_EP_TYPE_CONTROL           0
28398 +#define DWC_OTG_EP_TYPE_ISOC      1
28399 +#define DWC_OTG_EP_TYPE_BULK      2
28400 +#define DWC_OTG_EP_TYPE_INTR      3
28401 +
28402 +       /** DATA start PID for INTR and BULK EP */
28403 +       unsigned data_pid_start:1;
28404 +       /** Frame (even/odd) for ISOC EP */
28405 +       unsigned even_odd_frame:1;
28406 +       /** Max Packet bytes */
28407 +       unsigned maxpacket:11;
28408 +
28409 +       /** Max Transfer size */
28410 +       uint32_t maxxfer;
28411 +
28412 +       /** @name Transfer state */
28413 +       /** @{ */
28414 +
28415 +       /**
28416 +        * Pointer to the beginning of the transfer buffer -- do not modify
28417 +        * during transfer.
28418 +        */
28419 +
28420 +       dwc_dma_t dma_addr;
28421 +
28422 +       dwc_dma_t dma_desc_addr;
28423 +       dwc_otg_dev_dma_desc_t *desc_addr;
28424 +
28425 +       uint8_t *start_xfer_buff;
28426 +       /** pointer to the transfer buffer */
28427 +       uint8_t *xfer_buff;
28428 +       /** Number of bytes to transfer */
28429 +       unsigned xfer_len:19;
28430 +       /** Number of bytes transferred. */
28431 +       unsigned xfer_count:19;
28432 +       /** Sent ZLP */
28433 +       unsigned sent_zlp:1;
28434 +       /** Total len for control transfer */
28435 +       unsigned total_len:19;
28436 +
28437 +       /** stall clear flag */
28438 +       unsigned stall_clear_flag:1;
28439 +
28440 +       /** SETUP pkt cnt rollover flag for EP0 out*/
28441 +       unsigned stp_rollover;
28442 +
28443 +#ifdef DWC_UTE_CFI
28444 +       /* The buffer mode */
28445 +       data_buffer_mode_e buff_mode;
28446 +
28447 +       /* The chain of DMA descriptors.
28448 +        * MAX_DMA_DESCS_PER_EP will be allocated for each active EP.
28449 +        */
28450 +       dwc_otg_dma_desc_t *descs;
28451 +
28452 +       /* The DMA address of the descriptors chain start */
28453 +       dma_addr_t descs_dma_addr;
28454 +       /** This variable stores the length of the last enqueued request */
28455 +       uint32_t cfi_req_len;
28456 +#endif                         //DWC_UTE_CFI
28457 +
28458 +/** Max DMA Descriptor count for any EP */
28459 +#define MAX_DMA_DESC_CNT 256
28460 +       /** Allocated DMA Desc count */
28461 +       uint32_t desc_cnt;
28462 +       
28463 +       /** bInterval */
28464 +       uint32_t bInterval;
28465 +       /** Next frame num to setup next ISOC transfer */
28466 +       uint32_t frame_num;
28467 +       /** Indicates SOF number overrun in DSTS */
28468 +       uint8_t frm_overrun;
28469 +
28470 +#ifdef DWC_UTE_PER_IO
28471 +       /** Next frame num for which will be setup DMA Desc */
28472 +       uint32_t xiso_frame_num;
28473 +       /** bInterval */
28474 +       uint32_t xiso_bInterval;
28475 +       /** Count of currently active transfers - shall be either 0 or 1 */
28476 +       int xiso_active_xfers;
28477 +       int xiso_queued_xfers;
28478 +#endif
28479 +#ifdef DWC_EN_ISOC
28480 +       /**
28481 +        * Variables specific for ISOC EPs
28482 +        *
28483 +        */
28484 +       /** DMA addresses of ISOC buffers */
28485 +       dwc_dma_t dma_addr0;
28486 +       dwc_dma_t dma_addr1;
28487 +
28488 +       dwc_dma_t iso_dma_desc_addr;
28489 +       dwc_otg_dev_dma_desc_t *iso_desc_addr;
28490 +
28491 +       /** pointer to the transfer buffers */
28492 +       uint8_t *xfer_buff0;
28493 +       uint8_t *xfer_buff1;
28494 +
28495 +       /** number of ISOC Buffer is processing */
28496 +       uint32_t proc_buf_num;
28497 +       /** Interval of ISOC Buffer processing */
28498 +       uint32_t buf_proc_intrvl;
28499 +       /** Data size for regular frame */
28500 +       uint32_t data_per_frame;
28501 +
28502 +       /* todo - pattern data support is to be implemented in the future */
28503 +       /** Data size for pattern frame */
28504 +       uint32_t data_pattern_frame;
28505 +       /** Frame number of pattern data */
28506 +       uint32_t sync_frame;
28507 +
28508 +       /** bInterval */
28509 +       uint32_t bInterval;
28510 +       /** ISO Packet number per frame */
28511 +       uint32_t pkt_per_frm;
28512 +       /** Next frame num for which will be setup DMA Desc */
28513 +       uint32_t next_frame;
28514 +       /** Number of packets per buffer processing */
28515 +       uint32_t pkt_cnt;
28516 +       /** Info for all isoc packets */
28517 +       iso_pkt_info_t *pkt_info;
28518 +       /** current pkt number */
28519 +       uint32_t cur_pkt;
28520 +       /** current pkt number */
28521 +       uint8_t *cur_pkt_addr;
28522 +       /** current pkt number */
28523 +       uint32_t cur_pkt_dma_addr;
28524 +#endif                         /* DWC_EN_ISOC */
28525 +
28526 +/** @} */
28527 +} dwc_ep_t;
28528 +
28529 +/*
28530 + * Reasons for halting a host channel.
28531 + */
28532 +typedef enum dwc_otg_halt_status {
28533 +       DWC_OTG_HC_XFER_NO_HALT_STATUS,
28534 +       DWC_OTG_HC_XFER_COMPLETE,
28535 +       DWC_OTG_HC_XFER_URB_COMPLETE,
28536 +       DWC_OTG_HC_XFER_ACK,
28537 +       DWC_OTG_HC_XFER_NAK,
28538 +       DWC_OTG_HC_XFER_NYET,
28539 +       DWC_OTG_HC_XFER_STALL,
28540 +       DWC_OTG_HC_XFER_XACT_ERR,
28541 +       DWC_OTG_HC_XFER_FRAME_OVERRUN,
28542 +       DWC_OTG_HC_XFER_BABBLE_ERR,
28543 +       DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,
28544 +       DWC_OTG_HC_XFER_AHB_ERR,
28545 +       DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
28546 +       DWC_OTG_HC_XFER_URB_DEQUEUE
28547 +} dwc_otg_halt_status_e;
28548 +
28549 +/**
28550 + * Host channel descriptor. This structure represents the state of a single
28551 + * host channel when acting in host mode. It contains the data items needed to
28552 + * transfer packets to an endpoint via a host channel.
28553 + */
28554 +typedef struct dwc_hc {
28555 +       /** Host channel number used for register address lookup */
28556 +       uint8_t hc_num;
28557 +
28558 +       /** Device to access */
28559 +       unsigned dev_addr:7;
28560 +
28561 +       /** EP to access */
28562 +       unsigned ep_num:4;
28563 +
28564 +       /** EP direction. 0: OUT, 1: IN */
28565 +       unsigned ep_is_in:1;
28566 +
28567 +       /**
28568 +        * EP speed.
28569 +        * One of the following values:
28570 +        *      - DWC_OTG_EP_SPEED_LOW
28571 +        *      - DWC_OTG_EP_SPEED_FULL
28572 +        *      - DWC_OTG_EP_SPEED_HIGH
28573 +        */
28574 +       unsigned speed:2;
28575 +#define DWC_OTG_EP_SPEED_LOW   0
28576 +#define DWC_OTG_EP_SPEED_FULL  1
28577 +#define DWC_OTG_EP_SPEED_HIGH  2
28578 +
28579 +       /**
28580 +        * Endpoint type.
28581 +        * One of the following values:
28582 +        *      - DWC_OTG_EP_TYPE_CONTROL: 0
28583 +        *      - DWC_OTG_EP_TYPE_ISOC: 1
28584 +        *      - DWC_OTG_EP_TYPE_BULK: 2
28585 +        *      - DWC_OTG_EP_TYPE_INTR: 3
28586 +        */
28587 +       unsigned ep_type:2;
28588 +
28589 +       /** Max packet size in bytes */
28590 +       unsigned max_packet:11;
28591 +
28592 +       /**
28593 +        * PID for initial transaction.
28594 +        * 0: DATA0,<br>
28595 +        * 1: DATA2,<br>
28596 +        * 2: DATA1,<br>
28597 +        * 3: MDATA (non-Control EP),
28598 +        *        SETUP (Control EP)
28599 +        */
28600 +       unsigned data_pid_start:2;
28601 +#define DWC_OTG_HC_PID_DATA0 0
28602 +#define DWC_OTG_HC_PID_DATA2 1
28603 +#define DWC_OTG_HC_PID_DATA1 2
28604 +#define DWC_OTG_HC_PID_MDATA 3
28605 +#define DWC_OTG_HC_PID_SETUP 3
28606 +
28607 +       /** Number of periodic transactions per (micro)frame */
28608 +       unsigned multi_count:2;
28609 +
28610 +       /** @name Transfer State */
28611 +       /** @{ */
28612 +
28613 +       /** Pointer to the current transfer buffer position. */
28614 +       uint8_t *xfer_buff;
28615 +       /**
28616 +        * In Buffer DMA mode this buffer will be used
28617 +        * if xfer_buff is not DWORD aligned.
28618 +        */
28619 +       dwc_dma_t align_buff;
28620 +       /** Total number of bytes to transfer. */
28621 +       uint32_t xfer_len;
28622 +       /** Number of bytes transferred so far. */
28623 +       uint32_t xfer_count;
28624 +       /** Packet count at start of transfer.*/
28625 +       uint16_t start_pkt_count;
28626 +
28627 +       /**
28628 +        * Flag to indicate whether the transfer has been started. Set to 1 if
28629 +        * it has been started, 0 otherwise.
28630 +        */
28631 +       uint8_t xfer_started;
28632 +
28633 +       /**
28634 +        * Set to 1 to indicate that a PING request should be issued on this
28635 +        * channel. If 0, process normally.
28636 +        */
28637 +       uint8_t do_ping;
28638 +
28639 +       /**
28640 +        * Set to 1 to indicate that the error count for this transaction is
28641 +        * non-zero. Set to 0 if the error count is 0.
28642 +        */
28643 +       uint8_t error_state;
28644 +
28645 +       /**
28646 +        * Set to 1 to indicate that this channel should be halted the next
28647 +        * time a request is queued for the channel. This is necessary in
28648 +        * slave mode if no request queue space is available when an attempt
28649 +        * is made to halt the channel.
28650 +        */
28651 +       uint8_t halt_on_queue;
28652 +
28653 +       /**
28654 +        * Set to 1 if the host channel has been halted, but the core is not
28655 +        * finished flushing queued requests. Otherwise 0.
28656 +        */
28657 +       uint8_t halt_pending;
28658 +
28659 +       /**
28660 +        * Reason for halting the host channel.
28661 +        */
28662 +       dwc_otg_halt_status_e halt_status;
28663 +
28664 +       /*
28665 +        * Split settings for the host channel
28666 +        */
28667 +       uint8_t do_split;                  /**< Enable split for the channel */
28668 +       uint8_t complete_split;    /**< Enable complete split */
28669 +       uint8_t hub_addr;                  /**< Address of high speed hub */
28670 +
28671 +       uint8_t port_addr;                 /**< Port of the low/full speed device */
28672 +       /** Split transaction position
28673 +        * One of the following values:
28674 +        *        - DWC_HCSPLIT_XACTPOS_MID
28675 +        *        - DWC_HCSPLIT_XACTPOS_BEGIN
28676 +        *        - DWC_HCSPLIT_XACTPOS_END
28677 +        *        - DWC_HCSPLIT_XACTPOS_ALL */
28678 +       uint8_t xact_pos;
28679 +
28680 +       /** Set when the host channel does a short read. */
28681 +       uint8_t short_read;
28682 +
28683 +       /**
28684 +        * Number of requests issued for this channel since it was assigned to
28685 +        * the current transfer (not counting PINGs).
28686 +        */
28687 +       uint8_t requests;
28688 +
28689 +       /**
28690 +        * Queue Head for the transfer being processed by this channel.
28691 +        */
28692 +       struct dwc_otg_qh *qh;
28693 +
28694 +       /** @} */
28695 +
28696 +       /** Entry in list of host channels. */
28697 +        DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry;
28698 +
28699 +       /** @name Descriptor DMA support */
28700 +       /** @{ */
28701 +
28702 +       /** Number of Transfer Descriptors */
28703 +       uint16_t ntd;
28704 +
28705 +       /** Descriptor List DMA address */
28706 +       dwc_dma_t desc_list_addr;
28707 +
28708 +       /** Scheduling micro-frame bitmap. */
28709 +       uint8_t schinfo;
28710 +
28711 +       /** @} */
28712 +} dwc_hc_t;
28713 +
28714 +/**
28715 + * The following parameters may be specified when starting the module. These
28716 + * parameters define how the DWC_otg controller should be configured.
28717 + */
28718 +typedef struct dwc_otg_core_params {
28719 +       int32_t opt;
28720 +
28721 +       /**
28722 +        * Specifies the OTG capabilities. The driver will automatically
28723 +        * detect the value for this parameter if none is specified.
28724 +        * 0 - HNP and SRP capable (default)
28725 +        * 1 - SRP Only capable
28726 +        * 2 - No HNP/SRP capable
28727 +        */
28728 +       int32_t otg_cap;
28729 +
28730 +       /**
28731 +        * Specifies whether to use slave or DMA mode for accessing the data
28732 +        * FIFOs. The driver will automatically detect the value for this
28733 +        * parameter if none is specified.
28734 +        * 0 - Slave
28735 +        * 1 - DMA (default, if available)
28736 +        */
28737 +       int32_t dma_enable;
28738 +
28739 +       /**
28740 +        * When DMA mode is enabled specifies whether to use address DMA or DMA 
28741 +        * Descriptor mode for accessing the data FIFOs in device mode. The driver 
28742 +        * will automatically detect the value for this if none is specified.
28743 +        * 0 - address DMA
28744 +        * 1 - DMA Descriptor(default, if available)
28745 +        */
28746 +       int32_t dma_desc_enable;
28747 +       /** The DMA Burst size (applicable only for External DMA
28748 +        * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
28749 +        */
28750 +       int32_t dma_burst_size; /* Translate this to GAHBCFG values */
28751 +
28752 +       /**
28753 +        * Specifies the maximum speed of operation in host and device mode.
28754 +        * The actual speed depends on the speed of the attached device and
28755 +        * the value of phy_type. The actual speed depends on the speed of the
28756 +        * attached device.
28757 +        * 0 - High Speed (default)
28758 +        * 1 - Full Speed
28759 +        */
28760 +       int32_t speed;
28761 +       /** Specifies whether low power mode is supported when attached
28762 +        *      to a Full Speed or Low Speed device in host mode.
28763 +        * 0 - Don't support low power mode (default)
28764 +        * 1 - Support low power mode
28765 +        */
28766 +       int32_t host_support_fs_ls_low_power;
28767 +
28768 +       /** Specifies the PHY clock rate in low power mode when connected to a
28769 +        * Low Speed device in host mode. This parameter is applicable only if
28770 +        * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
28771 +        * then defaults to 6 MHZ otherwise 48 MHZ.
28772 +        *
28773 +        * 0 - 48 MHz
28774 +        * 1 - 6 MHz
28775 +        */
28776 +       int32_t host_ls_low_power_phy_clk;
28777 +
28778 +       /**
28779 +        * 0 - Use cC FIFO size parameters
28780 +        * 1 - Allow dynamic FIFO sizing (default)
28781 +        */
28782 +       int32_t enable_dynamic_fifo;
28783 +
28784 +       /** Total number of 4-byte words in the data FIFO memory. This
28785 +        * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
28786 +        * Tx FIFOs.
28787 +        * 32 to 32768 (default 8192)
28788 +        * Note: The total FIFO memory depth in the FPGA configuration is 8192.
28789 +        */
28790 +       int32_t data_fifo_size;
28791 +
28792 +       /** Number of 4-byte words in the Rx FIFO in device mode when dynamic
28793 +        * FIFO sizing is enabled.
28794 +        * 16 to 32768 (default 1064)
28795 +        */
28796 +       int32_t dev_rx_fifo_size;
28797 +
28798 +       /** Number of 4-byte words in the non-periodic Tx FIFO in device mode
28799 +        * when dynamic FIFO sizing is enabled.
28800 +        * 16 to 32768 (default 1024)
28801 +        */
28802 +       int32_t dev_nperio_tx_fifo_size;
28803 +
28804 +       /** Number of 4-byte words in each of the periodic Tx FIFOs in device
28805 +        * mode when dynamic FIFO sizing is enabled.
28806 +        * 4 to 768 (default 256)
28807 +        */
28808 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
28809 +
28810 +       /** Number of 4-byte words in the Rx FIFO in host mode when dynamic
28811 +        * FIFO sizing is enabled.
28812 +        * 16 to 32768 (default 1024)
28813 +        */
28814 +       int32_t host_rx_fifo_size;
28815 +
28816 +       /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
28817 +        * when Dynamic FIFO sizing is enabled in the core.
28818 +        * 16 to 32768 (default 1024)
28819 +        */
28820 +       int32_t host_nperio_tx_fifo_size;
28821 +
28822 +       /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
28823 +        * FIFO sizing is enabled.
28824 +        * 16 to 32768 (default 1024)
28825 +        */
28826 +       int32_t host_perio_tx_fifo_size;
28827 +
28828 +       /** The maximum transfer size supported in bytes.
28829 +        * 2047 to 65,535  (default 65,535)
28830 +        */
28831 +       int32_t max_transfer_size;
28832 +
28833 +       /** The maximum number of packets in a transfer.
28834 +        * 15 to 511  (default 511)
28835 +        */
28836 +       int32_t max_packet_count;
28837 +
28838 +       /** The number of host channel registers to use.
28839 +        * 1 to 16 (default 12)
28840 +        * Note: The FPGA configuration supports a maximum of 12 host channels.
28841 +        */
28842 +       int32_t host_channels;
28843 +
28844 +       /** The number of endpoints in addition to EP0 available for device
28845 +        * mode operations.
28846 +        * 1 to 15 (default 6 IN and OUT)
28847 +        * Note: The FPGA configuration supports a maximum of 6 IN and OUT
28848 +        * endpoints in addition to EP0.
28849 +        */
28850 +       int32_t dev_endpoints;
28851 +
28852 +               /**
28853 +                * Specifies the type of PHY interface to use. By default, the driver
28854 +                * will automatically detect the phy_type.
28855 +                *
28856 +                * 0 - Full Speed PHY
28857 +                * 1 - UTMI+ (default)
28858 +                * 2 - ULPI
28859 +                */
28860 +       int32_t phy_type;
28861 +
28862 +       /**
28863 +        * Specifies the UTMI+ Data Width. This parameter is
28864 +        * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
28865 +        * PHY_TYPE, this parameter indicates the data width between
28866 +        * the MAC and the ULPI Wrapper.) Also, this parameter is
28867 +        * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
28868 +        * to "8 and 16 bits", meaning that the core has been
28869 +        * configured to work at either data path width.
28870 +        *
28871 +        * 8 or 16 bits (default 16)
28872 +        */
28873 +       int32_t phy_utmi_width;
28874 +
28875 +       /**
28876 +        * Specifies whether the ULPI operates at double or single
28877 +        * data rate. This parameter is only applicable if PHY_TYPE is
28878 +        * ULPI.
28879 +        *
28880 +        * 0 - single data rate ULPI interface with 8 bit wide data
28881 +        * bus (default)
28882 +        * 1 - double data rate ULPI interface with 4 bit wide data
28883 +        * bus
28884 +        */
28885 +       int32_t phy_ulpi_ddr;
28886 +
28887 +       /**
28888 +        * Specifies whether to use the internal or external supply to
28889 +        * drive the vbus with a ULPI phy.
28890 +        */
28891 +       int32_t phy_ulpi_ext_vbus;
28892 +
28893 +       /**
28894 +        * Specifies whether to use the I2Cinterface for full speed PHY. This
28895 +        * parameter is only applicable if PHY_TYPE is FS.
28896 +        * 0 - No (default)
28897 +        * 1 - Yes
28898 +        */
28899 +       int32_t i2c_enable;
28900 +
28901 +       int32_t ulpi_fs_ls;
28902 +
28903 +       int32_t ts_dline;
28904 +
28905 +       /**
28906 +        * Specifies whether dedicated transmit FIFOs are
28907 +        * enabled for non periodic IN endpoints in device mode
28908 +        * 0 - No
28909 +        * 1 - Yes
28910 +        */
28911 +       int32_t en_multiple_tx_fifo;
28912 +
28913 +       /** Number of 4-byte words in each of the Tx FIFOs in device
28914 +        * mode when dynamic FIFO sizing is enabled.
28915 +        * 4 to 768 (default 256)
28916 +        */
28917 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
28918 +
28919 +       /** Thresholding enable flag-
28920 +        * bit 0 - enable non-ISO Tx thresholding
28921 +        * bit 1 - enable ISO Tx thresholding
28922 +        * bit 2 - enable Rx thresholding
28923 +        */
28924 +       uint32_t thr_ctl;
28925 +
28926 +       /** Thresholding length for Tx
28927 +        *      FIFOs in 32 bit DWORDs
28928 +        */
28929 +       uint32_t tx_thr_length;
28930 +
28931 +       /** Thresholding length for Rx
28932 +        *      FIFOs in 32 bit DWORDs
28933 +        */
28934 +       uint32_t rx_thr_length;
28935 +
28936 +       /**
28937 +        * Specifies whether LPM (Link Power Management) support is enabled
28938 +        */
28939 +       int32_t lpm_enable;
28940 +
28941 +       /** Per Transfer Interrupt
28942 +        *      mode enable flag
28943 +        * 1 - Enabled
28944 +        * 0 - Disabled
28945 +        */
28946 +       int32_t pti_enable;
28947 +
28948 +       /** Multi Processor Interrupt
28949 +        *      mode enable flag
28950 +        * 1 - Enabled
28951 +        * 0 - Disabled
28952 +        */
28953 +       int32_t mpi_enable;
28954 +
28955 +       /** IS_USB Capability
28956 +        * 1 - Enabled
28957 +        * 0 - Disabled
28958 +        */
28959 +       int32_t ic_usb_cap;
28960 +
28961 +       /** AHB Threshold Ratio
28962 +        * 2'b00 AHB Threshold =        MAC Threshold
28963 +        * 2'b01 AHB Threshold = 1/2    MAC Threshold
28964 +        * 2'b10 AHB Threshold = 1/4    MAC Threshold
28965 +        * 2'b11 AHB Threshold = 1/8    MAC Threshold
28966 +        */
28967 +       int32_t ahb_thr_ratio;
28968 +
28969 +       /** ADP Support
28970 +        * 1 - Enabled
28971 +        * 0 - Disabled
28972 +        */
28973 +       int32_t adp_supp_enable;
28974 +
28975 +       /** HFIR Reload Control
28976 +        * 0 - The HFIR cannot be reloaded dynamically.
28977 +        * 1 - Allow dynamic reloading of the HFIR register during runtime.
28978 +        */
28979 +       int32_t reload_ctl;
28980 +
28981 +       /** DCFG: Enable device Out NAK 
28982 +        * 0 - The core does not set NAK after Bulk Out transfer complete.
28983 +        * 1 - The core sets NAK after Bulk OUT transfer complete.
28984 +        */
28985 +       int32_t dev_out_nak;
28986 +
28987 +       /** DCFG: Enable Continue on BNA 
28988 +        * After receiving BNA interrupt the core disables the endpoint,when the
28989 +        * endpoint is re-enabled by the application the core starts processing 
28990 +        * 0 - from the DOEPDMA descriptor
28991 +        * 1 - from the descriptor which received the BNA.
28992 +        */
28993 +       int32_t cont_on_bna;
28994 +
28995 +       /** GAHBCFG: AHB Single Support 
28996 +        * This bit when programmed supports SINGLE transfers for remainder 
28997 +        * data in a transfer for DMA mode of operation.
28998 +        * 0 - in this case the remainder data will be sent using INCR burst size.
28999 +        * 1 - in this case the remainder data will be sent using SINGLE burst size.
29000 +        */
29001 +       int32_t ahb_single;
29002 +
29003 +       /** Core Power down mode
29004 +        * 0 - No Power Down is enabled
29005 +        * 1 - Reserved
29006 +        * 2 - Complete Power Down (Hibernation)
29007 +        */
29008 +       int32_t power_down;
29009 +
29010 +       /** OTG revision supported
29011 +        * 0 - OTG 1.3 revision
29012 +        * 1 - OTG 2.0 revision
29013 +        */
29014 +       int32_t otg_ver;
29015 +
29016 +} dwc_otg_core_params_t;
29017 +
29018 +#ifdef DEBUG
29019 +struct dwc_otg_core_if;
29020 +typedef struct hc_xfer_info {
29021 +       struct dwc_otg_core_if *core_if;
29022 +       dwc_hc_t *hc;
29023 +} hc_xfer_info_t;
29024 +#endif
29025 +
29026 +typedef struct ep_xfer_info {
29027 +       struct dwc_otg_core_if *core_if;
29028 +       dwc_ep_t *ep;
29029 +       uint8_t state;
29030 +} ep_xfer_info_t;
29031 +/*
29032 + * Device States
29033 + */
29034 +typedef enum dwc_otg_lx_state {
29035 +       /** On state */
29036 +       DWC_OTG_L0,
29037 +       /** LPM sleep state*/
29038 +       DWC_OTG_L1,
29039 +       /** USB suspend state*/
29040 +       DWC_OTG_L2,
29041 +       /** Off state*/
29042 +       DWC_OTG_L3
29043 +} dwc_otg_lx_state_e;
29044 +
29045 +struct dwc_otg_global_regs_backup {
29046 +       uint32_t gotgctl_local;
29047 +       uint32_t gintmsk_local;
29048 +       uint32_t gahbcfg_local;
29049 +       uint32_t gusbcfg_local;
29050 +       uint32_t grxfsiz_local;
29051 +       uint32_t gnptxfsiz_local;
29052 +#ifdef CONFIG_USB_DWC_OTG_LPM
29053 +       uint32_t glpmcfg_local;
29054 +#endif
29055 +       uint32_t gi2cctl_local;
29056 +       uint32_t hptxfsiz_local;
29057 +       uint32_t pcgcctl_local;
29058 +       uint32_t gdfifocfg_local;
29059 +       uint32_t dtxfsiz_local[MAX_EPS_CHANNELS];
29060 +       uint32_t gpwrdn_local;
29061 +       uint32_t xhib_pcgcctl;
29062 +       uint32_t xhib_gpwrdn;
29063 +};
29064 +
29065 +struct dwc_otg_host_regs_backup {
29066 +       uint32_t hcfg_local;
29067 +       uint32_t haintmsk_local;
29068 +       uint32_t hcintmsk_local[MAX_EPS_CHANNELS];
29069 +       uint32_t hprt0_local;
29070 +       uint32_t hfir_local;
29071 +};
29072 +
29073 +struct dwc_otg_dev_regs_backup {
29074 +       uint32_t dcfg;
29075 +       uint32_t dctl;
29076 +       uint32_t daintmsk;
29077 +       uint32_t diepmsk;
29078 +       uint32_t doepmsk;
29079 +       uint32_t diepctl[MAX_EPS_CHANNELS];
29080 +       uint32_t dieptsiz[MAX_EPS_CHANNELS];
29081 +       uint32_t diepdma[MAX_EPS_CHANNELS];
29082 +};
29083 +/**
29084 + * The <code>dwc_otg_core_if</code> structure contains information needed to manage
29085 + * the DWC_otg controller acting in either host or device mode. It
29086 + * represents the programming view of the controller as a whole.
29087 + */
29088 +struct dwc_otg_core_if {
29089 +       /** Parameters that define how the core should be configured.*/
29090 +       dwc_otg_core_params_t *core_params;
29091 +
29092 +       /** Core Global registers starting at offset 000h. */
29093 +       dwc_otg_core_global_regs_t *core_global_regs;
29094 +
29095 +       /** Device-specific information */
29096 +       dwc_otg_dev_if_t *dev_if;
29097 +       /** Host-specific information */
29098 +       dwc_otg_host_if_t *host_if;
29099 +
29100 +       /** Value from SNPSID register */
29101 +       uint32_t snpsid;
29102 +
29103 +       /*
29104 +        * Set to 1 if the core PHY interface bits in USBCFG have been
29105 +        * initialized.
29106 +        */
29107 +       uint8_t phy_init_done;
29108 +
29109 +       /*
29110 +        * SRP Success flag, set by srp success interrupt in FS I2C mode
29111 +        */
29112 +       uint8_t srp_success;
29113 +       uint8_t srp_timer_started;
29114 +       /** Timer for SRP. If it expires before SRP is successful
29115 +        * clear the SRP. */
29116 +       dwc_timer_t *srp_timer;
29117 +
29118 +#ifdef DWC_DEV_SRPCAP
29119 +       /* This timer is needed to power on the hibernated host core if SRP is not
29120 +        * initiated on connected SRP capable device for limited period of time
29121 +        */
29122 +       uint8_t pwron_timer_started;
29123 +       dwc_timer_t *pwron_timer;
29124 +#endif
29125 +       /* Common configuration information */
29126 +       /** Power and Clock Gating Control Register */
29127 +       volatile uint32_t *pcgcctl;
29128 +#define DWC_OTG_PCGCCTL_OFFSET 0xE00
29129 +
29130 +       /** Push/pop addresses for endpoints or host channels.*/
29131 +       uint32_t *data_fifo[MAX_EPS_CHANNELS];
29132 +#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
29133 +#define DWC_OTG_DATA_FIFO_SIZE 0x1000
29134 +
29135 +       /** Total RAM for FIFOs (Bytes) */
29136 +       uint16_t total_fifo_size;
29137 +       /** Size of Rx FIFO (Bytes) */
29138 +       uint16_t rx_fifo_size;
29139 +       /** Size of Non-periodic Tx FIFO (Bytes) */
29140 +       uint16_t nperio_tx_fifo_size;
29141 +
29142 +       /** 1 if DMA is enabled, 0 otherwise. */
29143 +       uint8_t dma_enable;
29144 +
29145 +       /** 1 if DMA descriptor is enabled, 0 otherwise. */
29146 +       uint8_t dma_desc_enable;
29147 +
29148 +       /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
29149 +       uint8_t pti_enh_enable;
29150 +
29151 +       /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
29152 +       uint8_t multiproc_int_enable;
29153 +
29154 +       /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
29155 +       uint8_t en_multiple_tx_fifo;
29156 +
29157 +       /** Set to 1 if multiple packets of a high-bandwidth transfer is in
29158 +        * process of being queued */
29159 +       uint8_t queuing_high_bandwidth;
29160 +
29161 +       /** Hardware Configuration -- stored here for convenience.*/
29162 +       hwcfg1_data_t hwcfg1;
29163 +       hwcfg2_data_t hwcfg2;
29164 +       hwcfg3_data_t hwcfg3;
29165 +       hwcfg4_data_t hwcfg4;
29166 +       fifosize_data_t hptxfsiz;
29167 +
29168 +       /** Host and Device Configuration -- stored here for convenience.*/
29169 +       hcfg_data_t hcfg;
29170 +       dcfg_data_t dcfg;
29171 +
29172 +       /** The operational State, during transations
29173 +        * (a_host>>a_peripherial and b_device=>b_host) this may not
29174 +        * match the core but allows the software to determine
29175 +        * transitions.
29176 +        */
29177 +       uint8_t op_state;
29178 +
29179 +       /**
29180 +        * Set to 1 if the HCD needs to be restarted on a session request
29181 +        * interrupt. This is required if no connector ID status change has
29182 +        * occurred since the HCD was last disconnected.
29183 +        */
29184 +       uint8_t restart_hcd_on_session_req;
29185 +
29186 +       /** HCD callbacks */
29187 +       /** A-Device is a_host */
29188 +#define A_HOST         (1)
29189 +       /** A-Device is a_suspend */
29190 +#define A_SUSPEND      (2)
29191 +       /** A-Device is a_peripherial */
29192 +#define A_PERIPHERAL   (3)
29193 +       /** B-Device is operating as a Peripheral. */
29194 +#define B_PERIPHERAL   (4)
29195 +       /** B-Device is operating as a Host. */
29196 +#define B_HOST         (5)
29197 +
29198 +       /** HCD callbacks */
29199 +       struct dwc_otg_cil_callbacks *hcd_cb;
29200 +       /** PCD callbacks */
29201 +       struct dwc_otg_cil_callbacks *pcd_cb;
29202 +
29203 +       /** Device mode Periodic Tx FIFO Mask */
29204 +       uint32_t p_tx_msk;
29205 +       /** Device mode Periodic Tx FIFO Mask */
29206 +       uint32_t tx_msk;
29207 +
29208 +       /** Workqueue object used for handling several interrupts */
29209 +       dwc_workq_t *wq_otg;
29210 +
29211 +       /** Timer object used for handling "Wakeup Detected" Interrupt */
29212 +       dwc_timer_t *wkp_timer;
29213 +       /** This arrays used for debug purposes for DEV OUT NAK enhancement */
29214 +       uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS];
29215 +       ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS];
29216 +       dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS];
29217 +#ifdef DEBUG
29218 +       uint32_t start_hcchar_val[MAX_EPS_CHANNELS];
29219 +
29220 +       hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS];
29221 +       dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS];
29222 +
29223 +       uint32_t hfnum_7_samples;
29224 +       uint64_t hfnum_7_frrem_accum;
29225 +       uint32_t hfnum_0_samples;
29226 +       uint64_t hfnum_0_frrem_accum;
29227 +       uint32_t hfnum_other_samples;
29228 +       uint64_t hfnum_other_frrem_accum;
29229 +#endif
29230 +
29231 +#ifdef DWC_UTE_CFI
29232 +       uint16_t pwron_rxfsiz;
29233 +       uint16_t pwron_gnptxfsiz;
29234 +       uint16_t pwron_txfsiz[15];
29235 +
29236 +       uint16_t init_rxfsiz;
29237 +       uint16_t init_gnptxfsiz;
29238 +       uint16_t init_txfsiz[15];
29239 +#endif
29240 +
29241 +       /** Lx state of device */
29242 +       dwc_otg_lx_state_e lx_state;
29243 +
29244 +       /** Saved Core Global registers */
29245 +       struct dwc_otg_global_regs_backup *gr_backup;
29246 +       /** Saved Host registers */
29247 +       struct dwc_otg_host_regs_backup *hr_backup;
29248 +       /** Saved Device registers */
29249 +       struct dwc_otg_dev_regs_backup *dr_backup;
29250 +
29251 +       /** Power Down Enable */
29252 +       uint32_t power_down;
29253 +
29254 +       /** ADP support Enable */
29255 +       uint32_t adp_enable;
29256 +
29257 +       /** ADP structure object */
29258 +       dwc_otg_adp_t adp;
29259 +
29260 +       /** hibernation/suspend flag */
29261 +       int hibernation_suspend;
29262 +
29263 +       /** Device mode extended hibernation flag */
29264 +       int xhib;
29265 +
29266 +       /** OTG revision supported */
29267 +       uint32_t otg_ver;
29268 +
29269 +       /** OTG status flag used for HNP polling */
29270 +       uint8_t otg_sts;
29271 +
29272 +       /** Pointer to either hcd->lock or pcd->lock */
29273 +       dwc_spinlock_t *lock;
29274 +
29275 +       /** Start predict NextEP based on Learning Queue if equal 1,
29276 +        * also used as counter of disabled NP IN EP's */
29277 +       uint8_t start_predict;
29278 +
29279 +       /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and 
29280 +        * active, 0xff otherwise */
29281 +       uint8_t nextep_seq[MAX_EPS_CHANNELS];
29282 +
29283 +       /** Index of fisrt EP in nextep_seq array which should be re-enabled **/
29284 +       uint8_t first_in_nextep_seq;
29285 +
29286 +       /** Frame number while entering to ISR - needed for ISOCs **/
29287 +       uint32_t frame_num; 
29288 +
29289 +};
29290 +
29291 +#ifdef DEBUG
29292 +/*
29293 + * This function is called when transfer is timed out.
29294 + */
29295 +extern void hc_xfer_timeout(void *ptr);
29296 +#endif
29297 +
29298 +/*
29299 + * This function is called when transfer is timed out on endpoint.
29300 + */
29301 +extern void ep_xfer_timeout(void *ptr);
29302 +
29303 +/*
29304 + * The following functions are functions for works
29305 + * using during handling some interrupts
29306 + */
29307 +extern void w_conn_id_status_change(void *p);
29308 +
29309 +extern void w_wakeup_detected(void *p);
29310 +
29311 +/** Saves global register values into system memory. */
29312 +extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if);
29313 +/** Saves device register values into system memory. */
29314 +extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if);
29315 +/** Saves host register values into system memory. */
29316 +extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if);
29317 +/** Restore global register values. */
29318 +extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if);
29319 +/** Restore host register values. */
29320 +extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset);
29321 +/** Restore device register values. */
29322 +extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if,
29323 +                                   int rem_wakeup);
29324 +extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if);
29325 +extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode,
29326 +                                 int is_host);
29327 +
29328 +extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
29329 +                                           int restore_mode, int reset);
29330 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
29331 +                                             int rem_wakeup, int reset);
29332 +
29333 +/*
29334 + * The following functions support initialization of the CIL driver component
29335 + * and the DWC_otg controller.
29336 + */
29337 +extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if);
29338 +extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);
29339 +
29340 +/** @name Device CIL Functions
29341 + * The following functions support managing the DWC_otg controller in device
29342 + * mode.
29343 + */
29344 +/**@{*/
29345 +extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if);
29346 +extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,
29347 +                                     uint32_t * _dest);
29348 +extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if);
29349 +extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29350 +extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29351 +extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29352 +extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,
29353 +                                     dwc_ep_t * _ep);
29354 +extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,
29355 +                                        dwc_ep_t * _ep);
29356 +extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,
29357 +                                      dwc_ep_t * _ep);
29358 +extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,
29359 +                                         dwc_ep_t * _ep);
29360 +extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,
29361 +                                   dwc_ep_t * _ep, int _dma);
29362 +extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29363 +extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,
29364 +                                  dwc_ep_t * _ep);
29365 +extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);
29366 +
29367 +#ifdef DWC_EN_ISOC
29368 +extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
29369 +                                             dwc_ep_t * ep);
29370 +extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
29371 +                                             dwc_ep_t * ep);
29372 +#endif /* DWC_EN_ISOC */
29373 +/**@}*/
29374 +
29375 +/** @name Host CIL Functions
29376 + * The following functions support managing the DWC_otg controller in host
29377 + * mode.
29378 + */
29379 +/**@{*/
29380 +extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29381 +extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if,
29382 +                           dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status);
29383 +extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29384 +extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if,
29385 +                                     dwc_hc_t * _hc);
29386 +extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if,
29387 +                                       dwc_hc_t * _hc);
29388 +extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29389 +extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if,
29390 +                                   dwc_hc_t * _hc);
29391 +extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if);
29392 +extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if);
29393 +
29394 +extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if,
29395 +                                          dwc_hc_t * hc);
29396 +
29397 +extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if);
29398 +
29399 +/* Macro used to clear one channel interrupt */
29400 +#define clear_hc_int(_hc_regs_, _intr_) \
29401 +do { \
29402 +       hcint_data_t hcint_clear = {.d32 = 0}; \
29403 +       hcint_clear.b._intr_ = 1; \
29404 +       DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \
29405 +} while (0)
29406 +
29407 +/*
29408 + * Macro used to disable one channel interrupt. Channel interrupts are
29409 + * disabled when the channel is halted or released by the interrupt handler.
29410 + * There is no need to handle further interrupts of that type until the
29411 + * channel is re-assigned. In fact, subsequent handling may cause crashes
29412 + * because the channel structures are cleaned up when the channel is released.
29413 + */
29414 +#define disable_hc_int(_hc_regs_, _intr_) \
29415 +do { \
29416 +       hcintmsk_data_t hcintmsk = {.d32 = 0}; \
29417 +       hcintmsk.b._intr_ = 1; \
29418 +       DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \
29419 +} while (0)
29420 +
29421 +/**
29422 + * This function Reads HPRT0 in preparation to modify. It keeps the
29423 + * WC bits 0 so that if they are read as 1, they won't clear when you
29424 + * write it back
29425 + */
29426 +static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if)
29427 +{
29428 +       hprt0_data_t hprt0;
29429 +       hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0);
29430 +       hprt0.b.prtena = 0;
29431 +       hprt0.b.prtconndet = 0;
29432 +       hprt0.b.prtenchng = 0;
29433 +       hprt0.b.prtovrcurrchng = 0;
29434 +       return hprt0.d32;
29435 +}
29436 +
29437 +/**@}*/
29438 +
29439 +/** @name Common CIL Functions
29440 + * The following functions support managing the DWC_otg controller in either
29441 + * device or host mode.
29442 + */
29443 +/**@{*/
29444 +
29445 +extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
29446 +                               uint8_t * dest, uint16_t bytes);
29447 +
29448 +extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);
29449 +extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);
29450 +extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);
29451 +
29452 +/**
29453 + * This function returns the Core Interrupt register.
29454 + */
29455 +static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
29456 +{
29457 +       return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &
29458 +               DWC_READ_REG32(&core_if->core_global_regs->gintmsk));
29459 +}
29460 +
29461 +/**
29462 + * This function returns the OTG Interrupt register.
29463 + */
29464 +static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if)
29465 +{
29466 +       return (DWC_READ_REG32(&core_if->core_global_regs->gotgint));
29467 +}
29468 +
29469 +/**
29470 + * This function reads the Device All Endpoints Interrupt register and
29471 + * returns the IN endpoint interrupt bits.
29472 + */
29473 +static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
29474 +                                                      core_if)
29475 +{
29476 +
29477 +       uint32_t v;
29478 +
29479 +       if (core_if->multiproc_int_enable) {
29480 +               v = DWC_READ_REG32(&core_if->dev_if->
29481 +                                  dev_global_regs->deachint) &
29482 +                   DWC_READ_REG32(&core_if->
29483 +                                  dev_if->dev_global_regs->deachintmsk);
29484 +       } else {
29485 +               v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29486 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29487 +       }
29488 +       return (v & 0xffff);
29489 +}
29490 +
29491 +/**
29492 + * This function reads the Device All Endpoints Interrupt register and
29493 + * returns the OUT endpoint interrupt bits.
29494 + */
29495 +static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
29496 +                                                       core_if)
29497 +{
29498 +       uint32_t v;
29499 +
29500 +       if (core_if->multiproc_int_enable) {
29501 +               v = DWC_READ_REG32(&core_if->dev_if->
29502 +                                  dev_global_regs->deachint) &
29503 +                   DWC_READ_REG32(&core_if->
29504 +                                  dev_if->dev_global_regs->deachintmsk);
29505 +       } else {
29506 +               v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29507 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29508 +       }
29509 +
29510 +       return ((v & 0xffff0000) >> 16);
29511 +}
29512 +
29513 +/**
29514 + * This function returns the Device IN EP Interrupt register
29515 + */
29516 +static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
29517 +                                                  dwc_ep_t * ep)
29518 +{
29519 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
29520 +       uint32_t v, msk, emp;
29521 +
29522 +       if (core_if->multiproc_int_enable) {
29523 +               msk =
29524 +                   DWC_READ_REG32(&dev_if->
29525 +                                  dev_global_regs->diepeachintmsk[ep->num]);
29526 +               emp =
29527 +                   DWC_READ_REG32(&dev_if->
29528 +                                  dev_global_regs->dtknqr4_fifoemptymsk);
29529 +               msk |= ((emp >> ep->num) & 0x1) << 7;
29530 +               v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29531 +       } else {
29532 +               msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);
29533 +               emp =
29534 +                   DWC_READ_REG32(&dev_if->
29535 +                                  dev_global_regs->dtknqr4_fifoemptymsk);
29536 +               msk |= ((emp >> ep->num) & 0x1) << 7;
29537 +               v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29538 +       }
29539 +
29540 +       return v;
29541 +}
29542 +
29543 +/**
29544 + * This function returns the Device OUT EP Interrupt register
29545 + */
29546 +static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *
29547 +                                                   _core_if, dwc_ep_t * _ep)
29548 +{
29549 +       dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
29550 +       uint32_t v;
29551 +       doepmsk_data_t msk = {.d32 = 0 };
29552 +
29553 +       if (_core_if->multiproc_int_enable) {
29554 +               msk.d32 =
29555 +                   DWC_READ_REG32(&dev_if->
29556 +                                  dev_global_regs->doepeachintmsk[_ep->num]);
29557 +               if (_core_if->pti_enh_enable) {
29558 +                       msk.b.pktdrpsts = 1;
29559 +               }
29560 +               v = DWC_READ_REG32(&dev_if->
29561 +                                  out_ep_regs[_ep->num]->doepint) & msk.d32;
29562 +       } else {
29563 +               msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);
29564 +               if (_core_if->pti_enh_enable) {
29565 +                       msk.b.pktdrpsts = 1;
29566 +               }
29567 +               v = DWC_READ_REG32(&dev_if->
29568 +                                  out_ep_regs[_ep->num]->doepint) & msk.d32;
29569 +       }
29570 +       return v;
29571 +}
29572 +
29573 +/**
29574 + * This function returns the Host All Channel Interrupt register
29575 + */
29576 +static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t *
29577 +                                                          _core_if)
29578 +{
29579 +       return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint));
29580 +}
29581 +
29582 +static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t *
29583 +                                                     _core_if, dwc_hc_t * _hc)
29584 +{
29585 +       return (DWC_READ_REG32
29586 +               (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint));
29587 +}
29588 +
29589 +/**
29590 + * This function returns the mode of the operation, host or device.
29591 + *
29592 + * @return 0 - Device Mode, 1 - Host Mode
29593 + */
29594 +static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)
29595 +{
29596 +       return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1);
29597 +}
29598 +
29599 +/**@}*/
29600 +
29601 +/**
29602 + * DWC_otg CIL callback structure. This structure allows the HCD and
29603 + * PCD to register functions used for starting and stopping the PCD
29604 + * and HCD for role change on for a DRD.
29605 + */
29606 +typedef struct dwc_otg_cil_callbacks {
29607 +       /** Start function for role change */
29608 +       int (*start) (void *_p);
29609 +       /** Stop Function for role change */
29610 +       int (*stop) (void *_p);
29611 +       /** Disconnect Function for role change */
29612 +       int (*disconnect) (void *_p);
29613 +       /** Resume/Remote wakeup Function */
29614 +       int (*resume_wakeup) (void *_p);
29615 +       /** Suspend function */
29616 +       int (*suspend) (void *_p);
29617 +       /** Session Start (SRP) */
29618 +       int (*session_start) (void *_p);
29619 +#ifdef CONFIG_USB_DWC_OTG_LPM
29620 +       /** Sleep (switch to L0 state) */
29621 +       int (*sleep) (void *_p);
29622 +#endif
29623 +       /** Pointer passed to start() and stop() */
29624 +       void *p;
29625 +} dwc_otg_cil_callbacks_t;
29626 +
29627 +extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if,
29628 +                                              dwc_otg_cil_callbacks_t * _cb,
29629 +                                              void *_p);
29630 +extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if,
29631 +                                              dwc_otg_cil_callbacks_t * _cb,
29632 +                                              void *_p);
29633 +
29634 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if);
29635 +
29636 +//////////////////////////////////////////////////////////////////////
29637 +/** Start the HCD.  Helper function for using the HCD callbacks.
29638 + *
29639 + * @param core_if Programming view of DWC_otg controller.
29640 + */
29641 +static inline void cil_hcd_start(dwc_otg_core_if_t * core_if)
29642 +{
29643 +       if (core_if->hcd_cb && core_if->hcd_cb->start) {
29644 +               core_if->hcd_cb->start(core_if->hcd_cb->p);
29645 +       }
29646 +}
29647 +
29648 +/** Stop the HCD.  Helper function for using the HCD callbacks.
29649 + *
29650 + * @param core_if Programming view of DWC_otg controller.
29651 + */
29652 +static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if)
29653 +{
29654 +       if (core_if->hcd_cb && core_if->hcd_cb->stop) {
29655 +               core_if->hcd_cb->stop(core_if->hcd_cb->p);
29656 +       }
29657 +}
29658 +
29659 +/** Disconnect the HCD.  Helper function for using the HCD callbacks.
29660 + *
29661 + * @param core_if Programming view of DWC_otg controller.
29662 + */
29663 +static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if)
29664 +{
29665 +       if (core_if->hcd_cb && core_if->hcd_cb->disconnect) {
29666 +               core_if->hcd_cb->disconnect(core_if->hcd_cb->p);
29667 +       }
29668 +}
29669 +
29670 +/** Inform the HCD the a New Session has begun.  Helper function for
29671 + * using the HCD callbacks.
29672 + *
29673 + * @param core_if Programming view of DWC_otg controller.
29674 + */
29675 +static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if)
29676 +{
29677 +       if (core_if->hcd_cb && core_if->hcd_cb->session_start) {
29678 +               core_if->hcd_cb->session_start(core_if->hcd_cb->p);
29679 +       }
29680 +}
29681 +
29682 +#ifdef CONFIG_USB_DWC_OTG_LPM
29683 +/**
29684 + * Inform the HCD about LPM sleep.
29685 + * Helper function for using the HCD callbacks.
29686 + *
29687 + * @param core_if Programming view of DWC_otg controller.
29688 + */
29689 +static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if)
29690 +{
29691 +       if (core_if->hcd_cb && core_if->hcd_cb->sleep) {
29692 +               core_if->hcd_cb->sleep(core_if->hcd_cb->p);
29693 +       }
29694 +}
29695 +#endif
29696 +
29697 +/** Resume the HCD.  Helper function for using the HCD callbacks.
29698 + *
29699 + * @param core_if Programming view of DWC_otg controller.
29700 + */
29701 +static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if)
29702 +{
29703 +       if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) {
29704 +               core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p);
29705 +       }
29706 +}
29707 +
29708 +/** Start the PCD.  Helper function for using the PCD callbacks.
29709 + *
29710 + * @param core_if Programming view of DWC_otg controller.
29711 + */
29712 +static inline void cil_pcd_start(dwc_otg_core_if_t * core_if)
29713 +{
29714 +       if (core_if->pcd_cb && core_if->pcd_cb->start) {
29715 +               core_if->pcd_cb->start(core_if->pcd_cb->p);
29716 +       }
29717 +}
29718 +
29719 +/** Stop the PCD.  Helper function for using the PCD callbacks.
29720 + *
29721 + * @param core_if Programming view of DWC_otg controller.
29722 + */
29723 +static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if)
29724 +{
29725 +       if (core_if->pcd_cb && core_if->pcd_cb->stop) {
29726 +               core_if->pcd_cb->stop(core_if->pcd_cb->p);
29727 +       }
29728 +}
29729 +
29730 +/** Suspend the PCD.  Helper function for using the PCD callbacks.
29731 + *
29732 + * @param core_if Programming view of DWC_otg controller.
29733 + */
29734 +static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if)
29735 +{
29736 +       if (core_if->pcd_cb && core_if->pcd_cb->suspend) {
29737 +               core_if->pcd_cb->suspend(core_if->pcd_cb->p);
29738 +       }
29739 +}
29740 +
29741 +/** Resume the PCD.  Helper function for using the PCD callbacks.
29742 + *
29743 + * @param core_if Programming view of DWC_otg controller.
29744 + */
29745 +static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if)
29746 +{
29747 +       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
29748 +               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
29749 +       }
29750 +}
29751 +
29752 +//////////////////////////////////////////////////////////////////////
29753 +
29754 +#endif
29755 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
29756 new file mode 100644
29757 index 0000000..21804c4
29758 --- /dev/null
29759 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
29760 @@ -0,0 +1,1563 @@
29761 +/* ==========================================================================
29762 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
29763 + * $Revision: #32 $
29764 + * $Date: 2012/08/10 $
29765 + * $Change: 2047372 $
29766 + *
29767 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
29768 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
29769 + * otherwise expressly agreed to in writing between Synopsys and you.
29770 + *
29771 + * The Software IS NOT an item of Licensed Software or Licensed Product under
29772 + * any End User Software License Agreement or Agreement for Licensed Product
29773 + * with Synopsys or any supplement thereto. You are permitted to use and
29774 + * redistribute this Software in source and binary forms, with or without
29775 + * modification, provided that redistributions of source code must retain this
29776 + * notice. You may not view, use, disclose, copy or distribute this file or
29777 + * any information contained herein except pursuant to this license grant from
29778 + * Synopsys. If you do not agree with this notice, including the disclaimer
29779 + * below, then you are not authorized to use the Software.
29780 + *
29781 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
29782 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29783 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29784 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
29785 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29786 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29787 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29788 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29789 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29790 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29791 + * DAMAGE.
29792 + * ========================================================================== */
29793 +
29794 +/** @file
29795 + *
29796 + * The Core Interface Layer provides basic services for accessing and
29797 + * managing the DWC_otg hardware. These services are used by both the
29798 + * Host Controller Driver and the Peripheral Controller Driver.
29799 + *
29800 + * This file contains the Common Interrupt handlers.
29801 + */
29802 +#include "dwc_os.h"
29803 +#include "dwc_otg_regs.h"
29804 +#include "dwc_otg_cil.h"
29805 +#include "dwc_otg_driver.h"
29806 +#include "dwc_otg_pcd.h"
29807 +#include "dwc_otg_hcd.h"
29808 +
29809 +#ifdef DEBUG
29810 +inline const char *op_state_str(dwc_otg_core_if_t * core_if)
29811 +{
29812 +       return (core_if->op_state == A_HOST ? "a_host" :
29813 +               (core_if->op_state == A_SUSPEND ? "a_suspend" :
29814 +                (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
29815 +                 (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
29816 +                  (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
29817 +}
29818 +#endif
29819 +
29820 +/** This function will log a debug message
29821 + *
29822 + * @param core_if Programming view of DWC_otg controller.
29823 + */
29824 +int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)
29825 +{
29826 +       gintsts_data_t gintsts;
29827 +       DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
29828 +                dwc_otg_mode(core_if) ? "Host" : "Device");
29829 +
29830 +       /* Clear interrupt */
29831 +       gintsts.d32 = 0;
29832 +       gintsts.b.modemismatch = 1;
29833 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29834 +       return 1;
29835 +}
29836 +
29837 +/**
29838 + * This function handles the OTG Interrupts. It reads the OTG
29839 + * Interrupt Register (GOTGINT) to determine what interrupt has
29840 + * occurred.
29841 + *
29842 + * @param core_if Programming view of DWC_otg controller.
29843 + */
29844 +int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)
29845 +{
29846 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
29847 +       gotgint_data_t gotgint;
29848 +       gotgctl_data_t gotgctl;
29849 +       gintmsk_data_t gintmsk;
29850 +       gpwrdn_data_t gpwrdn;
29851 +
29852 +       gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);
29853 +       gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29854 +       DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
29855 +                   op_state_str(core_if));
29856 +
29857 +       if (gotgint.b.sesenddet) {
29858 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29859 +                           "Session End Detected++ (%s)\n",
29860 +                           op_state_str(core_if));
29861 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29862 +
29863 +               if (core_if->op_state == B_HOST) {
29864 +                       cil_pcd_start(core_if);
29865 +                       core_if->op_state = B_PERIPHERAL;
29866 +               } else {
29867 +                       /* If not B_HOST and Device HNP still set. HNP
29868 +                        * Did not succeed!*/
29869 +                       if (gotgctl.b.devhnpen) {
29870 +                               DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
29871 +                               __DWC_ERROR("Device Not Connected/Responding!\n");
29872 +                       }
29873 +
29874 +                       /* If Session End Detected the B-Cable has
29875 +                        * been disconnected. */
29876 +                       /* Reset PCD and Gadget driver to a
29877 +                        * clean state. */
29878 +                       core_if->lx_state = DWC_OTG_L0;
29879 +                       DWC_SPINUNLOCK(core_if->lock);
29880 +                       cil_pcd_stop(core_if);
29881 +                       DWC_SPINLOCK(core_if->lock);
29882 +
29883 +                       if (core_if->adp_enable) {
29884 +                               if (core_if->power_down == 2) {
29885 +                                       gpwrdn.d32 = 0;
29886 +                                       gpwrdn.b.pwrdnswtch = 1;
29887 +                                       DWC_MODIFY_REG32(&core_if->
29888 +                                                        core_global_regs->
29889 +                                                        gpwrdn, gpwrdn.d32, 0);
29890 +                               }
29891 +
29892 +                               gpwrdn.d32 = 0;
29893 +                               gpwrdn.b.pmuintsel = 1;
29894 +                               gpwrdn.b.pmuactv = 1;
29895 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
29896 +                                                gpwrdn, 0, gpwrdn.d32);
29897 +
29898 +                               dwc_otg_adp_sense_start(core_if);
29899 +                       }
29900 +               }
29901 +
29902 +               gotgctl.d32 = 0;
29903 +               gotgctl.b.devhnpen = 1;
29904 +               DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29905 +       }
29906 +       if (gotgint.b.sesreqsucstschng) {
29907 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29908 +                           "Session Reqeust Success Status Change++\n");
29909 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29910 +               if (gotgctl.b.sesreqscs) {
29911 +
29912 +                       if ((core_if->core_params->phy_type ==
29913 +                            DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {
29914 +                               core_if->srp_success = 1;
29915 +                       } else {
29916 +                               DWC_SPINUNLOCK(core_if->lock);
29917 +                               cil_pcd_resume(core_if);
29918 +                               DWC_SPINLOCK(core_if->lock);
29919 +                               /* Clear Session Request */
29920 +                               gotgctl.d32 = 0;
29921 +                               gotgctl.b.sesreq = 1;
29922 +                               DWC_MODIFY_REG32(&global_regs->gotgctl,
29923 +                                                gotgctl.d32, 0);
29924 +                       }
29925 +               }
29926 +       }
29927 +       if (gotgint.b.hstnegsucstschng) {
29928 +               /* Print statements during the HNP interrupt handling
29929 +                * can cause it to fail.*/
29930 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29931 +               /* WA for 3.00a- HW is not setting cur_mode, even sometimes
29932 +                * this does not help*/
29933 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a)
29934 +                       dwc_udelay(100);
29935 +               if (gotgctl.b.hstnegscs) {
29936 +                       if (dwc_otg_is_host_mode(core_if)) {
29937 +                               core_if->op_state = B_HOST;
29938 +                               /*
29939 +                                * Need to disable SOF interrupt immediately.
29940 +                                * When switching from device to host, the PCD
29941 +                                * interrupt handler won't handle the
29942 +                                * interrupt if host mode is already set. The
29943 +                                * HCD interrupt handler won't get called if
29944 +                                * the HCD state is HALT. This means that the
29945 +                                * interrupt does not get handled and Linux
29946 +                                * complains loudly.
29947 +                                */
29948 +                               gintmsk.d32 = 0;
29949 +                               gintmsk.b.sofintr = 1;
29950 +                               DWC_MODIFY_REG32(&global_regs->gintmsk,
29951 +                                                gintmsk.d32, 0);
29952 +                               /* Call callback function with spin lock released */
29953 +                               DWC_SPINUNLOCK(core_if->lock);
29954 +                               cil_pcd_stop(core_if);
29955 +                               /*
29956 +                                * Initialize the Core for Host mode.
29957 +                                */
29958 +                               cil_hcd_start(core_if);
29959 +                               DWC_SPINLOCK(core_if->lock);
29960 +                               core_if->op_state = B_HOST;
29961 +                       }
29962 +               } else {
29963 +                       gotgctl.d32 = 0;
29964 +                       gotgctl.b.hnpreq = 1;
29965 +                       gotgctl.b.devhnpen = 1;
29966 +                       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29967 +                       DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
29968 +                       __DWC_ERROR("Device Not Connected/Responding\n");
29969 +               }
29970 +       }
29971 +       if (gotgint.b.hstnegdet) {
29972 +               /* The disconnect interrupt is set at the same time as
29973 +                * Host Negotiation Detected.  During the mode
29974 +                * switch all interrupts are cleared so the disconnect
29975 +                * interrupt handler will not get executed.
29976 +                */
29977 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29978 +                           "Host Negotiation Detected++ (%s)\n",
29979 +                           (dwc_otg_is_host_mode(core_if) ? "Host" :
29980 +                            "Device"));
29981 +               if (dwc_otg_is_device_mode(core_if)) {
29982 +                       DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
29983 +                                   core_if->op_state);
29984 +                       DWC_SPINUNLOCK(core_if->lock);
29985 +                       cil_hcd_disconnect(core_if);
29986 +                       cil_pcd_start(core_if);
29987 +                       DWC_SPINLOCK(core_if->lock);
29988 +                       core_if->op_state = A_PERIPHERAL;
29989 +               } else {
29990 +                       /*
29991 +                        * Need to disable SOF interrupt immediately. When
29992 +                        * switching from device to host, the PCD interrupt
29993 +                        * handler won't handle the interrupt if host mode is
29994 +                        * already set. The HCD interrupt handler won't get
29995 +                        * called if the HCD state is HALT. This means that
29996 +                        * the interrupt does not get handled and Linux
29997 +                        * complains loudly.
29998 +                        */
29999 +                       gintmsk.d32 = 0;
30000 +                       gintmsk.b.sofintr = 1;
30001 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);
30002 +                       DWC_SPINUNLOCK(core_if->lock);
30003 +                       cil_pcd_stop(core_if);
30004 +                       cil_hcd_start(core_if);
30005 +                       DWC_SPINLOCK(core_if->lock);
30006 +                       core_if->op_state = A_HOST;
30007 +               }
30008 +       }
30009 +       if (gotgint.b.adevtoutchng) {
30010 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
30011 +                           "A-Device Timeout Change++\n");
30012 +       }
30013 +       if (gotgint.b.debdone) {
30014 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
30015 +       }
30016 +
30017 +       /* Clear GOTGINT */
30018 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);
30019 +
30020 +       return 1;
30021 +}
30022 +
30023 +void w_conn_id_status_change(void *p)
30024 +{
30025 +       dwc_otg_core_if_t *core_if = p;
30026 +       uint32_t count = 0;
30027 +       gotgctl_data_t gotgctl = {.d32 = 0 };
30028 +
30029 +       gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
30030 +       DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
30031 +       DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
30032 +
30033 +       /* B-Device connector (Device Mode) */
30034 +       if (gotgctl.b.conidsts) {
30035 +               /* Wait for switch to device mode. */
30036 +               while (!dwc_otg_is_device_mode(core_if)) {
30037 +                       DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",
30038 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
30039 +                                   "Peripheral"));
30040 +                       dwc_mdelay(100);
30041 +                       if (++count > 10000)
30042 +                               break;
30043 +               }
30044 +               DWC_ASSERT(++count < 10000,
30045 +                          "Connection id status change timed out");
30046 +               core_if->op_state = B_PERIPHERAL;
30047 +               dwc_otg_core_init(core_if);
30048 +               dwc_otg_enable_global_interrupts(core_if);
30049 +               cil_pcd_start(core_if);
30050 +       } else {
30051 +               /* A-Device connector (Host Mode) */
30052 +               while (!dwc_otg_is_host_mode(core_if)) {
30053 +                       DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",
30054 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
30055 +                                   "Peripheral"));
30056 +                       dwc_mdelay(100);
30057 +                       if (++count > 10000)
30058 +                               break;
30059 +               }
30060 +               DWC_ASSERT(++count < 10000,
30061 +                          "Connection id status change timed out");
30062 +               core_if->op_state = A_HOST;
30063 +               /*
30064 +                * Initialize the Core for Host mode.
30065 +                */
30066 +               dwc_otg_core_init(core_if);
30067 +               dwc_otg_enable_global_interrupts(core_if);
30068 +               cil_hcd_start(core_if);
30069 +       }
30070 +}
30071 +
30072 +/**
30073 + * This function handles the Connector ID Status Change Interrupt.  It
30074 + * reads the OTG Interrupt Register (GOTCTL) to determine whether this
30075 + * is a Device to Host Mode transition or a Host Mode to Device
30076 + * Transition. 
30077 + *
30078 + * This only occurs when the cable is connected/removed from the PHY
30079 + * connector.
30080 + *
30081 + * @param core_if Programming view of DWC_otg controller.
30082 + */
30083 +int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)
30084 +{
30085 +
30086 +       /*
30087 +        * Need to disable SOF interrupt immediately. If switching from device
30088 +        * to host, the PCD interrupt handler won't handle the interrupt if
30089 +        * host mode is already set. The HCD interrupt handler won't get
30090 +        * called if the HCD state is HALT. This means that the interrupt does
30091 +        * not get handled and Linux complains loudly.
30092 +        */
30093 +       gintmsk_data_t gintmsk = {.d32 = 0 };
30094 +       gintsts_data_t gintsts = {.d32 = 0 };
30095 +
30096 +       gintmsk.b.sofintr = 1;
30097 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
30098 +
30099 +       DWC_DEBUGPL(DBG_CIL,
30100 +                   " ++Connector ID Status Change Interrupt++  (%s)\n",
30101 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
30102 +       
30103 +       DWC_SPINUNLOCK(core_if->lock);
30104 +
30105 +       /*
30106 +        * Need to schedule a work, as there are possible DELAY function calls
30107 +        * Release lock before scheduling workq as it holds spinlock during scheduling
30108 +        */
30109 +
30110 +       DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
30111 +                          core_if, "connection id status change");
30112 +       DWC_SPINLOCK(core_if->lock);
30113 +
30114 +       /* Set flag and clear interrupt */
30115 +       gintsts.b.conidstschng = 1;
30116 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30117 +
30118 +       return 1;
30119 +}
30120 +
30121 +/**
30122 + * This interrupt indicates that a device is initiating the Session
30123 + * Request Protocol to request the host to turn on bus power so a new
30124 + * session can begin. The handler responds by turning on bus power. If
30125 + * the DWC_otg controller is in low power mode, the handler brings the
30126 + * controller out of low power mode before turning on bus power.
30127 + *
30128 + * @param core_if Programming view of DWC_otg controller.
30129 + */
30130 +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
30131 +{
30132 +       gintsts_data_t gintsts;
30133 +
30134 +#ifndef DWC_HOST_ONLY
30135 +       DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
30136 +
30137 +       if (dwc_otg_is_device_mode(core_if)) {
30138 +               DWC_PRINTF("SRP: Device mode\n");
30139 +       } else {
30140 +               hprt0_data_t hprt0;
30141 +               DWC_PRINTF("SRP: Host mode\n");
30142 +
30143 +               /* Turn on the port power bit. */
30144 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
30145 +               hprt0.b.prtpwr = 1;
30146 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
30147 +
30148 +               /* Start the Connection timer. So a message can be displayed
30149 +                * if connect does not occur within 10 seconds. */
30150 +               cil_hcd_session_start(core_if);
30151 +       }
30152 +#endif
30153 +
30154 +       /* Clear interrupt */
30155 +       gintsts.d32 = 0;
30156 +       gintsts.b.sessreqintr = 1;
30157 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30158 +
30159 +       return 1;
30160 +}
30161 +
30162 +void w_wakeup_detected(void *p)
30163 +{
30164 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;
30165 +       /*
30166 +        * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
30167 +        * so that OPT tests pass with all PHYs).
30168 +        */
30169 +       hprt0_data_t hprt0 = {.d32 = 0 };
30170 +#if 0
30171 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30172 +       /* Restart the Phy Clock */
30173 +       pcgcctl.b.stoppclk = 1;
30174 +       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30175 +       dwc_udelay(10);
30176 +#endif //0
30177 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
30178 +       DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
30179 +//      dwc_mdelay(70);
30180 +       hprt0.b.prtres = 0;     /* Resume */
30181 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
30182 +       DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
30183 +                   DWC_READ_REG32(core_if->host_if->hprt0));
30184 +
30185 +       cil_hcd_resume(core_if);
30186 +
30187 +       /** Change to L0 state*/
30188 +       core_if->lx_state = DWC_OTG_L0;
30189 +}
30190 +
30191 +/**
30192 + * This interrupt indicates that the DWC_otg controller has detected a
30193 + * resume or remote wakeup sequence. If the DWC_otg controller is in
30194 + * low power mode, the handler must brings the controller out of low
30195 + * power mode. The controller automatically begins resume
30196 + * signaling. The handler schedules a time to stop resume signaling.
30197 + */
30198 +int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30199 +{
30200 +       gintsts_data_t gintsts;
30201 +
30202 +       DWC_DEBUGPL(DBG_ANY,
30203 +                   "++Resume and Remote Wakeup Detected Interrupt++\n");
30204 +
30205 +       DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
30206 +
30207 +       if (dwc_otg_is_device_mode(core_if)) {
30208 +               dctl_data_t dctl = {.d32 = 0 };
30209 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
30210 +                           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
30211 +                                          dsts));
30212 +               if (core_if->lx_state == DWC_OTG_L2) {
30213 +#ifdef PARTIAL_POWER_DOWN
30214 +                       if (core_if->hwcfg4.b.power_optimiz) {
30215 +                               pcgcctl_data_t power = {.d32 = 0 };
30216 +
30217 +                               power.d32 = DWC_READ_REG32(core_if->pcgcctl);
30218 +                               DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
30219 +                                           power.d32);
30220 +
30221 +                               power.b.stoppclk = 0;
30222 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30223 +
30224 +                               power.b.pwrclmp = 0;
30225 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30226 +
30227 +                               power.b.rstpdwnmodule = 0;
30228 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30229 +                       }
30230 +#endif
30231 +                       /* Clear the Remote Wakeup Signaling */
30232 +                       dctl.b.rmtwkupsig = 1;
30233 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
30234 +                                        dctl, dctl.d32, 0);
30235 +
30236 +                       DWC_SPINUNLOCK(core_if->lock);
30237 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
30238 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
30239 +                       }
30240 +                       DWC_SPINLOCK(core_if->lock);
30241 +               } else {
30242 +                       glpmcfg_data_t lpmcfg;
30243 +                       lpmcfg.d32 =
30244 +                           DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30245 +                       lpmcfg.b.hird_thres &= (~(1 << 4));
30246 +                       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
30247 +                                       lpmcfg.d32);
30248 +               }
30249 +               /** Change to L0 state*/
30250 +               core_if->lx_state = DWC_OTG_L0;
30251 +       } else {
30252 +               if (core_if->lx_state != DWC_OTG_L1) {
30253 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30254 +
30255 +                       /* Restart the Phy Clock */
30256 +                       pcgcctl.b.stoppclk = 1;
30257 +                       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30258 +                       DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);
30259 +               } else {
30260 +                       /** Change to L0 state*/
30261 +                       core_if->lx_state = DWC_OTG_L0;
30262 +               }
30263 +       }
30264 +
30265 +       /* Clear interrupt */
30266 +       gintsts.d32 = 0;
30267 +       gintsts.b.wkupintr = 1;
30268 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30269 +
30270 +       return 1;
30271 +}
30272 +
30273 +/**
30274 + * This interrupt indicates that the Wakeup Logic has detected a
30275 + * Device disconnect.
30276 + */
30277 +static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)
30278 +{
30279 +       gpwrdn_data_t gpwrdn = { .d32 = 0 };
30280 +       gpwrdn_data_t gpwrdn_temp = { .d32 = 0 };
30281 +       gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30282 +
30283 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30284 +
30285 +       if (!core_if->hibernation_suspend) {
30286 +               DWC_PRINTF("Already exited from Hibernation\n");
30287 +               return 1;
30288 +       }
30289 +
30290 +       /* Switch on the voltage to the core */
30291 +       gpwrdn.b.pwrdnswtch = 1;
30292 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30293 +       dwc_udelay(10);
30294 +
30295 +       /* Reset the core */
30296 +       gpwrdn.d32 = 0;
30297 +       gpwrdn.b.pwrdnrstn = 1;
30298 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30299 +       dwc_udelay(10);
30300 +
30301 +       /* Disable power clamps*/
30302 +       gpwrdn.d32 = 0;
30303 +       gpwrdn.b.pwrdnclmp = 1;
30304 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30305 +
30306 +       /* Remove reset the core signal */
30307 +       gpwrdn.d32 = 0;
30308 +       gpwrdn.b.pwrdnrstn = 1;
30309 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30310 +       dwc_udelay(10);
30311 +
30312 +       /* Disable PMU interrupt */
30313 +       gpwrdn.d32 = 0;
30314 +       gpwrdn.b.pmuintsel = 1;
30315 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30316 +
30317 +       core_if->hibernation_suspend = 0;
30318 +
30319 +       /* Disable PMU */
30320 +       gpwrdn.d32 = 0;
30321 +       gpwrdn.b.pmuactv = 1;
30322 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30323 +       dwc_udelay(10);
30324 +
30325 +       if (gpwrdn_temp.b.idsts) {
30326 +               core_if->op_state = B_PERIPHERAL;
30327 +               dwc_otg_core_init(core_if);
30328 +               dwc_otg_enable_global_interrupts(core_if);
30329 +               cil_pcd_start(core_if);
30330 +       } else {
30331 +               core_if->op_state = A_HOST;
30332 +               dwc_otg_core_init(core_if);
30333 +               dwc_otg_enable_global_interrupts(core_if);
30334 +               cil_hcd_start(core_if);
30335 +       }
30336 +
30337 +       return 1;
30338 +}
30339 +
30340 +/**
30341 + * This interrupt indicates that the Wakeup Logic has detected a
30342 + * remote wakeup sequence.
30343 + */
30344 +static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30345 +{
30346 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30347 +       DWC_DEBUGPL(DBG_ANY,
30348 +                   "++Powerdown Remote Wakeup Detected Interrupt++\n");
30349 +
30350 +       if (!core_if->hibernation_suspend) {
30351 +               DWC_PRINTF("Already exited from Hibernation\n");
30352 +               return 1;
30353 +       }
30354 +
30355 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30356 +       if (gpwrdn.b.idsts) {   // Device Mode
30357 +               if ((core_if->power_down == 2)
30358 +                   && (core_if->hibernation_suspend == 1)) {
30359 +                       dwc_otg_device_hibernation_restore(core_if, 0, 0);
30360 +               }
30361 +       } else {
30362 +               if ((core_if->power_down == 2)
30363 +                   && (core_if->hibernation_suspend == 1)) {
30364 +                       dwc_otg_host_hibernation_restore(core_if, 1, 0);
30365 +               }
30366 +       }
30367 +       return 1;
30368 +}
30369 +
30370 +static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
30371 +{
30372 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30373 +       gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30374 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30375 +
30376 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30377 +       gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30378 +       if (core_if->power_down == 2) {
30379 +               if (!core_if->hibernation_suspend) {
30380 +                       DWC_PRINTF("Already exited from Hibernation\n");
30381 +                       return 1;
30382 +               }
30383 +               DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");
30384 +               /* Switch on the voltage to the core */
30385 +               gpwrdn.b.pwrdnswtch = 1;
30386 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30387 +               dwc_udelay(10);
30388 +
30389 +               /* Reset the core */
30390 +               gpwrdn.d32 = 0;
30391 +               gpwrdn.b.pwrdnrstn = 1;
30392 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30393 +               dwc_udelay(10);
30394 +
30395 +               /* Disable power clamps */
30396 +               gpwrdn.d32 = 0;
30397 +               gpwrdn.b.pwrdnclmp = 1;
30398 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30399 +
30400 +               /* Remove reset the core signal */
30401 +               gpwrdn.d32 = 0;
30402 +               gpwrdn.b.pwrdnrstn = 1;
30403 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30404 +               dwc_udelay(10);
30405 +
30406 +               /* Disable PMU interrupt */
30407 +               gpwrdn.d32 = 0;
30408 +               gpwrdn.b.pmuintsel = 1;
30409 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30410 +
30411 +               /*Indicates that we are exiting from hibernation */
30412 +               core_if->hibernation_suspend = 0;
30413 +
30414 +               /* Disable PMU */
30415 +               gpwrdn.d32 = 0;
30416 +               gpwrdn.b.pmuactv = 1;
30417 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30418 +               dwc_udelay(10);
30419 +
30420 +               gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
30421 +               if (gpwrdn.b.dis_vbus == 1) {
30422 +                       gpwrdn.d32 = 0;
30423 +                       gpwrdn.b.dis_vbus = 1;
30424 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30425 +               }
30426 +
30427 +               if (gpwrdn_temp.b.idsts) {
30428 +                       core_if->op_state = B_PERIPHERAL;
30429 +                       dwc_otg_core_init(core_if);
30430 +                       dwc_otg_enable_global_interrupts(core_if);
30431 +                       cil_pcd_start(core_if);
30432 +               } else {
30433 +                       core_if->op_state = A_HOST;
30434 +                       dwc_otg_core_init(core_if);
30435 +                       dwc_otg_enable_global_interrupts(core_if);
30436 +                       cil_hcd_start(core_if);
30437 +               }
30438 +       }
30439 +
30440 +       if (core_if->adp_enable) {
30441 +               uint8_t is_host = 0;
30442 +               DWC_SPINUNLOCK(core_if->lock);
30443 +               /* Change the core_if's lock to hcd/pcd lock depend on mode? */
30444 +#ifndef DWC_HOST_ONLY          
30445 +               if (gpwrdn_temp.b.idsts)
30446 +                       core_if->lock = otg_dev->pcd->lock;
30447 +#endif
30448 +#ifndef DWC_DEVICE_ONLY
30449 +               if (!gpwrdn_temp.b.idsts) {
30450 +                               core_if->lock = otg_dev->hcd->lock;     
30451 +                               is_host = 1;
30452 +               }
30453 +#endif
30454 +               DWC_PRINTF("RESTART ADP\n");
30455 +               if (core_if->adp.probe_enabled)         
30456 +                       dwc_otg_adp_probe_stop(core_if);
30457 +               if (core_if->adp.sense_enabled)         
30458 +                       dwc_otg_adp_sense_stop(core_if);
30459 +               if (core_if->adp.sense_timer_started)           
30460 +                       DWC_TIMER_CANCEL(core_if->adp.sense_timer);
30461 +               if (core_if->adp.vbuson_timer_started)          
30462 +                       DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
30463 +               core_if->adp.probe_timer_values[0] = -1;
30464 +               core_if->adp.probe_timer_values[1] = -1;
30465 +               core_if->adp.sense_timer_started = 0;
30466 +               core_if->adp.vbuson_timer_started = 0;
30467 +               core_if->adp.probe_counter = 0;
30468 +               core_if->adp.gpwrdn = 0;
30469 +               
30470 +               /* Disable PMU and restart ADP */
30471 +               gpwrdn_temp.d32 = 0;
30472 +               gpwrdn_temp.b.pmuactv = 1;
30473 +               gpwrdn_temp.b.pmuintsel = 1;
30474 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30475 +               DWC_PRINTF("Check point 1\n");
30476 +               dwc_mdelay(110);
30477 +               dwc_otg_adp_start(core_if, is_host);
30478 +               DWC_SPINLOCK(core_if->lock);
30479 +       }
30480 +       
30481 +
30482 +       return 1;
30483 +}
30484 +
30485 +static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if)
30486 +{
30487 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30488 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
30489 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30490 +
30491 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30492 +       if (core_if->power_down == 2) {
30493 +               if (!core_if->hibernation_suspend) {
30494 +                       DWC_PRINTF("Already exited from Hibernation\n");
30495 +                       return 1;
30496 +               }
30497 +
30498 +               if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30499 +                        otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
30500 +                       gpwrdn.b.bsessvld == 0) {
30501 +                       /* Save gpwrdn register for further usage if stschng interrupt */
30502 +                       core_if->gr_backup->gpwrdn_local =
30503 +                               DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30504 +                       /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
30505 +                       return 1;
30506 +               }
30507 +
30508 +               /* Switch on the voltage to the core */
30509 +               gpwrdn.d32 = 0;
30510 +               gpwrdn.b.pwrdnswtch = 1;
30511 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30512 +               dwc_udelay(10);
30513 +
30514 +               /* Reset the core */
30515 +               gpwrdn.d32 = 0;
30516 +               gpwrdn.b.pwrdnrstn = 1;
30517 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30518 +               dwc_udelay(10);
30519 +
30520 +               /* Disable power clamps */
30521 +               gpwrdn.d32 = 0;
30522 +               gpwrdn.b.pwrdnclmp = 1;
30523 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30524 +
30525 +               /* Remove reset the core signal */
30526 +               gpwrdn.d32 = 0;
30527 +               gpwrdn.b.pwrdnrstn = 1;
30528 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30529 +               dwc_udelay(10);
30530 +
30531 +               /* Disable PMU interrupt */
30532 +               gpwrdn.d32 = 0;
30533 +               gpwrdn.b.pmuintsel = 1;
30534 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30535 +               dwc_udelay(10);
30536 +
30537 +               /*Indicates that we are exiting from hibernation */
30538 +               core_if->hibernation_suspend = 0;
30539 +
30540 +               /* Disable PMU */
30541 +               gpwrdn.d32 = 0;
30542 +               gpwrdn.b.pmuactv = 1;
30543 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30544 +               dwc_udelay(10);
30545 +
30546 +               core_if->op_state = B_PERIPHERAL;
30547 +               dwc_otg_core_init(core_if);
30548 +               dwc_otg_enable_global_interrupts(core_if);
30549 +               cil_pcd_start(core_if);
30550 +
30551 +               if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30552 +                       otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
30553 +                       /*
30554 +                        * Initiate SRP after initial ADP probe.
30555 +                        */
30556 +                       dwc_otg_initiate_srp(core_if);  
30557 +               }
30558 +       }
30559 +
30560 +       return 1;
30561 +}
30562 +/**
30563 + * This interrupt indicates that the Wakeup Logic has detected a
30564 + * status change either on IDDIG or BSessVld.
30565 + */
30566 +static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
30567 +{
30568 +       int retval;
30569 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30570 +       gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30571 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30572 +
30573 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30574 +       
30575 +       if (core_if->power_down == 2) {
30576 +               if (core_if->hibernation_suspend <= 0) {
30577 +                       DWC_PRINTF("Already exited from Hibernation\n");
30578 +                       return 1;
30579 +               } else
30580 +                       gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
30581 +
30582 +       } else {
30583 +               gpwrdn_temp.d32 = core_if->adp.gpwrdn;
30584 +       }
30585 +
30586 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30587 +       
30588 +       if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
30589 +               retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
30590 +       } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
30591 +               retval = dwc_otg_handle_pwrdn_session_change(core_if);
30592 +       }
30593 +
30594 +       return retval;
30595 +}
30596 +
30597 +/**
30598 + * This interrupt indicates that the Wakeup Logic has detected a
30599 + * SRP.
30600 + */
30601 +static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if)
30602 +{
30603 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30604 +
30605 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30606 +
30607 +       if (!core_if->hibernation_suspend) {
30608 +               DWC_PRINTF("Already exited from Hibernation\n");
30609 +               return 1;
30610 +       }
30611 +#ifdef DWC_DEV_SRPCAP
30612 +       if (core_if->pwron_timer_started) {
30613 +               core_if->pwron_timer_started = 0;
30614 +               DWC_TIMER_CANCEL(core_if->pwron_timer);
30615 +       }
30616 +#endif
30617 +
30618 +       /* Switch on the voltage to the core */
30619 +       gpwrdn.b.pwrdnswtch = 1;
30620 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30621 +       dwc_udelay(10);
30622 +
30623 +       /* Reset the core */
30624 +       gpwrdn.d32 = 0;
30625 +       gpwrdn.b.pwrdnrstn = 1;
30626 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30627 +       dwc_udelay(10);
30628 +
30629 +       /* Disable power clamps */
30630 +       gpwrdn.d32 = 0;
30631 +       gpwrdn.b.pwrdnclmp = 1;
30632 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30633 +
30634 +       /* Remove reset the core signal */
30635 +       gpwrdn.d32 = 0;
30636 +       gpwrdn.b.pwrdnrstn = 1;
30637 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30638 +       dwc_udelay(10);
30639 +
30640 +       /* Disable PMU interrupt */
30641 +       gpwrdn.d32 = 0;
30642 +       gpwrdn.b.pmuintsel = 1;
30643 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30644 +
30645 +       /* Indicates that we are exiting from hibernation */
30646 +       core_if->hibernation_suspend = 0;
30647 +
30648 +       /* Disable PMU */
30649 +       gpwrdn.d32 = 0;
30650 +       gpwrdn.b.pmuactv = 1;
30651 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30652 +       dwc_udelay(10);
30653 +
30654 +       /* Programm Disable VBUS to 0 */
30655 +       gpwrdn.d32 = 0;
30656 +       gpwrdn.b.dis_vbus = 1;
30657 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30658 +
30659 +       /*Initialize the core as Host */
30660 +       core_if->op_state = A_HOST;
30661 +       dwc_otg_core_init(core_if);
30662 +       dwc_otg_enable_global_interrupts(core_if);
30663 +       cil_hcd_start(core_if);
30664 +
30665 +       return 1;
30666 +}
30667 +
30668 +/** This interrupt indicates that restore command after Hibernation
30669 + * was completed by the core. */
30670 +int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if)
30671 +{
30672 +       pcgcctl_data_t pcgcctl;
30673 +       DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");
30674 +
30675 +       //TODO De-assert restore signal. 8.a
30676 +       pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);
30677 +       if (pcgcctl.b.restoremode == 1) {
30678 +               gintmsk_data_t gintmsk = {.d32 = 0 };
30679 +               /*
30680 +                * If restore mode is Remote Wakeup,
30681 +                * unmask Remote Wakeup interrupt.
30682 +                */
30683 +               gintmsk.b.wkupintr = 1;
30684 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
30685 +                                0, gintmsk.d32);
30686 +       }
30687 +
30688 +       return 1;
30689 +}
30690 +
30691 +/**
30692 + * This interrupt indicates that a device has been disconnected from
30693 + * the root port.
30694 + */
30695 +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)
30696 +{
30697 +       gintsts_data_t gintsts;
30698 +
30699 +       DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
30700 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
30701 +                   op_state_str(core_if));
30702 +
30703 +/** @todo Consolidate this if statement. */
30704 +#ifndef DWC_HOST_ONLY
30705 +       if (core_if->op_state == B_HOST) {
30706 +               /* If in device mode Disconnect and stop the HCD, then
30707 +                * start the PCD. */
30708 +               DWC_SPINUNLOCK(core_if->lock);
30709 +               cil_hcd_disconnect(core_if);
30710 +               cil_pcd_start(core_if);
30711 +               DWC_SPINLOCK(core_if->lock);
30712 +               core_if->op_state = B_PERIPHERAL;
30713 +       } else if (dwc_otg_is_device_mode(core_if)) {
30714 +               gotgctl_data_t gotgctl = {.d32 = 0 };
30715 +               gotgctl.d32 =
30716 +                   DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
30717 +               if (gotgctl.b.hstsethnpen == 1) {
30718 +                       /* Do nothing, if HNP in process the OTG
30719 +                        * interrupt "Host Negotiation Detected"
30720 +                        * interrupt will do the mode switch.
30721 +                        */
30722 +               } else if (gotgctl.b.devhnpen == 0) {
30723 +                       /* If in device mode Disconnect and stop the HCD, then
30724 +                        * start the PCD. */
30725 +                       DWC_SPINUNLOCK(core_if->lock);
30726 +                       cil_hcd_disconnect(core_if);
30727 +                       cil_pcd_start(core_if);
30728 +                       DWC_SPINLOCK(core_if->lock);
30729 +                       core_if->op_state = B_PERIPHERAL;
30730 +               } else {
30731 +                       DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
30732 +               }
30733 +       } else {
30734 +               if (core_if->op_state == A_HOST) {
30735 +                       /* A-Cable still connected but device disconnected. */
30736 +                       cil_hcd_disconnect(core_if);
30737 +                       if (core_if->adp_enable) {
30738 +                               gpwrdn_data_t gpwrdn = { .d32 = 0 };
30739 +                               cil_hcd_stop(core_if);
30740 +                               /* Enable Power Down Logic */
30741 +                               gpwrdn.b.pmuintsel = 1;
30742 +                               gpwrdn.b.pmuactv = 1;
30743 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30744 +                                                gpwrdn, 0, gpwrdn.d32);
30745 +                               dwc_otg_adp_probe_start(core_if);
30746 +
30747 +                               /* Power off the core */
30748 +                               if (core_if->power_down == 2) {
30749 +                                       gpwrdn.d32 = 0;
30750 +                                       gpwrdn.b.pwrdnswtch = 1;
30751 +                                       DWC_MODIFY_REG32
30752 +                                           (&core_if->core_global_regs->gpwrdn,
30753 +                                            gpwrdn.d32, 0);
30754 +                               }
30755 +                       }
30756 +               }
30757 +       }
30758 +#endif
30759 +       /* Change to L3(OFF) state */
30760 +       core_if->lx_state = DWC_OTG_L3;
30761 +
30762 +       gintsts.d32 = 0;
30763 +       gintsts.b.disconnect = 1;
30764 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30765 +       return 1;
30766 +}
30767 +
30768 +/**
30769 + * This interrupt indicates that SUSPEND state has been detected on
30770 + * the USB.
30771 + *
30772 + * For HNP the USB Suspend interrupt signals the change from
30773 + * "a_peripheral" to "a_host".
30774 + *
30775 + * When power management is enabled the core will be put in low power
30776 + * mode.
30777 + */
30778 +int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
30779 +{
30780 +       dsts_data_t dsts;
30781 +       gintsts_data_t gintsts;
30782 +       dcfg_data_t dcfg;
30783 +
30784 +       DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
30785 +
30786 +       if (dwc_otg_is_device_mode(core_if)) {
30787 +               /* Check the Device status register to determine if the Suspend
30788 +                * state is active. */
30789 +               dsts.d32 =
30790 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
30791 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
30792 +               DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
30793 +                           "HWCFG4.power Optimize=%d\n",
30794 +                           dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
30795 +
30796 +#ifdef PARTIAL_POWER_DOWN
30797 +/** @todo Add a module parameter for power management. */
30798 +
30799 +               if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
30800 +                       pcgcctl_data_t power = {.d32 = 0 };
30801 +                       DWC_DEBUGPL(DBG_CIL, "suspend\n");
30802 +
30803 +                       power.b.pwrclmp = 1;
30804 +                       DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30805 +
30806 +                       power.b.rstpdwnmodule = 1;
30807 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30808 +
30809 +                       power.b.stoppclk = 1;
30810 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30811 +
30812 +               } else {
30813 +                       DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
30814 +               }
30815 +#endif
30816 +               /* PCD callback for suspend. Release the lock inside of callback function */
30817 +               cil_pcd_suspend(core_if);
30818 +               if (core_if->power_down == 2)
30819 +               {
30820 +                       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30821 +                       DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state);
30822 +                       DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr);
30823 +
30824 +                       if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30825 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
30826 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
30827 +                               gusbcfg_data_t gusbcfg = {.d32 = 0 };
30828 +
30829 +                               /* Change to L2(suspend) state */
30830 +                               core_if->lx_state = DWC_OTG_L2;
30831 +
30832 +                               /* Clear interrupt in gintsts */
30833 +                               gintsts.d32 = 0;
30834 +                               gintsts.b.usbsuspend = 1;
30835 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
30836 +                                               gintsts, gintsts.d32);
30837 +                               DWC_PRINTF("Start of hibernation completed\n");
30838 +                               dwc_otg_save_global_regs(core_if);
30839 +                               dwc_otg_save_dev_regs(core_if);
30840 +
30841 +                               gusbcfg.d32 =
30842 +                                   DWC_READ_REG32(&core_if->core_global_regs->
30843 +                                                  gusbcfg);
30844 +                               if (gusbcfg.b.ulpi_utmi_sel == 1) {
30845 +                                       /* ULPI interface */
30846 +                                       /* Suspend the Phy Clock */
30847 +                                       pcgcctl.d32 = 0;
30848 +                                       pcgcctl.b.stoppclk = 1;
30849 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30850 +                                                        pcgcctl.d32);
30851 +                                       dwc_udelay(10);
30852 +                                       gpwrdn.b.pmuactv = 1;
30853 +                                       DWC_MODIFY_REG32(&core_if->
30854 +                                                        core_global_regs->
30855 +                                                        gpwrdn, 0, gpwrdn.d32);
30856 +                               } else {
30857 +                                       /* UTMI+ Interface */
30858 +                                       gpwrdn.b.pmuactv = 1;
30859 +                                       DWC_MODIFY_REG32(&core_if->
30860 +                                                        core_global_regs->
30861 +                                                        gpwrdn, 0, gpwrdn.d32);
30862 +                                       dwc_udelay(10);
30863 +                                       pcgcctl.b.stoppclk = 1;
30864 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30865 +                                                        pcgcctl.d32);
30866 +                                       dwc_udelay(10);
30867 +                               }
30868 +
30869 +                               /* Set flag to indicate that we are in hibernation */
30870 +                               core_if->hibernation_suspend = 1;
30871 +                               /* Enable interrupts from wake up logic */
30872 +                               gpwrdn.d32 = 0;
30873 +                               gpwrdn.b.pmuintsel = 1;
30874 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30875 +                                                gpwrdn, 0, gpwrdn.d32);
30876 +                               dwc_udelay(10);
30877 +
30878 +                               /* Unmask device mode interrupts in GPWRDN */
30879 +                               gpwrdn.d32 = 0;
30880 +                               gpwrdn.b.rst_det_msk = 1;
30881 +                               gpwrdn.b.lnstchng_msk = 1;
30882 +                               gpwrdn.b.sts_chngint_msk = 1;
30883 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30884 +                                                gpwrdn, 0, gpwrdn.d32);
30885 +                               dwc_udelay(10);
30886 +
30887 +                               /* Enable Power Down Clamp */
30888 +                               gpwrdn.d32 = 0;
30889 +                               gpwrdn.b.pwrdnclmp = 1;
30890 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30891 +                                                gpwrdn, 0, gpwrdn.d32);
30892 +                               dwc_udelay(10);
30893 +
30894 +                               /* Switch off VDD */
30895 +                               gpwrdn.d32 = 0;
30896 +                               gpwrdn.b.pwrdnswtch = 1;
30897 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30898 +                                                gpwrdn, 0, gpwrdn.d32);
30899 +
30900 +                               /* Save gpwrdn register for further usage if stschng interrupt */
30901 +                               core_if->gr_backup->gpwrdn_local =
30902 +                                                       DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30903 +                               DWC_PRINTF("Hibernation completed\n");
30904 +
30905 +                               return 1;
30906 +                       }
30907 +               } else if (core_if->power_down == 3) {
30908 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30909 +                       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30910 +                       DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state);
30911 +                       DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr);
30912 +
30913 +                       if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30914 +                               DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n");
30915 +                               core_if->xhib = 1;
30916 +
30917 +                               /* Clear interrupt in gintsts */
30918 +                               gintsts.d32 = 0;
30919 +                               gintsts.b.usbsuspend = 1;
30920 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
30921 +                                       gintsts, gintsts.d32);
30922 +
30923 +                               dwc_otg_save_global_regs(core_if);
30924 +                               dwc_otg_save_dev_regs(core_if);
30925 +
30926 +                               /* Wait for 10 PHY clocks */
30927 +                               dwc_udelay(10);
30928 +
30929 +                               /* Program GPIO register while entering to xHib */
30930 +                               DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1);
30931 +
30932 +                               pcgcctl.b.enbl_extnd_hiber = 1;
30933 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30934 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30935 +
30936 +                               pcgcctl.d32 = 0;
30937 +                               pcgcctl.b.extnd_hiber_pwrclmp = 1;
30938 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30939 +
30940 +                               pcgcctl.d32 = 0;
30941 +                               pcgcctl.b.extnd_hiber_switch = 1;
30942 +                               core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30943 +                               core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32;
30944 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30945 +
30946 +                               DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n");
30947 +
30948 +                               return 1;
30949 +                       }
30950 +               }
30951 +       } else {
30952 +               if (core_if->op_state == A_PERIPHERAL) {
30953 +                       DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
30954 +                       /* Clear the a_peripheral flag, back to a_host. */
30955 +                       DWC_SPINUNLOCK(core_if->lock);
30956 +                       cil_pcd_stop(core_if);
30957 +                       cil_hcd_start(core_if);
30958 +                       DWC_SPINLOCK(core_if->lock);
30959 +                       core_if->op_state = A_HOST;
30960 +               }
30961 +       }
30962 +
30963 +       /* Change to L2(suspend) state */
30964 +       core_if->lx_state = DWC_OTG_L2;
30965 +
30966 +       /* Clear interrupt */
30967 +       gintsts.d32 = 0;
30968 +       gintsts.b.usbsuspend = 1;
30969 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30970 +
30971 +       return 1;
30972 +}
30973 +
30974 +static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if)
30975 +{
30976 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30977 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30978 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
30979 +
30980 +       dwc_udelay(10);
30981 +
30982 +       /* Program GPIO register while entering to xHib */
30983 +       DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0);
30984 +
30985 +       pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl;
30986 +       pcgcctl.b.extnd_hiber_pwrclmp = 0;
30987 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30988 +       dwc_udelay(10);
30989 +
30990 +       gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn;
30991 +       gpwrdn.b.restore = 1;
30992 +       DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32);
30993 +       dwc_udelay(10);
30994 +
30995 +       restore_lpm_i2c_regs(core_if);
30996 +
30997 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30998 +       pcgcctl.b.max_xcvrselect = 1;
30999 +       pcgcctl.b.ess_reg_restored = 0;
31000 +       pcgcctl.b.extnd_hiber_switch = 0;
31001 +       pcgcctl.b.extnd_hiber_pwrclmp = 0;
31002 +       pcgcctl.b.enbl_extnd_hiber = 1;
31003 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
31004 +
31005 +       gahbcfg.d32 = core_if->gr_backup->gahbcfg_local;
31006 +       gahbcfg.b.glblintrmsk = 1;
31007 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
31008 +
31009 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
31010 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16);
31011 +
31012 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
31013 +                       core_if->gr_backup->gusbcfg_local);
31014 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
31015 +                       core_if->dr_backup->dcfg);
31016 +
31017 +       pcgcctl.d32 = 0;
31018 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
31019 +       pcgcctl.b.max_xcvrselect = 1;
31020 +       pcgcctl.d32 |= 0x608;
31021 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
31022 +       dwc_udelay(10);
31023 +
31024 +       pcgcctl.d32 = 0;
31025 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
31026 +       pcgcctl.b.max_xcvrselect = 1;
31027 +       pcgcctl.b.ess_reg_restored = 1;
31028 +       pcgcctl.b.enbl_extnd_hiber = 1;
31029 +       pcgcctl.b.rstpdwnmodule = 1;
31030 +       pcgcctl.b.restoremode = 1;
31031 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
31032 +
31033 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
31034 +
31035 +       return 1;
31036 +}
31037 +
31038 +#ifdef CONFIG_USB_DWC_OTG_LPM
31039 +/**
31040 + * This function hadles LPM transaction received interrupt.
31041 + */
31042 +static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
31043 +{
31044 +       glpmcfg_data_t lpmcfg;
31045 +       gintsts_data_t gintsts;
31046 +
31047 +       if (!core_if->core_params->lpm_enable) {
31048 +               DWC_PRINTF("Unexpected LPM interrupt\n");
31049 +       }
31050 +
31051 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
31052 +       DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
31053 +
31054 +       if (dwc_otg_is_host_mode(core_if)) {
31055 +               cil_hcd_sleep(core_if);
31056 +       } else {
31057 +               lpmcfg.b.hird_thres |= (1 << 4);
31058 +               DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
31059 +                               lpmcfg.d32);
31060 +       }
31061 +
31062 +       /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */
31063 +       dwc_udelay(10);
31064 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
31065 +       if (lpmcfg.b.prt_sleep_sts) {
31066 +               /* Save the current state */
31067 +               core_if->lx_state = DWC_OTG_L1;
31068 +       }
31069 +
31070 +       /* Clear interrupt  */
31071 +       gintsts.d32 = 0;
31072 +       gintsts.b.lpmtranrcvd = 1;
31073 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
31074 +       return 1;
31075 +}
31076 +#endif /* CONFIG_USB_DWC_OTG_LPM */
31077 +
31078 +/**
31079 + * This function returns the Core Interrupt register.
31080 + */
31081 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
31082 +{
31083 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
31084 +       gintsts_data_t gintsts;
31085 +       gintmsk_data_t gintmsk;
31086 +       gintmsk_data_t gintmsk_common = {.d32 = 0 };
31087 +       gintmsk_common.b.wkupintr = 1;
31088 +       gintmsk_common.b.sessreqintr = 1;
31089 +       gintmsk_common.b.conidstschng = 1;
31090 +       gintmsk_common.b.otgintr = 1;
31091 +       gintmsk_common.b.modemismatch = 1;
31092 +       gintmsk_common.b.disconnect = 1;
31093 +       gintmsk_common.b.usbsuspend = 1;
31094 +#ifdef CONFIG_USB_DWC_OTG_LPM
31095 +       gintmsk_common.b.lpmtranrcvd = 1;
31096 +#endif
31097 +       gintmsk_common.b.restoredone = 1;
31098 +       /** @todo: The port interrupt occurs while in device
31099 +         * mode. Added code to CIL to clear the interrupt for now!
31100 +         */
31101 +       gintmsk_common.b.portintr = 1;
31102 +
31103 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
31104 +       gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
31105 +       gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
31106 +
31107 +#ifdef DEBUG
31108 +       /* if any common interrupts set */
31109 +       if (gintsts.d32 & gintmsk_common.d32) {
31110 +               DWC_DEBUGPL(DBG_ANY, "gintsts=%08x  gintmsk=%08x\n",
31111 +                           gintsts.d32, gintmsk.d32);
31112 +       }
31113 +#endif
31114 +       if (gahbcfg.b.glblintrmsk)      
31115 +               return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
31116 +       else
31117 +               return 0;
31118 +
31119 +}
31120 +
31121 +/* MACRO for clearing interupt bits in GPWRDN register */
31122 +#define CLEAR_GPWRDN_INTR(__core_if,__intr) \
31123 +do { \
31124 +               gpwrdn_data_t gpwrdn = {.d32=0}; \
31125 +               gpwrdn.b.__intr = 1; \
31126 +               DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \
31127 +               0, gpwrdn.d32); \
31128 +} while (0)
31129 +
31130 +/**
31131 + * Common interrupt handler.
31132 + *
31133 + * The common interrupts are those that occur in both Host and Device mode.
31134 + * This handler handles the following interrupts:
31135 + * - Mode Mismatch Interrupt
31136 + * - Disconnect Interrupt
31137 + * - OTG Interrupt
31138 + * - Connector ID Status Change Interrupt
31139 + * - Session Request Interrupt.
31140 + * - Resume / Remote Wakeup Detected Interrupt.
31141 + * - LPM Transaction Received Interrupt
31142 + * - ADP Transaction Received Interrupt
31143 + *
31144 + */
31145 +int32_t dwc_otg_handle_common_intr(void *dev)
31146 +{
31147 +       int retval = 0;
31148 +       gintsts_data_t gintsts;
31149 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
31150 +       dwc_otg_device_t *otg_dev = dev;
31151 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
31152 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
31153 +       if (dwc_otg_is_device_mode(core_if))
31154 +               core_if->frame_num = dwc_otg_get_frame_number(core_if);
31155 +               
31156 +       if (core_if->lock)
31157 +               DWC_SPINLOCK(core_if->lock);
31158 +
31159 +       if (core_if->power_down == 3 && core_if->xhib == 1) {
31160 +               DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n");
31161 +               retval |= dwc_otg_handle_xhib_exit_intr(core_if);
31162 +               core_if->xhib = 2;
31163 +               if (core_if->lock)
31164 +                       DWC_SPINUNLOCK(core_if->lock);
31165 +
31166 +               return retval;
31167 +       }
31168 +
31169 +       if (core_if->hibernation_suspend <= 0) {
31170 +               gintsts.d32 = dwc_otg_read_common_intr(core_if);
31171 +
31172 +               if (gintsts.b.modemismatch) {
31173 +                       retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
31174 +               }
31175 +               if (gintsts.b.otgintr) {
31176 +                       retval |= dwc_otg_handle_otg_intr(core_if);
31177 +               }
31178 +               if (gintsts.b.conidstschng) {
31179 +                       retval |=
31180 +                           dwc_otg_handle_conn_id_status_change_intr(core_if);
31181 +               }
31182 +               if (gintsts.b.disconnect) {
31183 +                       retval |= dwc_otg_handle_disconnect_intr(core_if);
31184 +               }
31185 +               if (gintsts.b.sessreqintr) {
31186 +                       retval |= dwc_otg_handle_session_req_intr(core_if);
31187 +               }
31188 +               if (gintsts.b.wkupintr) {
31189 +                       retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
31190 +               }
31191 +               if (gintsts.b.usbsuspend) {
31192 +                       retval |= dwc_otg_handle_usb_suspend_intr(core_if);
31193 +               }
31194 +#ifdef CONFIG_USB_DWC_OTG_LPM
31195 +               if (gintsts.b.lpmtranrcvd) {
31196 +                       retval |= dwc_otg_handle_lpm_intr(core_if);
31197 +               }
31198 +#endif
31199 +               if (gintsts.b.restoredone) {
31200 +                       gintsts.d32 = 0;
31201 +                       if (core_if->power_down == 2)
31202 +                               core_if->hibernation_suspend = -1;
31203 +                       else if (core_if->power_down == 3 && core_if->xhib == 2) {
31204 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
31205 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
31206 +                               dctl_data_t dctl = {.d32 = 0 };
31207 +
31208 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
31209 +                                               gintsts, 0xFFFFFFFF);
31210 +
31211 +                               DWC_DEBUGPL(DBG_ANY,
31212 +                                           "RESTORE DONE generated\n");
31213 +
31214 +                               gpwrdn.b.restore = 1;
31215 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
31216 +                               dwc_udelay(10);
31217 +
31218 +                               pcgcctl.b.rstpdwnmodule = 1;
31219 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
31220 +
31221 +                               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local);
31222 +                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg);
31223 +                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl);
31224 +                               dwc_udelay(50);
31225 +
31226 +                               dctl.b.pwronprgdone = 1;
31227 +                               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
31228 +                               dwc_udelay(10);
31229 +
31230 +                               dwc_otg_restore_global_regs(core_if);
31231 +                               dwc_otg_restore_dev_regs(core_if, 0);
31232 +
31233 +                               dctl.d32 = 0;
31234 +                               dctl.b.pwronprgdone = 1;
31235 +                               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
31236 +                               dwc_udelay(10);
31237 +
31238 +                               pcgcctl.d32 = 0;
31239 +                               pcgcctl.b.enbl_extnd_hiber = 1;
31240 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
31241 +
31242 +                               /* The core will be in ON STATE */
31243 +                               core_if->lx_state = DWC_OTG_L0;
31244 +                               core_if->xhib = 0;
31245 +
31246 +                               DWC_SPINUNLOCK(core_if->lock);
31247 +                               if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
31248 +                                       core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
31249 +                               }
31250 +                               DWC_SPINLOCK(core_if->lock);
31251 +
31252 +                       }
31253 +
31254 +                       gintsts.b.restoredone = 1;
31255 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
31256 +                       DWC_PRINTF(" --Restore done interrupt received-- \n");
31257 +                       retval |= 1;
31258 +               }
31259 +               if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
31260 +                       /* The port interrupt occurs while in device mode with HPRT0
31261 +                        * Port Enable/Disable.
31262 +                        */
31263 +                       gintsts.d32 = 0;
31264 +                       gintsts.b.portintr = 1;
31265 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
31266 +                       retval |= 1;
31267 +
31268 +               }
31269 +       } else {
31270 +               DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
31271 +
31272 +               if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {
31273 +                       CLEAR_GPWRDN_INTR(core_if, disconn_det);
31274 +                       if (gpwrdn.b.linestate == 0) {
31275 +                               dwc_otg_handle_pwrdn_disconnect_intr(core_if);
31276 +                       } else {
31277 +                               DWC_PRINTF("Disconnect detected while linestate is not 0\n");
31278 +                       }
31279 +
31280 +                       retval |= 1;
31281 +               }
31282 +               if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {
31283 +                       CLEAR_GPWRDN_INTR(core_if, lnstschng);
31284 +                       /* remote wakeup from hibernation */
31285 +                       if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {
31286 +                               dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if);
31287 +                       } else {
31288 +                               DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate);
31289 +                       }
31290 +                       retval |= 1;
31291 +               }
31292 +               if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {
31293 +                       CLEAR_GPWRDN_INTR(core_if, rst_det);
31294 +                       if (gpwrdn.b.linestate == 0) {
31295 +                               DWC_PRINTF("Reset detected\n");
31296 +                               retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1);
31297 +                       }
31298 +               }
31299 +               if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {
31300 +                       CLEAR_GPWRDN_INTR(core_if, srp_det);
31301 +                       dwc_otg_handle_pwrdn_srp_intr(core_if);
31302 +                       retval |= 1;
31303 +               }
31304 +       }
31305 +       /* Handle ADP interrupt here */
31306 +       if (gpwrdn.b.adp_int) {
31307 +               DWC_PRINTF("ADP interrupt\n");
31308 +               CLEAR_GPWRDN_INTR(core_if, adp_int);
31309 +               dwc_otg_adp_handle_intr(core_if);
31310 +               retval |= 1;
31311 +       }
31312 +       if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
31313 +               DWC_PRINTF("STS CHNG interrupt asserted\n");
31314 +               CLEAR_GPWRDN_INTR(core_if, sts_chngint);
31315 +               dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
31316 +
31317 +               retval |= 1;
31318 +       }
31319 +       if (core_if->lock)
31320 +               DWC_SPINUNLOCK(core_if->lock);
31321 +
31322 +       return retval;
31323 +}
31324 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
31325 new file mode 100644
31326 index 0000000..10b68c4
31327 --- /dev/null
31328 +++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
31329 @@ -0,0 +1,705 @@
31330 +/* ==========================================================================
31331 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
31332 + * $Revision: #13 $
31333 + * $Date: 2012/08/10 $
31334 + * $Change: 2047372 $
31335 + *
31336 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31337 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31338 + * otherwise expressly agreed to in writing between Synopsys and you.
31339 + *
31340 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31341 + * any End User Software License Agreement or Agreement for Licensed Product
31342 + * with Synopsys or any supplement thereto. You are permitted to use and
31343 + * redistribute this Software in source and binary forms, with or without
31344 + * modification, provided that redistributions of source code must retain this
31345 + * notice. You may not view, use, disclose, copy or distribute this file or
31346 + * any information contained herein except pursuant to this license grant from
31347 + * Synopsys. If you do not agree with this notice, including the disclaimer
31348 + * below, then you are not authorized to use the Software.
31349 + *
31350 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31351 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31352 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31353 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31354 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31355 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31356 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31357 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31358 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31359 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31360 + * DAMAGE.
31361 + * ========================================================================== */
31362 +#if !defined(__DWC_CORE_IF_H__)
31363 +#define __DWC_CORE_IF_H__
31364 +
31365 +#include "dwc_os.h"
31366 +
31367 +/** @file
31368 + * This file defines DWC_OTG Core API
31369 + */
31370 +
31371 +struct dwc_otg_core_if;
31372 +typedef struct dwc_otg_core_if dwc_otg_core_if_t;
31373 +
31374 +/** Maximum number of Periodic FIFOs */
31375 +#define MAX_PERIO_FIFOS 15
31376 +/** Maximum number of Periodic FIFOs */
31377 +#define MAX_TX_FIFOS 15
31378 +
31379 +/** Maximum number of Endpoints/HostChannels */
31380 +#define MAX_EPS_CHANNELS 16
31381 +
31382 +extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);
31383 +extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);
31384 +extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if);
31385 +
31386 +extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if);
31387 +extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if);
31388 +
31389 +extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if);
31390 +extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if);
31391 +
31392 +extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);
31393 +
31394 +/** This function should be called on every hardware interrupt. */
31395 +extern int32_t dwc_otg_handle_common_intr(void *otg_dev);
31396 +
31397 +/** @name OTG Core Parameters */
31398 +/** @{ */
31399 +
31400 +/**
31401 + * Specifies the OTG capabilities. The driver will automatically
31402 + * detect the value for this parameter if none is specified.
31403 + * 0 - HNP and SRP capable (default)
31404 + * 1 - SRP Only capable
31405 + * 2 - No HNP/SRP capable
31406 + */
31407 +extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val);
31408 +extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if);
31409 +#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
31410 +#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
31411 +#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
31412 +#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
31413 +
31414 +extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val);
31415 +extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if);
31416 +#define dwc_param_opt_default 1
31417 +
31418 +/**
31419 + * Specifies whether to use slave or DMA mode for accessing the data
31420 + * FIFOs. The driver will automatically detect the value for this
31421 + * parameter if none is specified.
31422 + * 0 - Slave
31423 + * 1 - DMA (default, if available)
31424 + */
31425 +extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if,
31426 +                                       int32_t val);
31427 +extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if);
31428 +#define dwc_param_dma_enable_default 1
31429 +
31430 +/**
31431 + * When DMA mode is enabled specifies whether to use
31432 + * address DMA or DMA Descritor mode for accessing the data
31433 + * FIFOs in device mode. The driver will automatically detect
31434 + * the value for this parameter if none is specified.
31435 + * 0 - address DMA
31436 + * 1 - DMA Descriptor(default, if available)
31437 + */
31438 +extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,
31439 +                                            int32_t val);
31440 +extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);
31441 +//#define dwc_param_dma_desc_enable_default 1
31442 +#define dwc_param_dma_desc_enable_default 0 // Broadcom BCM2708
31443 +
31444 +/** The DMA Burst size (applicable only for External DMA
31445 + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
31446 + */
31447 +extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if,
31448 +                                           int32_t val);
31449 +extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if);
31450 +#define dwc_param_dma_burst_size_default 32
31451 +
31452 +/**
31453 + * Specifies the maximum speed of operation in host and device mode.
31454 + * The actual speed depends on the speed of the attached device and
31455 + * the value of phy_type. The actual speed depends on the speed of the
31456 + * attached device.
31457 + * 0 - High Speed (default)
31458 + * 1 - Full Speed
31459 + */
31460 +extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val);
31461 +extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if);
31462 +#define dwc_param_speed_default 0
31463 +#define DWC_SPEED_PARAM_HIGH 0
31464 +#define DWC_SPEED_PARAM_FULL 1
31465 +
31466 +/** Specifies whether low power mode is supported when attached
31467 + *     to a Full Speed or Low Speed device in host mode.
31468 + * 0 - Don't support low power mode (default)
31469 + * 1 - Support low power mode
31470 + */
31471 +extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
31472 +                                                         core_if, int32_t val);
31473 +extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
31474 +                                                             * core_if);
31475 +#define dwc_param_host_support_fs_ls_low_power_default 0
31476 +
31477 +/** Specifies the PHY clock rate in low power mode when connected to a
31478 + * Low Speed device in host mode. This parameter is applicable only if
31479 + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
31480 + * then defaults to 6 MHZ otherwise 48 MHZ.
31481 + *
31482 + * 0 - 48 MHz
31483 + * 1 - 6 MHz
31484 + */
31485 +extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31486 +                                                      core_if, int32_t val);
31487 +extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31488 +                                                          core_if);
31489 +#define dwc_param_host_ls_low_power_phy_clk_default 0
31490 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
31491 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
31492 +
31493 +/**
31494 + * 0 - Use cC FIFO size parameters
31495 + * 1 - Allow dynamic FIFO sizing (default)
31496 + */
31497 +extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
31498 +                                                int32_t val);
31499 +extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
31500 +                                                    core_if);
31501 +#define dwc_param_enable_dynamic_fifo_default 1
31502 +
31503 +/** Total number of 4-byte words in the data FIFO memory. This
31504 + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
31505 + * Tx FIFOs.
31506 + * 32 to 32768 (default 8192)
31507 + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
31508 + */
31509 +extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if,
31510 +                                           int32_t val);
31511 +extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if);
31512 +//#define dwc_param_data_fifo_size_default 8192
31513 +#define dwc_param_data_fifo_size_default 0xFF0 // Broadcom BCM2708
31514 +
31515 +/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
31516 + * FIFO sizing is enabled.
31517 + * 16 to 32768 (default 1064)
31518 + */
31519 +extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if,
31520 +                                             int32_t val);
31521 +extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if);
31522 +#define dwc_param_dev_rx_fifo_size_default 1064
31523 +
31524 +/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
31525 + * when dynamic FIFO sizing is enabled.
31526 + * 16 to 32768 (default 1024)
31527 + */
31528 +extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31529 +                                                    core_if, int32_t val);
31530 +extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31531 +                                                        core_if);
31532 +#define dwc_param_dev_nperio_tx_fifo_size_default 1024
31533 +
31534 +/** Number of 4-byte words in each of the periodic Tx FIFOs in device
31535 + * mode when dynamic FIFO sizing is enabled.
31536 + * 4 to 768 (default 256)
31537 + */
31538 +extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
31539 +                                                   int32_t val, int fifo_num);
31540 +extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
31541 +                                                       core_if, int fifo_num);
31542 +#define dwc_param_dev_perio_tx_fifo_size_default 256
31543 +
31544 +/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
31545 + * FIFO sizing is enabled.
31546 + * 16 to 32768 (default 1024)
31547 + */
31548 +extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
31549 +                                              int32_t val);
31550 +extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);
31551 +//#define dwc_param_host_rx_fifo_size_default 1024
31552 +#define dwc_param_host_rx_fifo_size_default 774 // Broadcom BCM2708
31553 +
31554 +/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
31555 + * when Dynamic FIFO sizing is enabled in the core.
31556 + * 16 to 32768 (default 1024)
31557 + */
31558 +extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31559 +                                                     core_if, int32_t val);
31560 +extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31561 +                                                         core_if);
31562 +//#define dwc_param_host_nperio_tx_fifo_size_default 1024
31563 +#define dwc_param_host_nperio_tx_fifo_size_default 0x100 // Broadcom BCM2708
31564 +
31565 +/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
31566 + * FIFO sizing is enabled.
31567 + * 16 to 32768 (default 1024)
31568 + */
31569 +extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31570 +                                                    core_if, int32_t val);
31571 +extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31572 +                                                        core_if);
31573 +//#define dwc_param_host_perio_tx_fifo_size_default 1024
31574 +#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708
31575 +
31576 +/** The maximum transfer size supported in bytes.
31577 + * 2047 to 65,535  (default 65,535)
31578 + */
31579 +extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
31580 +                                              int32_t val);
31581 +extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if);
31582 +#define dwc_param_max_transfer_size_default 65535
31583 +
31584 +/** The maximum number of packets in a transfer.
31585 + * 15 to 511  (default 511)
31586 + */
31587 +extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if,
31588 +                                             int32_t val);
31589 +extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if);
31590 +#define dwc_param_max_packet_count_default 511
31591 +
31592 +/** The number of host channel registers to use.
31593 + * 1 to 16 (default 12)
31594 + * Note: The FPGA configuration supports a maximum of 12 host channels.
31595 + */
31596 +extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,
31597 +                                          int32_t val);
31598 +extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);
31599 +//#define dwc_param_host_channels_default 12
31600 +#define dwc_param_host_channels_default 8 // Broadcom BCM2708
31601 +
31602 +/** The number of endpoints in addition to EP0 available for device
31603 + * mode operations.
31604 + * 1 to 15 (default 6 IN and OUT)
31605 + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
31606 + * endpoints in addition to EP0.
31607 + */
31608 +extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,
31609 +                                          int32_t val);
31610 +extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);
31611 +#define dwc_param_dev_endpoints_default 6
31612 +
31613 +/**
31614 + * Specifies the type of PHY interface to use. By default, the driver
31615 + * will automatically detect the phy_type.
31616 + *
31617 + * 0 - Full Speed PHY
31618 + * 1 - UTMI+ (default)
31619 + * 2 - ULPI
31620 + */
31621 +extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val);
31622 +extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if);
31623 +#define DWC_PHY_TYPE_PARAM_FS 0
31624 +#define DWC_PHY_TYPE_PARAM_UTMI 1
31625 +#define DWC_PHY_TYPE_PARAM_ULPI 2
31626 +#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
31627 +
31628 +/**
31629 + * Specifies the UTMI+ Data Width. This parameter is
31630 + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
31631 + * PHY_TYPE, this parameter indicates the data width between
31632 + * the MAC and the ULPI Wrapper.) Also, this parameter is
31633 + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
31634 + * to "8 and 16 bits", meaning that the core has been
31635 + * configured to work at either data path width.
31636 + *
31637 + * 8 or 16 bits (default 16)
31638 + */
31639 +extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if,
31640 +                                           int32_t val);
31641 +extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if);
31642 +//#define dwc_param_phy_utmi_width_default 16
31643 +#define dwc_param_phy_utmi_width_default 8 // Broadcom BCM2708 
31644 +
31645 +/**
31646 + * Specifies whether the ULPI operates at double or single
31647 + * data rate. This parameter is only applicable if PHY_TYPE is
31648 + * ULPI.
31649 + *
31650 + * 0 - single data rate ULPI interface with 8 bit wide data
31651 + * bus (default)
31652 + * 1 - double data rate ULPI interface with 4 bit wide data
31653 + * bus
31654 + */
31655 +extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if,
31656 +                                         int32_t val);
31657 +extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if);
31658 +#define dwc_param_phy_ulpi_ddr_default 0
31659 +
31660 +/**
31661 + * Specifies whether to use the internal or external supply to
31662 + * drive the vbus with a ULPI phy.
31663 + */
31664 +extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
31665 +                                              int32_t val);
31666 +extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if);
31667 +#define DWC_PHY_ULPI_INTERNAL_VBUS 0
31668 +#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
31669 +#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
31670 +
31671 +/**
31672 + * Specifies whether to use the I2Cinterface for full speed PHY. This
31673 + * parameter is only applicable if PHY_TYPE is FS.
31674 + * 0 - No (default)
31675 + * 1 - Yes
31676 + */
31677 +extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if,
31678 +                                       int32_t val);
31679 +extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if);
31680 +#define dwc_param_i2c_enable_default 0
31681 +
31682 +extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if,
31683 +                                       int32_t val);
31684 +extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if);
31685 +#define dwc_param_ulpi_fs_ls_default 0
31686 +
31687 +extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val);
31688 +extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if);
31689 +#define dwc_param_ts_dline_default 0
31690 +
31691 +/**
31692 + * Specifies whether dedicated transmit FIFOs are
31693 + * enabled for non periodic IN endpoints in device mode
31694 + * 0 - No
31695 + * 1 - Yes
31696 + */
31697 +extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
31698 +                                                int32_t val);
31699 +extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
31700 +                                                    core_if);
31701 +#define dwc_param_en_multiple_tx_fifo_default 1
31702 +
31703 +/** Number of 4-byte words in each of the Tx FIFOs in device
31704 + * mode when dynamic FIFO sizing is enabled.
31705 + * 4 to 768 (default 256)
31706 + */
31707 +extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31708 +                                             int fifo_num, int32_t val);
31709 +extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31710 +                                                 int fifo_num);
31711 +#define dwc_param_dev_tx_fifo_size_default 768
31712 +
31713 +/** Thresholding enable flag-
31714 + * bit 0 - enable non-ISO Tx thresholding
31715 + * bit 1 - enable ISO Tx thresholding
31716 + * bit 2 - enable Rx thresholding
31717 + */
31718 +extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val);
31719 +extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num);
31720 +#define dwc_param_thr_ctl_default 0
31721 +
31722 +/** Thresholding length for Tx
31723 + * FIFOs in 32 bit DWORDs
31724 + */
31725 +extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if,
31726 +                                          int32_t val);
31727 +extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if);
31728 +#define dwc_param_tx_thr_length_default 64
31729 +
31730 +/** Thresholding length for Rx
31731 + *     FIFOs in 32 bit DWORDs
31732 + */
31733 +extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if,
31734 +                                          int32_t val);
31735 +extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if);
31736 +#define dwc_param_rx_thr_length_default 64
31737 +
31738 +/**
31739 + * Specifies whether LPM (Link Power Management) support is enabled
31740 + */
31741 +extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if,
31742 +                                       int32_t val);
31743 +extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if);
31744 +#define dwc_param_lpm_enable_default 1
31745 +
31746 +/**
31747 + * Specifies whether PTI enhancement is enabled
31748 + */
31749 +extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if,
31750 +                                       int32_t val);
31751 +extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if);
31752 +#define dwc_param_pti_enable_default 0
31753 +
31754 +/**
31755 + * Specifies whether MPI enhancement is enabled
31756 + */
31757 +extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if,
31758 +                                       int32_t val);
31759 +extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if);
31760 +#define dwc_param_mpi_enable_default 0
31761 +
31762 +/**
31763 + * Specifies whether ADP capability is enabled
31764 + */
31765 +extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if,
31766 +                                       int32_t val);
31767 +extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if);
31768 +#define dwc_param_adp_enable_default 0
31769 +
31770 +/**
31771 + * Specifies whether IC_USB capability is enabled
31772 + */
31773 +
31774 +extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,
31775 +                                       int32_t val);
31776 +extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if);
31777 +#define dwc_param_ic_usb_cap_default 0
31778 +
31779 +extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if,
31780 +                                          int32_t val);
31781 +extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if);
31782 +#define dwc_param_ahb_thr_ratio_default 0
31783 +
31784 +extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if,
31785 +                                       int32_t val);
31786 +extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if);
31787 +#define dwc_param_power_down_default 0
31788 +
31789 +extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if,
31790 +                                       int32_t val);
31791 +extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if);
31792 +#define dwc_param_reload_ctl_default 0
31793 +
31794 +extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if,
31795 +                                                                               int32_t val);
31796 +extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if);
31797 +#define dwc_param_dev_out_nak_default 0
31798 +
31799 +extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if,
31800 +                                                                                int32_t val);
31801 +extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if);
31802 +#define dwc_param_cont_on_bna_default 0
31803 +
31804 +extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if,
31805 +                                                                                int32_t val);
31806 +extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if);
31807 +#define dwc_param_ahb_single_default 0
31808 +
31809 +extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val);
31810 +extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if);
31811 +#define dwc_param_otg_ver_default 0
31812 +
31813 +/** @} */
31814 +
31815 +/** @name Access to registers and bit-fields */
31816 +
31817 +/**
31818 + * Dump core registers and SPRAM
31819 + */
31820 +extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if);
31821 +extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if);
31822 +extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if);
31823 +extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if);
31824 +
31825 +/**
31826 + * Get host negotiation status.
31827 + */
31828 +extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if);
31829 +
31830 +/**
31831 + * Get srp status
31832 + */
31833 +extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if);
31834 +
31835 +/**
31836 + * Set hnpreq bit in the GOTGCTL register.
31837 + */
31838 +extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val);
31839 +
31840 +/**
31841 + * Get Content of SNPSID register.
31842 + */
31843 +extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if);
31844 +
31845 +/**
31846 + * Get current mode.
31847 + * Returns 0 if in device mode, and 1 if in host mode.
31848 + */
31849 +extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if);
31850 +
31851 +/**
31852 + * Get value of hnpcapable field in the GUSBCFG register
31853 + */
31854 +extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if);
31855 +/**
31856 + * Set value of hnpcapable field in the GUSBCFG register
31857 + */
31858 +extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31859 +
31860 +/**
31861 + * Get value of srpcapable field in the GUSBCFG register
31862 + */
31863 +extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if);
31864 +/**
31865 + * Set value of srpcapable field in the GUSBCFG register
31866 + */
31867 +extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31868 +
31869 +/**
31870 + * Get value of devspeed field in the DCFG register
31871 + */
31872 +extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if);
31873 +/**
31874 + * Set value of devspeed field in the DCFG register
31875 + */
31876 +extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val);
31877 +
31878 +/**
31879 + * Get the value of busconnected field from the HPRT0 register
31880 + */
31881 +extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if);
31882 +
31883 +/**
31884 + * Gets the device enumeration Speed.
31885 + */
31886 +extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if);
31887 +
31888 +/**
31889 + * Get value of prtpwr field from the HPRT0 register
31890 + */
31891 +extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if);
31892 +
31893 +/**
31894 + * Get value of flag indicating core state - hibernated or not
31895 + */
31896 +extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if);
31897 +
31898 +/**
31899 + * Set value of prtpwr field from the HPRT0 register
31900 + */
31901 +extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val);
31902 +
31903 +/**
31904 + * Get value of prtsusp field from the HPRT0 regsiter
31905 + */
31906 +extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if);
31907 +/**
31908 + * Set value of prtpwr field from the HPRT0 register
31909 + */
31910 +extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val);
31911 +
31912 +/**
31913 + * Get value of ModeChTimEn field from the HCFG regsiter
31914 + */
31915 +extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if);
31916 +/**
31917 + * Set value of ModeChTimEn field from the HCFG regsiter
31918 + */
31919 +extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val);
31920 +
31921 +/**
31922 + * Get value of Fram Interval field from the HFIR regsiter
31923 + */
31924 +extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if);
31925 +/**
31926 + * Set value of Frame Interval field from the HFIR regsiter
31927 + */
31928 +extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val);
31929 +
31930 +/**
31931 + * Set value of prtres field from the HPRT0 register
31932 + *FIXME Remove?
31933 + */
31934 +extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val);
31935 +
31936 +/**
31937 + * Get value of rmtwkupsig bit in DCTL register
31938 + */
31939 +extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if);
31940 +
31941 +/**
31942 + * Get value of prt_sleep_sts field from the GLPMCFG register
31943 + */
31944 +extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if);
31945 +
31946 +/**
31947 + * Get value of rem_wkup_en field from the GLPMCFG register
31948 + */
31949 +extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if);
31950 +
31951 +/**
31952 + * Get value of appl_resp field from the GLPMCFG register
31953 + */
31954 +extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if);
31955 +/**
31956 + * Set value of appl_resp field from the GLPMCFG register
31957 + */
31958 +extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val);
31959 +
31960 +/**
31961 + * Get value of hsic_connect field from the GLPMCFG register
31962 + */
31963 +extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if);
31964 +/**
31965 + * Set value of hsic_connect field from the GLPMCFG register
31966 + */
31967 +extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val);
31968 +
31969 +/**
31970 + * Get value of inv_sel_hsic field from the GLPMCFG register.
31971 + */
31972 +extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if);
31973 +/**
31974 + * Set value of inv_sel_hsic field from the GLPMFG register.
31975 + */
31976 +extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val);
31977 +
31978 +/*
31979 + * Some functions for accessing registers
31980 + */
31981 +
31982 +/**
31983 + *  GOTGCTL register
31984 + */
31985 +extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if);
31986 +extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val);
31987 +
31988 +/**
31989 + * GUSBCFG register
31990 + */
31991 +extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if);
31992 +extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val);
31993 +
31994 +/**
31995 + * GRXFSIZ register
31996 + */
31997 +extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if);
31998 +extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31999 +
32000 +/**
32001 + * GNPTXFSIZ register
32002 + */
32003 +extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if);
32004 +extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
32005 +
32006 +extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if);
32007 +extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val);
32008 +
32009 +/**
32010 + * GGPIO register
32011 + */
32012 +extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if);
32013 +extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val);
32014 +
32015 +/**
32016 + * GUID register
32017 + */
32018 +extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if);
32019 +extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val);
32020 +
32021 +/**
32022 + * HPRT0 register
32023 + */
32024 +extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if);
32025 +extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val);
32026 +
32027 +/**
32028 + * GHPTXFSIZE
32029 + */
32030 +extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if);
32031 +
32032 +/** @} */
32033 +
32034 +#endif                         /* __DWC_CORE_IF_H__ */
32035 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
32036 new file mode 100644
32037 index 0000000..8681aa9
32038 --- /dev/null
32039 +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
32040 @@ -0,0 +1,116 @@
32041 +/* ==========================================================================
32042 + *
32043 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
32044 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
32045 + * otherwise expressly agreed to in writing between Synopsys and you.
32046 + * 
32047 + * The Software IS NOT an item of Licensed Software or Licensed Product under
32048 + * any End User Software License Agreement or Agreement for Licensed Product
32049 + * with Synopsys or any supplement thereto. You are permitted to use and
32050 + * redistribute this Software in source and binary forms, with or without
32051 + * modification, provided that redistributions of source code must retain this
32052 + * notice. You may not view, use, disclose, copy or distribute this file or
32053 + * any information contained herein except pursuant to this license grant from
32054 + * Synopsys. If you do not agree with this notice, including the disclaimer
32055 + * below, then you are not authorized to use the Software.
32056 + * 
32057 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
32058 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32059 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32060 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
32061 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32062 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32063 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32064 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32065 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32066 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32067 + * DAMAGE.
32068 + * ========================================================================== */
32069 +
32070 +#ifndef __DWC_OTG_DBG_H__
32071 +#define __DWC_OTG_DBG_H__
32072 +
32073 +/** @file
32074 + * This file defines debug levels.
32075 + * Debugging support vanishes in non-debug builds.  
32076 + */
32077 +
32078 +/**
32079 + * The Debug Level bit-mask variable.
32080 + */
32081 +extern uint32_t g_dbg_lvl;
32082 +/**
32083 + * Set the Debug Level variable.
32084 + */
32085 +static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
32086 +{
32087 +       uint32_t old = g_dbg_lvl;
32088 +       g_dbg_lvl = new;
32089 +       return old;
32090 +}
32091 +
32092 +/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
32093 +#define DBG_CIL                (0x2)
32094 +/** When debug level has the DBG_CILV bit set, display CIL Verbose debug
32095 + * messages */
32096 +#define DBG_CILV       (0x20)
32097 +/**  When debug level has the DBG_PCD bit set, display PCD (Device) debug
32098 + *  messages */
32099 +#define DBG_PCD                (0x4)
32100 +/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug
32101 + * messages */
32102 +#define DBG_PCDV       (0x40)
32103 +/** When debug level has the DBG_HCD bit set, display Host debug messages */
32104 +#define DBG_HCD                (0x8)
32105 +/** When debug level has the DBG_HCDV bit set, display Verbose Host debug
32106 + * messages */
32107 +#define DBG_HCDV       (0x80)
32108 +/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host
32109 + *  mode. */
32110 +#define DBG_HCD_URB    (0x800)
32111 +/** When debug level has the DBG_HCDI bit set, display host interrupt
32112 + *  messages. */
32113 +#define DBG_HCDI       (0x1000)
32114 +
32115 +/** When debug level has any bit set, display debug messages */
32116 +#define DBG_ANY                (0xFF)
32117 +
32118 +/** All debug messages off */
32119 +#define DBG_OFF                0
32120 +
32121 +/** Prefix string for DWC_DEBUG print macros. */
32122 +#define USB_DWC "DWC_otg: "
32123 +
32124 +/** 
32125 + * Print a debug message when the Global debug level variable contains
32126 + * the bit defined in <code>lvl</code>.
32127 + *
32128 + * @param[in] lvl - Debug level, use one of the DBG_ constants above.
32129 + * @param[in] x - like printf
32130 + *
32131 + *    Example:<p>
32132 + * <code>
32133 + *      DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr);
32134 + * </code>
32135 + * <br>
32136 + * results in:<br> 
32137 + * <code>
32138 + * usb-DWC_otg: dwc_otg_cil_init(ca867000)
32139 + * </code>
32140 + */
32141 +#ifdef DEBUG
32142 +
32143 +# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0)
32144 +# define DWC_DEBUGP(x...)      DWC_DEBUGPL(DBG_ANY, x )
32145 +
32146 +# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl)
32147 +
32148 +#else
32149 +
32150 +# define DWC_DEBUGPL(lvl, x...) do{}while(0)
32151 +# define DWC_DEBUGP(x...)
32152 +
32153 +# define CHK_DEBUG_LEVEL(level) (0)
32154 +
32155 +#endif /*DEBUG*/
32156 +#endif
32157 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
32158 new file mode 100644
32159 index 0000000..e7f99e1
32160 --- /dev/null
32161 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
32162 @@ -0,0 +1,1700 @@
32163 +/* ==========================================================================
32164 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
32165 + * $Revision: #92 $
32166 + * $Date: 2012/08/10 $
32167 + * $Change: 2047372 $
32168 + *
32169 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
32170 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
32171 + * otherwise expressly agreed to in writing between Synopsys and you.
32172 + *
32173 + * The Software IS NOT an item of Licensed Software or Licensed Product under
32174 + * any End User Software License Agreement or Agreement for Licensed Product
32175 + * with Synopsys or any supplement thereto. You are permitted to use and
32176 + * redistribute this Software in source and binary forms, with or without
32177 + * modification, provided that redistributions of source code must retain this
32178 + * notice. You may not view, use, disclose, copy or distribute this file or
32179 + * any information contained herein except pursuant to this license grant from
32180 + * Synopsys. If you do not agree with this notice, including the disclaimer
32181 + * below, then you are not authorized to use the Software.
32182 + *
32183 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
32184 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32185 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32186 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
32187 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32188 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32189 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32190 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32191 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32192 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32193 + * DAMAGE.
32194 + * ========================================================================== */
32195 +
32196 +/** @file
32197 + * The dwc_otg_driver module provides the initialization and cleanup entry
32198 + * points for the DWC_otg driver. This module will be dynamically installed
32199 + * after Linux is booted using the insmod command. When the module is
32200 + * installed, the dwc_otg_driver_init function is called. When the module is
32201 + * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
32202 + *
32203 + * This module also defines a data structure for the dwc_otg_driver, which is
32204 + * used in conjunction with the standard ARM lm_device structure. These
32205 + * structures allow the OTG driver to comply with the standard Linux driver
32206 + * model in which devices and drivers are registered with a bus driver. This
32207 + * has the benefit that Linux can expose attributes of the driver and device
32208 + * in its special sysfs file system. Users can then read or write files in
32209 + * this file system to perform diagnostics on the driver components or the
32210 + * device.
32211 + */
32212 +
32213 +#include "dwc_otg_os_dep.h"
32214 +#include "dwc_os.h"
32215 +#include "dwc_otg_dbg.h"
32216 +#include "dwc_otg_driver.h"
32217 +#include "dwc_otg_attr.h"
32218 +#include "dwc_otg_core_if.h"
32219 +#include "dwc_otg_pcd_if.h"
32220 +#include "dwc_otg_hcd_if.h"
32221 +
32222 +#define DWC_DRIVER_VERSION     "3.00a 10-AUG-2012"
32223 +#define DWC_DRIVER_DESC                "HS OTG USB Controller driver"
32224 +
32225 +bool microframe_schedule=true;
32226 +
32227 +static const char dwc_driver_name[] = "dwc_otg";
32228 +
32229 +extern int pcd_init(
32230 +#ifdef LM_INTERFACE
32231 +                          struct lm_device *_dev
32232 +#elif  defined(PCI_INTERFACE)
32233 +                          struct pci_dev *_dev
32234 +#elif  defined(PLATFORM_INTERFACE)
32235 +       struct platform_device *dev
32236 +#endif
32237 +    );
32238 +extern int hcd_init(
32239 +#ifdef LM_INTERFACE
32240 +                          struct lm_device *_dev
32241 +#elif  defined(PCI_INTERFACE)
32242 +                          struct pci_dev *_dev
32243 +#elif  defined(PLATFORM_INTERFACE)
32244 +       struct platform_device *dev
32245 +#endif
32246 +    );
32247 +
32248 +extern int pcd_remove(
32249 +#ifdef LM_INTERFACE
32250 +                            struct lm_device *_dev
32251 +#elif  defined(PCI_INTERFACE)
32252 +                            struct pci_dev *_dev
32253 +#elif  defined(PLATFORM_INTERFACE)
32254 +       struct platform_device *_dev
32255 +#endif
32256 +    );
32257 +
32258 +extern void hcd_remove(
32259 +#ifdef LM_INTERFACE
32260 +                             struct lm_device *_dev
32261 +#elif  defined(PCI_INTERFACE)
32262 +                             struct pci_dev *_dev
32263 +#elif  defined(PLATFORM_INTERFACE)
32264 +       struct platform_device *_dev
32265 +#endif
32266 +    );
32267 +
32268 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
32269 +
32270 +/*-------------------------------------------------------------------------*/
32271 +/* Encapsulate the module parameter settings */
32272 +
32273 +struct dwc_otg_driver_module_params {
32274 +       int32_t opt;
32275 +       int32_t otg_cap;
32276 +       int32_t dma_enable;
32277 +       int32_t dma_desc_enable;
32278 +       int32_t dma_burst_size;
32279 +       int32_t speed;
32280 +       int32_t host_support_fs_ls_low_power;
32281 +       int32_t host_ls_low_power_phy_clk;
32282 +       int32_t enable_dynamic_fifo;
32283 +       int32_t data_fifo_size;
32284 +       int32_t dev_rx_fifo_size;
32285 +       int32_t dev_nperio_tx_fifo_size;
32286 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
32287 +       int32_t host_rx_fifo_size;
32288 +       int32_t host_nperio_tx_fifo_size;
32289 +       int32_t host_perio_tx_fifo_size;
32290 +       int32_t max_transfer_size;
32291 +       int32_t max_packet_count;
32292 +       int32_t host_channels;
32293 +       int32_t dev_endpoints;
32294 +       int32_t phy_type;
32295 +       int32_t phy_utmi_width;
32296 +       int32_t phy_ulpi_ddr;
32297 +       int32_t phy_ulpi_ext_vbus;
32298 +       int32_t i2c_enable;
32299 +       int32_t ulpi_fs_ls;
32300 +       int32_t ts_dline;
32301 +       int32_t en_multiple_tx_fifo;
32302 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
32303 +       uint32_t thr_ctl;
32304 +       uint32_t tx_thr_length;
32305 +       uint32_t rx_thr_length;
32306 +       int32_t pti_enable;
32307 +       int32_t mpi_enable;
32308 +       int32_t lpm_enable;
32309 +       int32_t ic_usb_cap;
32310 +       int32_t ahb_thr_ratio;
32311 +       int32_t power_down;
32312 +       int32_t reload_ctl;
32313 +       int32_t dev_out_nak;
32314 +       int32_t cont_on_bna;
32315 +       int32_t ahb_single;
32316 +       int32_t otg_ver;
32317 +       int32_t adp_enable;
32318 +};
32319 +
32320 +static struct dwc_otg_driver_module_params dwc_otg_module_params = {
32321 +       .opt = -1,
32322 +       .otg_cap = -1,
32323 +       .dma_enable = -1,
32324 +       .dma_desc_enable = -1,
32325 +       .dma_burst_size = -1,
32326 +       .speed = -1,
32327 +       .host_support_fs_ls_low_power = -1,
32328 +       .host_ls_low_power_phy_clk = -1,
32329 +       .enable_dynamic_fifo = -1,
32330 +       .data_fifo_size = -1,
32331 +       .dev_rx_fifo_size = -1,
32332 +       .dev_nperio_tx_fifo_size = -1,
32333 +       .dev_perio_tx_fifo_size = {
32334 +                                  /* dev_perio_tx_fifo_size_1 */
32335 +                                  -1,
32336 +                                  -1,
32337 +                                  -1,
32338 +                                  -1,
32339 +                                  -1,
32340 +                                  -1,
32341 +                                  -1,
32342 +                                  -1,
32343 +                                  -1,
32344 +                                  -1,
32345 +                                  -1,
32346 +                                  -1,
32347 +                                  -1,
32348 +                                  -1,
32349 +                                  -1
32350 +                                  /* 15 */
32351 +                                  },
32352 +       .host_rx_fifo_size = -1,
32353 +       .host_nperio_tx_fifo_size = -1,
32354 +       .host_perio_tx_fifo_size = -1,
32355 +       .max_transfer_size = -1,
32356 +       .max_packet_count = -1,
32357 +       .host_channels = -1,
32358 +       .dev_endpoints = -1,
32359 +       .phy_type = -1,
32360 +       .phy_utmi_width = -1,
32361 +       .phy_ulpi_ddr = -1,
32362 +       .phy_ulpi_ext_vbus = -1,
32363 +       .i2c_enable = -1,
32364 +       .ulpi_fs_ls = -1,
32365 +       .ts_dline = -1,
32366 +       .en_multiple_tx_fifo = -1,
32367 +       .dev_tx_fifo_size = {
32368 +                            /* dev_tx_fifo_size */
32369 +                            -1,
32370 +                            -1,
32371 +                            -1,
32372 +                            -1,
32373 +                            -1,
32374 +                            -1,
32375 +                            -1,
32376 +                            -1,
32377 +                            -1,
32378 +                            -1,
32379 +                            -1,
32380 +                            -1,
32381 +                            -1,
32382 +                            -1,
32383 +                            -1
32384 +                            /* 15 */
32385 +                            },
32386 +       .thr_ctl = -1,
32387 +       .tx_thr_length = -1,
32388 +       .rx_thr_length = -1,
32389 +       .pti_enable = -1,
32390 +       .mpi_enable = -1,
32391 +       .lpm_enable = -1,
32392 +       .ic_usb_cap = -1,
32393 +       .ahb_thr_ratio = -1,
32394 +       .power_down = -1,
32395 +       .reload_ctl = -1,
32396 +       .dev_out_nak = -1,
32397 +       .cont_on_bna = -1,
32398 +       .ahb_single = -1,
32399 +       .otg_ver = -1,
32400 +       .adp_enable = -1,
32401 +};
32402 +
32403 +/**
32404 + * This function shows the Driver Version.
32405 + */
32406 +static ssize_t version_show(struct device_driver *dev, char *buf)
32407 +{
32408 +       return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n",
32409 +                       DWC_DRIVER_VERSION);
32410 +}
32411 +
32412 +static DRIVER_ATTR(version, S_IRUGO, version_show, NULL);
32413 +
32414 +/**
32415 + * Global Debug Level Mask.
32416 + */
32417 +uint32_t g_dbg_lvl = 0;                /* OFF */
32418 +
32419 +/**
32420 + * This function shows the driver Debug Level.
32421 + */
32422 +static ssize_t dbg_level_show(struct device_driver *drv, char *buf)
32423 +{
32424 +       return sprintf(buf, "0x%0x\n", g_dbg_lvl);
32425 +}
32426 +
32427 +/**
32428 + * This function stores the driver Debug Level.
32429 + */
32430 +static ssize_t dbg_level_store(struct device_driver *drv, const char *buf,
32431 +                              size_t count)
32432 +{
32433 +       g_dbg_lvl = simple_strtoul(buf, NULL, 16);
32434 +       return count;
32435 +}
32436 +
32437 +static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,
32438 +                  dbg_level_store);
32439 +
32440 +/**
32441 + * This function is called during module intialization
32442 + * to pass module parameters to the DWC_OTG CORE.
32443 + */
32444 +static int set_parameters(dwc_otg_core_if_t * core_if)
32445 +{
32446 +       int retval = 0;
32447 +       int i;
32448 +
32449 +       if (dwc_otg_module_params.otg_cap != -1) {
32450 +               retval +=
32451 +                   dwc_otg_set_param_otg_cap(core_if,
32452 +                                             dwc_otg_module_params.otg_cap);
32453 +       }
32454 +       if (dwc_otg_module_params.dma_enable != -1) {
32455 +               retval +=
32456 +                   dwc_otg_set_param_dma_enable(core_if,
32457 +                                                dwc_otg_module_params.
32458 +                                                dma_enable);
32459 +       }
32460 +       if (dwc_otg_module_params.dma_desc_enable != -1) {
32461 +               retval +=
32462 +                   dwc_otg_set_param_dma_desc_enable(core_if,
32463 +                                                     dwc_otg_module_params.
32464 +                                                     dma_desc_enable);
32465 +       }
32466 +       if (dwc_otg_module_params.opt != -1) {
32467 +               retval +=
32468 +                   dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt);
32469 +       }
32470 +       if (dwc_otg_module_params.dma_burst_size != -1) {
32471 +               retval +=
32472 +                   dwc_otg_set_param_dma_burst_size(core_if,
32473 +                                                    dwc_otg_module_params.
32474 +                                                    dma_burst_size);
32475 +       }
32476 +       if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) {
32477 +               retval +=
32478 +                   dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
32479 +                                                                  dwc_otg_module_params.
32480 +                                                                  host_support_fs_ls_low_power);
32481 +       }
32482 +       if (dwc_otg_module_params.enable_dynamic_fifo != -1) {
32483 +               retval +=
32484 +                   dwc_otg_set_param_enable_dynamic_fifo(core_if,
32485 +                                                         dwc_otg_module_params.
32486 +                                                         enable_dynamic_fifo);
32487 +       }
32488 +       if (dwc_otg_module_params.data_fifo_size != -1) {
32489 +               retval +=
32490 +                   dwc_otg_set_param_data_fifo_size(core_if,
32491 +                                                    dwc_otg_module_params.
32492 +                                                    data_fifo_size);
32493 +       }
32494 +       if (dwc_otg_module_params.dev_rx_fifo_size != -1) {
32495 +               retval +=
32496 +                   dwc_otg_set_param_dev_rx_fifo_size(core_if,
32497 +                                                      dwc_otg_module_params.
32498 +                                                      dev_rx_fifo_size);
32499 +       }
32500 +       if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) {
32501 +               retval +=
32502 +                   dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
32503 +                                                             dwc_otg_module_params.
32504 +                                                             dev_nperio_tx_fifo_size);
32505 +       }
32506 +       if (dwc_otg_module_params.host_rx_fifo_size != -1) {
32507 +               retval +=
32508 +                   dwc_otg_set_param_host_rx_fifo_size(core_if,
32509 +                                                       dwc_otg_module_params.host_rx_fifo_size);
32510 +       }
32511 +       if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) {
32512 +               retval +=
32513 +                   dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
32514 +                                                              dwc_otg_module_params.
32515 +                                                              host_nperio_tx_fifo_size);
32516 +       }
32517 +       if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) {
32518 +               retval +=
32519 +                   dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
32520 +                                                             dwc_otg_module_params.
32521 +                                                             host_perio_tx_fifo_size);
32522 +       }
32523 +       if (dwc_otg_module_params.max_transfer_size != -1) {
32524 +               retval +=
32525 +                   dwc_otg_set_param_max_transfer_size(core_if,
32526 +                                                       dwc_otg_module_params.
32527 +                                                       max_transfer_size);
32528 +       }
32529 +       if (dwc_otg_module_params.max_packet_count != -1) {
32530 +               retval +=
32531 +                   dwc_otg_set_param_max_packet_count(core_if,
32532 +                                                      dwc_otg_module_params.
32533 +                                                      max_packet_count);
32534 +       }
32535 +       if (dwc_otg_module_params.host_channels != -1) {
32536 +               retval +=
32537 +                   dwc_otg_set_param_host_channels(core_if,
32538 +                                                   dwc_otg_module_params.
32539 +                                                   host_channels);
32540 +       }
32541 +       if (dwc_otg_module_params.dev_endpoints != -1) {
32542 +               retval +=
32543 +                   dwc_otg_set_param_dev_endpoints(core_if,
32544 +                                                   dwc_otg_module_params.
32545 +                                                   dev_endpoints);
32546 +       }
32547 +       if (dwc_otg_module_params.phy_type != -1) {
32548 +               retval +=
32549 +                   dwc_otg_set_param_phy_type(core_if,
32550 +                                              dwc_otg_module_params.phy_type);
32551 +       }
32552 +       if (dwc_otg_module_params.speed != -1) {
32553 +               retval +=
32554 +                   dwc_otg_set_param_speed(core_if,
32555 +                                           dwc_otg_module_params.speed);
32556 +       }
32557 +       if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) {
32558 +               retval +=
32559 +                   dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
32560 +                                                               dwc_otg_module_params.
32561 +                                                               host_ls_low_power_phy_clk);
32562 +       }
32563 +       if (dwc_otg_module_params.phy_ulpi_ddr != -1) {
32564 +               retval +=
32565 +                   dwc_otg_set_param_phy_ulpi_ddr(core_if,
32566 +                                                  dwc_otg_module_params.
32567 +                                                  phy_ulpi_ddr);
32568 +       }
32569 +       if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) {
32570 +               retval +=
32571 +                   dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
32572 +                                                       dwc_otg_module_params.
32573 +                                                       phy_ulpi_ext_vbus);
32574 +       }
32575 +       if (dwc_otg_module_params.phy_utmi_width != -1) {
32576 +               retval +=
32577 +                   dwc_otg_set_param_phy_utmi_width(core_if,
32578 +                                                    dwc_otg_module_params.
32579 +                                                    phy_utmi_width);
32580 +       }
32581 +       if (dwc_otg_module_params.ulpi_fs_ls != -1) {
32582 +               retval +=
32583 +                   dwc_otg_set_param_ulpi_fs_ls(core_if,
32584 +                                                dwc_otg_module_params.ulpi_fs_ls);
32585 +       }
32586 +       if (dwc_otg_module_params.ts_dline != -1) {
32587 +               retval +=
32588 +                   dwc_otg_set_param_ts_dline(core_if,
32589 +                                              dwc_otg_module_params.ts_dline);
32590 +       }
32591 +       if (dwc_otg_module_params.i2c_enable != -1) {
32592 +               retval +=
32593 +                   dwc_otg_set_param_i2c_enable(core_if,
32594 +                                                dwc_otg_module_params.
32595 +                                                i2c_enable);
32596 +       }
32597 +       if (dwc_otg_module_params.en_multiple_tx_fifo != -1) {
32598 +               retval +=
32599 +                   dwc_otg_set_param_en_multiple_tx_fifo(core_if,
32600 +                                                         dwc_otg_module_params.
32601 +                                                         en_multiple_tx_fifo);
32602 +       }
32603 +       for (i = 0; i < 15; i++) {
32604 +               if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {
32605 +                       retval +=
32606 +                           dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
32607 +                                                                    dwc_otg_module_params.
32608 +                                                                    dev_perio_tx_fifo_size
32609 +                                                                    [i], i);
32610 +               }
32611 +       }
32612 +
32613 +       for (i = 0; i < 15; i++) {
32614 +               if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {
32615 +                       retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
32616 +                                                                    dwc_otg_module_params.
32617 +                                                                    dev_tx_fifo_size
32618 +                                                                    [i], i);
32619 +               }
32620 +       }
32621 +       if (dwc_otg_module_params.thr_ctl != -1) {
32622 +               retval +=
32623 +                   dwc_otg_set_param_thr_ctl(core_if,
32624 +                                             dwc_otg_module_params.thr_ctl);
32625 +       }
32626 +       if (dwc_otg_module_params.mpi_enable != -1) {
32627 +               retval +=
32628 +                   dwc_otg_set_param_mpi_enable(core_if,
32629 +                                                dwc_otg_module_params.
32630 +                                                mpi_enable);
32631 +       }
32632 +       if (dwc_otg_module_params.pti_enable != -1) {
32633 +               retval +=
32634 +                   dwc_otg_set_param_pti_enable(core_if,
32635 +                                                dwc_otg_module_params.
32636 +                                                pti_enable);
32637 +       }
32638 +       if (dwc_otg_module_params.lpm_enable != -1) {
32639 +               retval +=
32640 +                   dwc_otg_set_param_lpm_enable(core_if,
32641 +                                                dwc_otg_module_params.
32642 +                                                lpm_enable);
32643 +       }
32644 +       if (dwc_otg_module_params.ic_usb_cap != -1) {
32645 +               retval +=
32646 +                   dwc_otg_set_param_ic_usb_cap(core_if,
32647 +                                                dwc_otg_module_params.
32648 +                                                ic_usb_cap);
32649 +       }
32650 +       if (dwc_otg_module_params.tx_thr_length != -1) {
32651 +               retval +=
32652 +                   dwc_otg_set_param_tx_thr_length(core_if,
32653 +                                                   dwc_otg_module_params.tx_thr_length);
32654 +       }
32655 +       if (dwc_otg_module_params.rx_thr_length != -1) {
32656 +               retval +=
32657 +                   dwc_otg_set_param_rx_thr_length(core_if,
32658 +                                                   dwc_otg_module_params.
32659 +                                                   rx_thr_length);
32660 +       }
32661 +       if (dwc_otg_module_params.ahb_thr_ratio != -1) {
32662 +               retval +=
32663 +                   dwc_otg_set_param_ahb_thr_ratio(core_if,
32664 +                                                   dwc_otg_module_params.ahb_thr_ratio);
32665 +       }
32666 +       if (dwc_otg_module_params.power_down != -1) {
32667 +               retval +=
32668 +                   dwc_otg_set_param_power_down(core_if,
32669 +                                                dwc_otg_module_params.power_down);
32670 +       }
32671 +       if (dwc_otg_module_params.reload_ctl != -1) {
32672 +               retval +=
32673 +                   dwc_otg_set_param_reload_ctl(core_if,
32674 +                                                dwc_otg_module_params.reload_ctl);
32675 +       }
32676 +
32677 +       if (dwc_otg_module_params.dev_out_nak != -1) {
32678 +               retval +=
32679 +                       dwc_otg_set_param_dev_out_nak(core_if,
32680 +                       dwc_otg_module_params.dev_out_nak);
32681 +       }
32682 +
32683 +       if (dwc_otg_module_params.cont_on_bna != -1) {
32684 +               retval +=
32685 +                       dwc_otg_set_param_cont_on_bna(core_if,
32686 +                       dwc_otg_module_params.cont_on_bna);
32687 +       }
32688 +
32689 +       if (dwc_otg_module_params.ahb_single != -1) {
32690 +               retval +=
32691 +                       dwc_otg_set_param_ahb_single(core_if,
32692 +                       dwc_otg_module_params.ahb_single);
32693 +       }
32694 +
32695 +       if (dwc_otg_module_params.otg_ver != -1) {
32696 +               retval +=
32697 +                   dwc_otg_set_param_otg_ver(core_if,
32698 +                                             dwc_otg_module_params.otg_ver);
32699 +       }
32700 +       if (dwc_otg_module_params.adp_enable != -1) {
32701 +               retval +=
32702 +                   dwc_otg_set_param_adp_enable(core_if,
32703 +                                                dwc_otg_module_params.
32704 +                                                adp_enable);
32705 +       }
32706 +       return retval;
32707 +}
32708 +
32709 +/**
32710 + * This function is the top level interrupt handler for the Common
32711 + * (Device and host modes) interrupts.
32712 + */
32713 +static irqreturn_t dwc_otg_common_irq(int irq, void *dev)
32714 +{
32715 +       int32_t retval = IRQ_NONE;
32716 +
32717 +       retval = dwc_otg_handle_common_intr(dev);
32718 +       if (retval != 0) {
32719 +               S3C2410X_CLEAR_EINTPEND();
32720 +       }
32721 +       return IRQ_RETVAL(retval);
32722 +}
32723 +
32724 +/**
32725 + * This function is called when a lm_device is unregistered with the
32726 + * dwc_otg_driver. This happens, for example, when the rmmod command is
32727 + * executed. The device may or may not be electrically present. If it is
32728 + * present, the driver stops device processing. Any resources used on behalf
32729 + * of this device are freed.
32730 + *
32731 + * @param _dev
32732 + */
32733 +#ifdef LM_INTERFACE
32734 +#define REM_RETVAL(n) 
32735 +static void dwc_otg_driver_remove(      struct lm_device *_dev )
32736 +{       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
32737 +#elif  defined(PCI_INTERFACE)
32738 +#define REM_RETVAL(n) 
32739 +static void dwc_otg_driver_remove(      struct pci_dev *_dev )
32740 +{      dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
32741 +#elif  defined(PLATFORM_INTERFACE)
32742 +#define REM_RETVAL(n) n
32743 +static int dwc_otg_driver_remove(        struct platform_device *_dev )
32744 +{       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
32745 +#endif
32746 +
32747 +       DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
32748 +
32749 +       if (!otg_dev) {
32750 +               /* Memory allocation for the dwc_otg_device failed. */
32751 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
32752 +                return REM_RETVAL(-ENOMEM);
32753 +       }
32754 +#ifndef DWC_DEVICE_ONLY
32755 +       if (otg_dev->hcd) {
32756 +               hcd_remove(_dev);
32757 +       } else {
32758 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
32759 +                return REM_RETVAL(-EINVAL);
32760 +       }
32761 +#endif
32762 +
32763 +#ifndef DWC_HOST_ONLY
32764 +       if (otg_dev->pcd) {
32765 +               pcd_remove(_dev);
32766 +       } else {
32767 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__);
32768 +                return REM_RETVAL(-EINVAL);
32769 +       }
32770 +#endif
32771 +       /*
32772 +        * Free the IRQ
32773 +        */
32774 +       if (otg_dev->common_irq_installed) {
32775 +#ifdef PLATFORM_INTERFACE
32776 +               free_irq(platform_get_irq(_dev, 0), otg_dev);
32777 +#else
32778 +               free_irq(_dev->irq, otg_dev);
32779 +#endif
32780 +        } else {
32781 +               DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
32782 +               return REM_RETVAL(-ENXIO);
32783 +       }  
32784 +
32785 +       if (otg_dev->core_if) {
32786 +               dwc_otg_cil_remove(otg_dev->core_if);
32787 +       } else {
32788 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__);
32789 +               return REM_RETVAL(-ENXIO);
32790 +       }
32791 +
32792 +       /*
32793 +        * Remove the device attributes
32794 +        */
32795 +       dwc_otg_attr_remove(_dev);
32796 +
32797 +       /*
32798 +        * Return the memory.
32799 +        */
32800 +       if (otg_dev->os_dep.base) {
32801 +               iounmap(otg_dev->os_dep.base);
32802 +       }
32803 +       DWC_FREE(otg_dev);
32804 +
32805 +       /*
32806 +        * Clear the drvdata pointer.
32807 +        */
32808 +#ifdef LM_INTERFACE
32809 +       lm_set_drvdata(_dev, 0);
32810 +#elif defined(PCI_INTERFACE)
32811 +        release_mem_region(otg_dev->os_dep.rsrc_start,
32812 +                           otg_dev->os_dep.rsrc_len);
32813 +       pci_set_drvdata(_dev, 0);
32814 +#elif  defined(PLATFORM_INTERFACE)
32815 +        platform_set_drvdata(_dev, 0);
32816 +#endif
32817 +        return REM_RETVAL(0);
32818 +}
32819 +
32820 +/**
32821 + * This function is called when an lm_device is bound to a
32822 + * dwc_otg_driver. It creates the driver components required to
32823 + * control the device (CIL, HCD, and PCD) and it initializes the
32824 + * device. The driver components are stored in a dwc_otg_device
32825 + * structure. A reference to the dwc_otg_device is saved in the
32826 + * lm_device. This allows the driver to access the dwc_otg_device
32827 + * structure on subsequent calls to driver methods for this device.
32828 + *
32829 + * @param _dev Bus device
32830 + */
32831 +static int dwc_otg_driver_probe(
32832 +#ifdef LM_INTERFACE
32833 +                                      struct lm_device *_dev
32834 +#elif defined(PCI_INTERFACE)
32835 +                                      struct pci_dev *_dev,
32836 +                                      const struct pci_device_id *id
32837 +#elif  defined(PLATFORM_INTERFACE)
32838 +                                       struct platform_device *_dev
32839 +#endif
32840 +    )
32841 +{
32842 +       int retval = 0;
32843 +       dwc_otg_device_t *dwc_otg_device;
32844 +        int devirq;
32845 +
32846 +       dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev);
32847 +#ifdef LM_INTERFACE
32848 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start);
32849 +#elif defined(PCI_INTERFACE)
32850 +       if (!id) {
32851 +               DWC_ERROR("Invalid pci_device_id %p", id);
32852 +               return -EINVAL;
32853 +       }
32854 +
32855 +       if (!_dev || (pci_enable_device(_dev) < 0)) {
32856 +               DWC_ERROR("Invalid pci_device %p", _dev);
32857 +               return -ENODEV;
32858 +       }
32859 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));
32860 +       /* other stuff needed as well? */
32861 +        
32862 +#elif  defined(PLATFORM_INTERFACE)
32863 +       dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n",
32864 +                (unsigned)_dev->resource->start,
32865 +                (unsigned)(_dev->resource->end - _dev->resource->start));
32866 +#endif
32867 +
32868 +       dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));
32869 +
32870 +       if (!dwc_otg_device) {
32871 +               dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");
32872 +               return -ENOMEM;
32873 +       }
32874 +
32875 +       memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
32876 +       dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
32877 +
32878 +       /*
32879 +        * Map the DWC_otg Core memory into virtual address space.
32880 +        */
32881 +#ifdef LM_INTERFACE
32882 +       dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K);
32883 +
32884 +       if (!dwc_otg_device->os_dep.base) {
32885 +               dev_err(&_dev->dev, "ioremap() failed\n");
32886 +               DWC_FREE(dwc_otg_device);
32887 +               return -ENOMEM;
32888 +       }
32889 +       dev_dbg(&_dev->dev, "base=0x%08x\n",
32890 +               (unsigned)dwc_otg_device->os_dep.base);
32891 +#elif defined(PCI_INTERFACE)
32892 +       _dev->current_state = PCI_D0;
32893 +       _dev->dev.power.power_state = PMSG_ON;
32894 +
32895 +       if (!_dev->irq) {
32896 +               DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!",
32897 +                         pci_name(_dev));
32898 +               iounmap(dwc_otg_device->os_dep.base);
32899 +               DWC_FREE(dwc_otg_device);
32900 +               return -ENODEV;
32901 +       }
32902 +
32903 +       dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0);
32904 +       dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0);
32905 +       DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n",
32906 +                   (unsigned)dwc_otg_device->os_dep.rsrc_start,
32907 +                   (unsigned)dwc_otg_device->os_dep.rsrc_len);
32908 +       if (!request_mem_region
32909 +           (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len,
32910 +            "dwc_otg")) {
32911 +               dev_dbg(&_dev->dev, "error requesting memory\n");
32912 +               iounmap(dwc_otg_device->os_dep.base);
32913 +               DWC_FREE(dwc_otg_device);
32914 +               return -EFAULT;
32915 +       }
32916 +
32917 +       dwc_otg_device->os_dep.base =
32918 +           ioremap_nocache(dwc_otg_device->os_dep.rsrc_start,
32919 +                           dwc_otg_device->os_dep.rsrc_len);
32920 +       if (dwc_otg_device->os_dep.base == NULL) {
32921 +               dev_dbg(&_dev->dev, "error mapping memory\n");
32922 +               release_mem_region(dwc_otg_device->os_dep.rsrc_start,
32923 +                                  dwc_otg_device->os_dep.rsrc_len);
32924 +               iounmap(dwc_otg_device->os_dep.base);
32925 +               DWC_FREE(dwc_otg_device);
32926 +               return -EFAULT;
32927 +       }
32928 +       dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n",
32929 +               dwc_otg_device->os_dep.base);
32930 +       dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base;
32931 +       dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n",
32932 +               dwc_otg_device->os_dep.base);
32933 +       dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__,
32934 +               (unsigned)dwc_otg_device->os_dep.rsrc_start,
32935 +               dwc_otg_device->os_dep.base);
32936 +
32937 +       pci_set_master(_dev);
32938 +       pci_set_drvdata(_dev, dwc_otg_device);
32939 +#elif defined(PLATFORM_INTERFACE)
32940 +        DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n",
32941 +                    _dev->resource->start,
32942 +                    _dev->resource->end - _dev->resource->start + 1);
32943 +#if 1
32944 +        if (!request_mem_region(_dev->resource->start,
32945 +                                _dev->resource->end - _dev->resource->start + 1,
32946 +                                "dwc_otg")) {
32947 +          dev_dbg(&_dev->dev, "error reserving mapped memory\n");
32948 +          retval = -EFAULT;
32949 +          goto fail;
32950 +        }
32951 +
32952 +       dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
32953 +                                                      _dev->resource->end -
32954 +                                                      _dev->resource->start+1);
32955 +#else
32956 +        {
32957 +                struct map_desc desc = {
32958 +                    .virtual = IO_ADDRESS((unsigned)_dev->resource->start),
32959 +                    .pfn     = __phys_to_pfn((unsigned)_dev->resource->start),
32960 +                    .length  = SZ_128K,
32961 +                    .type    = MT_DEVICE
32962 +                };
32963 +                iotable_init(&desc, 1);
32964 +                dwc_otg_device->os_dep.base = (void *)desc.virtual;
32965 +        }
32966 +#endif
32967 +       if (!dwc_otg_device->os_dep.base) {
32968 +               dev_err(&_dev->dev, "ioremap() failed\n");
32969 +               retval = -ENOMEM;
32970 +               goto fail;
32971 +       }
32972 +       dev_dbg(&_dev->dev, "base=0x%08x\n",
32973 +                (unsigned)dwc_otg_device->os_dep.base);
32974 +#endif
32975 +
32976 +       /*
32977 +        * Initialize driver data to point to the global DWC_otg
32978 +        * Device structure.
32979 +        */
32980 +#ifdef LM_INTERFACE
32981 +       lm_set_drvdata(_dev, dwc_otg_device);
32982 +#elif defined(PLATFORM_INTERFACE)
32983 +       platform_set_drvdata(_dev, dwc_otg_device);
32984 +#endif
32985 +       dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
32986 +
32987 +       dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base);
32988 +        DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n",
32989 +                    dwc_otg_device, dwc_otg_device->core_if);//GRAYG
32990 +        
32991 +       if (!dwc_otg_device->core_if) {
32992 +               dev_err(&_dev->dev, "CIL initialization failed!\n");
32993 +               retval = -ENOMEM;
32994 +               goto fail;
32995 +       }
32996 +
32997 +       dev_dbg(&_dev->dev, "Calling get_gsnpsid\n");
32998 +       /*
32999 +        * Attempt to ensure this device is really a DWC_otg Controller.
33000 +        * Read and verify the SNPSID register contents. The value should be
33001 +        * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3",
33002 +        * as in "OTG version 2.XX" or "OTG version 3.XX".
33003 +        */
33004 +
33005 +       if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=     0x4F542000) &&
33006 +               ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
33007 +               dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
33008 +                       dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
33009 +               retval = -EINVAL;
33010 +               goto fail;
33011 +       }
33012 +
33013 +       /*
33014 +        * Validate parameter values.
33015 +        */
33016 +       dev_dbg(&_dev->dev, "Calling set_parameters\n");
33017 +       if (set_parameters(dwc_otg_device->core_if)) {
33018 +               retval = -EINVAL;
33019 +               goto fail;
33020 +       }
33021 +
33022 +       /*
33023 +        * Create Device Attributes in sysfs
33024 +        */
33025 +       dev_dbg(&_dev->dev, "Calling attr_create\n");
33026 +       dwc_otg_attr_create(_dev);
33027 +
33028 +       /*
33029 +        * Disable the global interrupt until all the interrupt
33030 +        * handlers are installed.
33031 +        */
33032 +       dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n");
33033 +       dwc_otg_disable_global_interrupts(dwc_otg_device->core_if);
33034 +
33035 +       /*
33036 +        * Install the interrupt handler for the common interrupts before
33037 +        * enabling common interrupts in core_init below.
33038 +        */
33039 +        
33040 +#if defined(PLATFORM_INTERFACE)
33041 +        devirq = platform_get_irq(_dev, 0);
33042 +#else
33043 +        devirq = _dev->irq;
33044 +#endif
33045 +       DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
33046 +                   devirq);
33047 +       dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);
33048 +       retval = request_irq(devirq, dwc_otg_common_irq,
33049 +                             IRQF_SHARED,
33050 +                             "dwc_otg", dwc_otg_device);
33051 +       if (retval) {
33052 +               DWC_ERROR("request of irq%d failed\n", devirq);
33053 +               retval = -EBUSY;
33054 +               goto fail;
33055 +       } else {
33056 +               dwc_otg_device->common_irq_installed = 1;
33057 +       }
33058 +
33059 +#ifndef IRQF_TRIGGER_LOW
33060 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
33061 +       dev_dbg(&_dev->dev, "Calling set_irq_type\n");
33062 +       set_irq_type(devirq,
33063 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
33064 +                     IRQT_LOW
33065 +#else
33066 +                     IRQ_TYPE_LEVEL_LOW
33067 +#endif
33068 +                    );
33069 +#endif
33070 +#endif /*IRQF_TRIGGER_LOW*/
33071 +        
33072 +       /*
33073 +        * Initialize the DWC_otg core.
33074 +        */
33075 +       dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n");
33076 +       dwc_otg_core_init(dwc_otg_device->core_if);
33077 +               
33078 +#ifndef DWC_HOST_ONLY
33079 +       /*
33080 +        * Initialize the PCD
33081 +        */
33082 +       dev_dbg(&_dev->dev, "Calling pcd_init\n");
33083 +       retval = pcd_init(_dev);
33084 +       if (retval != 0) {
33085 +               DWC_ERROR("pcd_init failed\n");
33086 +               dwc_otg_device->pcd = NULL;
33087 +               goto fail;
33088 +       }       
33089 +#endif
33090 +#ifndef DWC_DEVICE_ONLY
33091 +       /*
33092 +        * Initialize the HCD
33093 +        */
33094 +       dev_dbg(&_dev->dev, "Calling hcd_init\n");
33095 +       retval = hcd_init(_dev);
33096 +       if (retval != 0) {
33097 +               DWC_ERROR("hcd_init failed\n");
33098 +               dwc_otg_device->hcd = NULL;
33099 +               goto fail;
33100 +       }
33101 +#endif
33102 +        /* Recover from drvdata having been overwritten by hcd_init() */
33103 +#ifdef LM_INTERFACE
33104 +       lm_set_drvdata(_dev, dwc_otg_device);
33105 +#elif defined(PLATFORM_INTERFACE)
33106 +       platform_set_drvdata(_dev, dwc_otg_device);
33107 +#elif defined(PCI_INTERFACE)
33108 +       pci_set_drvdata(_dev, dwc_otg_device);
33109 +       dwc_otg_device->os_dep.pcidev = _dev;
33110 +#endif
33111 +
33112 +       /*
33113 +        * Enable the global interrupt after all the interrupt
33114 +        * handlers are installed if there is no ADP support else 
33115 +        * perform initial actions required for Internal ADP logic.
33116 +        */
33117 +       if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {   
33118 +               dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n");
33119 +               dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
33120 +               dev_dbg(&_dev->dev, "Done\n");
33121 +       } else
33122 +               dwc_otg_adp_start(dwc_otg_device->core_if, 
33123 +                                                       dwc_otg_is_host_mode(dwc_otg_device->core_if));
33124 +
33125 +       return 0;
33126 +
33127 +fail:
33128 +       dwc_otg_driver_remove(_dev);
33129 +       return retval;
33130 +}
33131 +
33132 +/**
33133 + * This structure defines the methods to be called by a bus driver
33134 + * during the lifecycle of a device on that bus. Both drivers and
33135 + * devices are registered with a bus driver. The bus driver matches
33136 + * devices to drivers based on information in the device and driver
33137 + * structures.
33138 + *
33139 + * The probe function is called when the bus driver matches a device
33140 + * to this driver. The remove function is called when a device is
33141 + * unregistered with the bus driver.
33142 + */
33143 +#ifdef LM_INTERFACE
33144 +static struct lm_driver dwc_otg_driver = {
33145 +       .drv = {.name = (char *)dwc_driver_name,},
33146 +       .probe = dwc_otg_driver_probe,
33147 +       .remove = dwc_otg_driver_remove,
33148 +        // 'suspend' and 'resume' absent
33149 +};
33150 +#elif defined(PCI_INTERFACE)
33151 +static const struct pci_device_id pci_ids[] = { {
33152 +                                                PCI_DEVICE(0x16c3, 0xabcd),
33153 +                                                .driver_data =
33154 +                                                (unsigned long)0xdeadbeef,
33155 +                                                }, { /* end: all zeroes */ }
33156 +};
33157 +
33158 +MODULE_DEVICE_TABLE(pci, pci_ids);
33159 +
33160 +/* pci driver glue; this is a "new style" PCI driver module */
33161 +static struct pci_driver dwc_otg_driver = {
33162 +       .name = "dwc_otg",
33163 +       .id_table = pci_ids,
33164 +
33165 +       .probe = dwc_otg_driver_probe,
33166 +       .remove = dwc_otg_driver_remove,
33167 +
33168 +       .driver = {
33169 +                  .name = (char *)dwc_driver_name,
33170 +                  },
33171 +};
33172 +#elif defined(PLATFORM_INTERFACE)
33173 +static struct platform_device_id platform_ids[] = {
33174 +        {
33175 +              .name = "bcm2708_usb",
33176 +              .driver_data = (kernel_ulong_t) 0xdeadbeef,
33177 +        },
33178 +        { /* end: all zeroes */ }
33179 +};
33180 +MODULE_DEVICE_TABLE(platform, platform_ids);
33181 +
33182 +static struct platform_driver dwc_otg_driver = {
33183 +       .driver = {
33184 +               .name = (char *)dwc_driver_name,
33185 +               },
33186 +        .id_table = platform_ids,
33187 +                        
33188 +       .probe = dwc_otg_driver_probe,
33189 +       .remove = dwc_otg_driver_remove,
33190 +        // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early' 
33191 +};
33192 +#endif
33193 +
33194 +/**
33195 + * This function is called when the dwc_otg_driver is installed with the
33196 + * insmod command. It registers the dwc_otg_driver structure with the
33197 + * appropriate bus driver. This will cause the dwc_otg_driver_probe function
33198 + * to be called. In addition, the bus driver will automatically expose
33199 + * attributes defined for the device and driver in the special sysfs file
33200 + * system.
33201 + *
33202 + * @return
33203 + */
33204 +static int __init dwc_otg_driver_init(void)
33205 +{
33206 +       int retval = 0;
33207 +       int error;
33208 +        struct device_driver *drv;
33209 +       printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
33210 +              DWC_DRIVER_VERSION,
33211 +#ifdef LM_INTERFACE
33212 +               "logicmodule");
33213 +       retval = lm_driver_register(&dwc_otg_driver);
33214 +        drv = &dwc_otg_driver.drv;
33215 +#elif defined(PCI_INTERFACE)
33216 +               "pci");
33217 +       retval = pci_register_driver(&dwc_otg_driver);
33218 +        drv = &dwc_otg_driver.driver;
33219 +#elif defined(PLATFORM_INTERFACE)
33220 +               "platform");
33221 +       retval = platform_driver_register(&dwc_otg_driver);
33222 +        drv = &dwc_otg_driver.driver;
33223 +#endif
33224 +       if (retval < 0) {
33225 +               printk(KERN_ERR "%s retval=%d\n", __func__, retval);
33226 +               return retval;
33227 +       }
33228 +
33229 +       error = driver_create_file(drv, &driver_attr_version);
33230 +#ifdef DEBUG
33231 +       error = driver_create_file(drv, &driver_attr_debuglevel);
33232 +#endif
33233 +       return retval;
33234 +}
33235 +
33236 +module_init(dwc_otg_driver_init);
33237 +
33238 +/**
33239 + * This function is called when the driver is removed from the kernel
33240 + * with the rmmod command. The driver unregisters itself with its bus
33241 + * driver.
33242 + *
33243 + */
33244 +static void __exit dwc_otg_driver_cleanup(void)
33245 +{
33246 +       printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");
33247 +
33248 +#ifdef LM_INTERFACE
33249 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);
33250 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version);
33251 +       lm_driver_unregister(&dwc_otg_driver);
33252 +#elif defined(PCI_INTERFACE)
33253 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
33254 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
33255 +       pci_unregister_driver(&dwc_otg_driver);
33256 +#elif defined(PLATFORM_INTERFACE)
33257 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
33258 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
33259 +       platform_driver_unregister(&dwc_otg_driver);
33260 +#endif
33261 +
33262 +       printk(KERN_INFO "%s module removed\n", dwc_driver_name);
33263 +}
33264 +
33265 +module_exit(dwc_otg_driver_cleanup);
33266 +
33267 +MODULE_DESCRIPTION(DWC_DRIVER_DESC);
33268 +MODULE_AUTHOR("Synopsys Inc.");
33269 +MODULE_LICENSE("GPL");
33270 +
33271 +module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);
33272 +MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");
33273 +module_param_named(opt, dwc_otg_module_params.opt, int, 0444);
33274 +MODULE_PARM_DESC(opt, "OPT Mode");
33275 +module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);
33276 +MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");
33277 +
33278 +module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int,
33279 +                  0444);
33280 +MODULE_PARM_DESC(dma_desc_enable,
33281 +                "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");
33282 +
33283 +module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int,
33284 +                  0444);
33285 +MODULE_PARM_DESC(dma_burst_size,
33286 +                "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");
33287 +module_param_named(speed, dwc_otg_module_params.speed, int, 0444);
33288 +MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");
33289 +module_param_named(host_support_fs_ls_low_power,
33290 +                  dwc_otg_module_params.host_support_fs_ls_low_power, int,
33291 +                  0444);
33292 +MODULE_PARM_DESC(host_support_fs_ls_low_power,
33293 +                "Support Low Power w/FS or LS 0=Support 1=Don't Support");
33294 +module_param_named(host_ls_low_power_phy_clk,
33295 +                  dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);
33296 +MODULE_PARM_DESC(host_ls_low_power_phy_clk,
33297 +                "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");
33298 +module_param_named(enable_dynamic_fifo,
33299 +                  dwc_otg_module_params.enable_dynamic_fifo, int, 0444);
33300 +MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");
33301 +module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int,
33302 +                  0444);
33303 +MODULE_PARM_DESC(data_fifo_size,
33304 +                "Total number of words in the data FIFO memory 32-32768");
33305 +module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size,
33306 +                  int, 0444);
33307 +MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33308 +module_param_named(dev_nperio_tx_fifo_size,
33309 +                  dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);
33310 +MODULE_PARM_DESC(dev_nperio_tx_fifo_size,
33311 +                "Number of words in the non-periodic Tx FIFO 16-32768");
33312 +module_param_named(dev_perio_tx_fifo_size_1,
33313 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);
33314 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_1,
33315 +                "Number of words in the periodic Tx FIFO 4-768");
33316 +module_param_named(dev_perio_tx_fifo_size_2,
33317 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);
33318 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_2,
33319 +                "Number of words in the periodic Tx FIFO 4-768");
33320 +module_param_named(dev_perio_tx_fifo_size_3,
33321 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);
33322 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_3,
33323 +                "Number of words in the periodic Tx FIFO 4-768");
33324 +module_param_named(dev_perio_tx_fifo_size_4,
33325 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);
33326 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_4,
33327 +                "Number of words in the periodic Tx FIFO 4-768");
33328 +module_param_named(dev_perio_tx_fifo_size_5,
33329 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);
33330 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_5,
33331 +                "Number of words in the periodic Tx FIFO 4-768");
33332 +module_param_named(dev_perio_tx_fifo_size_6,
33333 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);
33334 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_6,
33335 +                "Number of words in the periodic Tx FIFO 4-768");
33336 +module_param_named(dev_perio_tx_fifo_size_7,
33337 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);
33338 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_7,
33339 +                "Number of words in the periodic Tx FIFO 4-768");
33340 +module_param_named(dev_perio_tx_fifo_size_8,
33341 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);
33342 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_8,
33343 +                "Number of words in the periodic Tx FIFO 4-768");
33344 +module_param_named(dev_perio_tx_fifo_size_9,
33345 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);
33346 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_9,
33347 +                "Number of words in the periodic Tx FIFO 4-768");
33348 +module_param_named(dev_perio_tx_fifo_size_10,
33349 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);
33350 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_10,
33351 +                "Number of words in the periodic Tx FIFO 4-768");
33352 +module_param_named(dev_perio_tx_fifo_size_11,
33353 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);
33354 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_11,
33355 +                "Number of words in the periodic Tx FIFO 4-768");
33356 +module_param_named(dev_perio_tx_fifo_size_12,
33357 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444);
33358 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_12,
33359 +                "Number of words in the periodic Tx FIFO 4-768");
33360 +module_param_named(dev_perio_tx_fifo_size_13,
33361 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444);
33362 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_13,
33363 +                "Number of words in the periodic Tx FIFO 4-768");
33364 +module_param_named(dev_perio_tx_fifo_size_14,
33365 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444);
33366 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_14,
33367 +                "Number of words in the periodic Tx FIFO 4-768");
33368 +module_param_named(dev_perio_tx_fifo_size_15,
33369 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444);
33370 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_15,
33371 +                "Number of words in the periodic Tx FIFO 4-768");
33372 +module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size,
33373 +                  int, 0444);
33374 +MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33375 +module_param_named(host_nperio_tx_fifo_size,
33376 +                  dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444);
33377 +MODULE_PARM_DESC(host_nperio_tx_fifo_size,
33378 +                "Number of words in the non-periodic Tx FIFO 16-32768");
33379 +module_param_named(host_perio_tx_fifo_size,
33380 +                  dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444);
33381 +MODULE_PARM_DESC(host_perio_tx_fifo_size,
33382 +                "Number of words in the host periodic Tx FIFO 16-32768");
33383 +module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size,
33384 +                  int, 0444);
33385 +/** @todo Set the max to 512K, modify checks */
33386 +MODULE_PARM_DESC(max_transfer_size,
33387 +                "The maximum transfer size supported in bytes 2047-65535");
33388 +module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count,
33389 +                  int, 0444);
33390 +MODULE_PARM_DESC(max_packet_count,
33391 +                "The maximum number of packets in a transfer 15-511");
33392 +module_param_named(host_channels, dwc_otg_module_params.host_channels, int,
33393 +                  0444);
33394 +MODULE_PARM_DESC(host_channels,
33395 +                "The number of host channel registers to use 1-16");
33396 +module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int,
33397 +                  0444);
33398 +MODULE_PARM_DESC(dev_endpoints,
33399 +                "The number of endpoints in addition to EP0 available for device mode 1-15");
33400 +module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444);
33401 +MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI");
33402 +module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int,
33403 +                  0444);
33404 +MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");
33405 +module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444);
33406 +MODULE_PARM_DESC(phy_ulpi_ddr,
33407 +                "ULPI at double or single data rate 0=Single 1=Double");
33408 +module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus,
33409 +                  int, 0444);
33410 +MODULE_PARM_DESC(phy_ulpi_ext_vbus,
33411 +                "ULPI PHY using internal or external vbus 0=Internal");
33412 +module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444);
33413 +MODULE_PARM_DESC(i2c_enable, "FS PHY Interface");
33414 +module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444);
33415 +MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only");
33416 +module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444);
33417 +MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs");
33418 +module_param_named(debug, g_dbg_lvl, int, 0444);
33419 +MODULE_PARM_DESC(debug, "");
33420 +
33421 +module_param_named(en_multiple_tx_fifo,
33422 +                  dwc_otg_module_params.en_multiple_tx_fifo, int, 0444);
33423 +MODULE_PARM_DESC(en_multiple_tx_fifo,
33424 +                "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled");
33425 +module_param_named(dev_tx_fifo_size_1,
33426 +                  dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444);
33427 +MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768");
33428 +module_param_named(dev_tx_fifo_size_2,
33429 +                  dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444);
33430 +MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768");
33431 +module_param_named(dev_tx_fifo_size_3,
33432 +                  dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444);
33433 +MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768");
33434 +module_param_named(dev_tx_fifo_size_4,
33435 +                  dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444);
33436 +MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768");
33437 +module_param_named(dev_tx_fifo_size_5,
33438 +                  dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444);
33439 +MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768");
33440 +module_param_named(dev_tx_fifo_size_6,
33441 +                  dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444);
33442 +MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768");
33443 +module_param_named(dev_tx_fifo_size_7,
33444 +                  dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444);
33445 +MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768");
33446 +module_param_named(dev_tx_fifo_size_8,
33447 +                  dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444);
33448 +MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768");
33449 +module_param_named(dev_tx_fifo_size_9,
33450 +                  dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444);
33451 +MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768");
33452 +module_param_named(dev_tx_fifo_size_10,
33453 +                  dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444);
33454 +MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768");
33455 +module_param_named(dev_tx_fifo_size_11,
33456 +                  dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444);
33457 +MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768");
33458 +module_param_named(dev_tx_fifo_size_12,
33459 +                  dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444);
33460 +MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768");
33461 +module_param_named(dev_tx_fifo_size_13,
33462 +                  dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444);
33463 +MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768");
33464 +module_param_named(dev_tx_fifo_size_14,
33465 +                  dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444);
33466 +MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768");
33467 +module_param_named(dev_tx_fifo_size_15,
33468 +                  dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444);
33469 +MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768");
33470 +
33471 +module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444);
33472 +MODULE_PARM_DESC(thr_ctl,
33473 +                "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled");
33474 +module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int,
33475 +                  0444);
33476 +MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs");
33477 +module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int,
33478 +                  0444);
33479 +MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs");
33480 +
33481 +module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444);
33482 +module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444);
33483 +module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444);
33484 +MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled");
33485 +module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444);
33486 +MODULE_PARM_DESC(ic_usb_cap,
33487 +                "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled");
33488 +module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int,
33489 +                  0444);
33490 +MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio");
33491 +module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444);
33492 +MODULE_PARM_DESC(power_down, "Power Down Mode");
33493 +module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444);
33494 +MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control");
33495 +module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444);
33496 +MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK");
33497 +module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444);
33498 +MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA");
33499 +module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444);
33500 +MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support");
33501 +module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444);
33502 +MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled");
33503 +module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444);
33504 +MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
33505 +module_param(microframe_schedule, bool, 0444);
33506 +MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
33507 +
33508 +/** @page "Module Parameters"
33509 + *
33510 + * The following parameters may be specified when starting the module.
33511 + * These parameters define how the DWC_otg controller should be
33512 + * configured. Parameter values are passed to the CIL initialization
33513 + * function dwc_otg_cil_init
33514 + *
33515 + * Example: <code>modprobe dwc_otg speed=1 otg_cap=1</code>
33516 + *
33517 +
33518 + <table>
33519 + <tr><td>Parameter Name</td><td>Meaning</td></tr>
33520 +
33521 + <tr>
33522 + <td>otg_cap</td>
33523 + <td>Specifies the OTG capabilities. The driver will automatically detect the
33524 + value for this parameter if none is specified.
33525 + - 0: HNP and SRP capable (default, if available)
33526 + - 1: SRP Only capable
33527 + - 2: No HNP/SRP capable
33528 + </td></tr>
33529 +
33530 + <tr>
33531 + <td>dma_enable</td>
33532 + <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs.
33533 + The driver will automatically detect the value for this parameter if none is
33534 + specified.
33535 + - 0: Slave
33536 + - 1: DMA (default, if available)
33537 + </td></tr>
33538 +
33539 + <tr>
33540 + <td>dma_burst_size</td>
33541 + <td>The DMA Burst size (applicable only for External DMA Mode).
33542 + - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32)
33543 + </td></tr>
33544 +
33545 + <tr>
33546 + <td>speed</td>
33547 + <td>Specifies the maximum speed of operation in host and device mode. The
33548 + actual speed depends on the speed of the attached device and the value of
33549 + phy_type.
33550 + - 0: High Speed (default)
33551 + - 1: Full Speed
33552 + </td></tr>
33553 +
33554 + <tr>
33555 + <td>host_support_fs_ls_low_power</td>
33556 + <td>Specifies whether low power mode is supported when attached to a Full
33557 + Speed or Low Speed device in host mode.
33558 + - 0: Don't support low power mode (default)
33559 + - 1: Support low power mode
33560 + </td></tr>
33561 +
33562 + <tr>
33563 + <td>host_ls_low_power_phy_clk</td>
33564 + <td>Specifies the PHY clock rate in low power mode when connected to a Low
33565 + Speed device in host mode. This parameter is applicable only if
33566 + HOST_SUPPORT_FS_LS_LOW_POWER is enabled.
33567 + - 0: 48 MHz (default)
33568 + - 1: 6 MHz
33569 + </td></tr>
33570 +
33571 + <tr>
33572 + <td>enable_dynamic_fifo</td>
33573 + <td> Specifies whether FIFOs may be resized by the driver software.
33574 + - 0: Use cC FIFO size parameters
33575 + - 1: Allow dynamic FIFO sizing (default)
33576 + </td></tr>
33577 +
33578 + <tr>
33579 + <td>data_fifo_size</td>
33580 + <td>Total number of 4-byte words in the data FIFO memory. This memory
33581 + includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs.
33582 + - Values: 32 to 32768 (default 8192)
33583 +
33584 + Note: The total FIFO memory depth in the FPGA configuration is 8192.
33585 + </td></tr>
33586 +
33587 + <tr>
33588 + <td>dev_rx_fifo_size</td>
33589 + <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic
33590 + FIFO sizing is enabled.
33591 + - Values: 16 to 32768 (default 1064)
33592 + </td></tr>
33593 +
33594 + <tr>
33595 + <td>dev_nperio_tx_fifo_size</td>
33596 + <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when
33597 + dynamic FIFO sizing is enabled.
33598 + - Values: 16 to 32768 (default 1024)
33599 + </td></tr>
33600 +
33601 + <tr>
33602 + <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td>
33603 + <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode
33604 + when dynamic FIFO sizing is enabled.
33605 + - Values: 4 to 768 (default 256)
33606 + </td></tr>
33607 +
33608 + <tr>
33609 + <td>host_rx_fifo_size</td>
33610 + <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO
33611 + sizing is enabled.
33612 + - Values: 16 to 32768 (default 1024)
33613 + </td></tr>
33614 +
33615 + <tr>
33616 + <td>host_nperio_tx_fifo_size</td>
33617 + <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when
33618 + dynamic FIFO sizing is enabled in the core.
33619 + - Values: 16 to 32768 (default 1024)
33620 + </td></tr>
33621 +
33622 + <tr>
33623 + <td>host_perio_tx_fifo_size</td>
33624 + <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO
33625 + sizing is enabled.
33626 + - Values: 16 to 32768 (default 1024)
33627 + </td></tr>
33628 +
33629 + <tr>
33630 + <td>max_transfer_size</td>
33631 + <td>The maximum transfer size supported in bytes.
33632 + - Values: 2047 to 65,535 (default 65,535)
33633 + </td></tr>
33634 +
33635 + <tr>
33636 + <td>max_packet_count</td>
33637 + <td>The maximum number of packets in a transfer.
33638 + - Values: 15 to 511 (default 511)
33639 + </td></tr>
33640 +
33641 + <tr>
33642 + <td>host_channels</td>
33643 + <td>The number of host channel registers to use.
33644 + - Values: 1 to 16 (default 12)
33645 +
33646 + Note: The FPGA configuration supports a maximum of 12 host channels.
33647 + </td></tr>
33648 +
33649 + <tr>
33650 + <td>dev_endpoints</td>
33651 + <td>The number of endpoints in addition to EP0 available for device mode
33652 + operations.
33653 + - Values: 1 to 15 (default 6 IN and OUT)
33654 +
33655 + Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in
33656 + addition to EP0.
33657 + </td></tr>
33658 +
33659 + <tr>
33660 + <td>phy_type</td>
33661 + <td>Specifies the type of PHY interface to use. By default, the driver will
33662 + automatically detect the phy_type.
33663 + - 0: Full Speed
33664 + - 1: UTMI+ (default, if available)
33665 + - 2: ULPI
33666 + </td></tr>
33667 +
33668 + <tr>
33669 + <td>phy_utmi_width</td>
33670 + <td>Specifies the UTMI+ Data Width. This parameter is applicable for a
33671 + phy_type of UTMI+. Also, this parameter is applicable only if the
33672 + OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the
33673 + core has been configured to work at either data path width.
33674 + - Values: 8 or 16 bits (default 16)
33675 + </td></tr>
33676 +
33677 + <tr>
33678 + <td>phy_ulpi_ddr</td>
33679 + <td>Specifies whether the ULPI operates at double or single data rate. This
33680 + parameter is only applicable if phy_type is ULPI.
33681 + - 0: single data rate ULPI interface with 8 bit wide data bus (default)
33682 + - 1: double data rate ULPI interface with 4 bit wide data bus
33683 + </td></tr>
33684 +
33685 + <tr>
33686 + <td>i2c_enable</td>
33687 + <td>Specifies whether to use the I2C interface for full speed PHY. This
33688 + parameter is only applicable if PHY_TYPE is FS.
33689 + - 0: Disabled (default)
33690 + - 1: Enabled
33691 + </td></tr>
33692 +
33693 + <tr>
33694 + <td>ulpi_fs_ls</td>
33695 + <td>Specifies whether to use ULPI FS/LS mode only.
33696 + - 0: Disabled (default)
33697 + - 1: Enabled
33698 + </td></tr>
33699 +
33700 + <tr>
33701 + <td>ts_dline</td>
33702 + <td>Specifies whether term select D-Line pulsing for all PHYs is enabled.
33703 + - 0: Disabled (default)
33704 + - 1: Enabled
33705 + </td></tr>
33706
33707 + <tr>
33708 + <td>en_multiple_tx_fifo</td>
33709 + <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.
33710 + The driver will automatically detect the value for this parameter if none is
33711 + specified.
33712 + - 0: Disabled
33713 + - 1: Enabled (default, if available)
33714 + </td></tr>
33715 +
33716 + <tr>
33717 + <td>dev_tx_fifo_size_n (n = 1 to 15)</td>
33718 + <td>Number of 4-byte words in each of the Tx FIFOs in device mode
33719 + when dynamic FIFO sizing is enabled.
33720 + - Values: 4 to 768 (default 256)
33721 + </td></tr>
33722 +
33723 + <tr>
33724 + <td>tx_thr_length</td>
33725 + <td>Transmit Threshold length in 32 bit double words
33726 + - Values: 8 to 128 (default 64)
33727 + </td></tr>
33728 +
33729 + <tr>
33730 + <td>rx_thr_length</td>
33731 + <td>Receive Threshold length in 32 bit double words
33732 + - Values: 8 to 128 (default 64)
33733 + </td></tr>
33734 +
33735 +<tr>
33736 + <td>thr_ctl</td>
33737 + <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of 
33738 + this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and
33739 + Rx transfers accordingly.
33740 + The driver will automatically detect the value for this parameter if none is
33741 + specified.
33742 + - Values: 0 to 7 (default 0)
33743 + Bit values indicate:
33744 + - 0: Thresholding disabled
33745 + - 1: Thresholding enabled
33746 + </td></tr>
33747 +
33748 +<tr>
33749 + <td>dma_desc_enable</td>
33750 + <td>Specifies whether to enable Descriptor DMA mode.
33751 + The driver will automatically detect the value for this parameter if none is
33752 + specified.
33753 + - 0: Descriptor DMA disabled
33754 + - 1: Descriptor DMA (default, if available)
33755 + </td></tr>
33756 +
33757 +<tr>
33758 + <td>mpi_enable</td>
33759 + <td>Specifies whether to enable MPI enhancement mode.
33760 + The driver will automatically detect the value for this parameter if none is
33761 + specified.
33762 + - 0: MPI disabled (default)
33763 + - 1: MPI enable
33764 + </td></tr>
33765 +
33766 +<tr>
33767 + <td>pti_enable</td>
33768 + <td>Specifies whether to enable PTI enhancement support.
33769 + The driver will automatically detect the value for this parameter if none is
33770 + specified.
33771 + - 0: PTI disabled (default)
33772 + - 1: PTI enable
33773 + </td></tr>
33774 +
33775 +<tr>
33776 + <td>lpm_enable</td>
33777 + <td>Specifies whether to enable LPM support.
33778 + The driver will automatically detect the value for this parameter if none is
33779 + specified.
33780 + - 0: LPM disabled
33781 + - 1: LPM enable (default, if available)
33782 + </td></tr>
33783 +
33784 +<tr>
33785 + <td>ic_usb_cap</td>
33786 + <td>Specifies whether to enable IC_USB capability.
33787 + The driver will automatically detect the value for this parameter if none is
33788 + specified.
33789 + - 0: IC_USB disabled (default, if available)
33790 + - 1: IC_USB enable 
33791 + </td></tr>
33792 +
33793 +<tr>
33794 + <td>ahb_thr_ratio</td>
33795 + <td>Specifies AHB Threshold ratio.
33796 + - Values: 0 to 3 (default 0)
33797 + </td></tr>
33798 +
33799 +<tr>
33800 + <td>power_down</td>
33801 + <td>Specifies Power Down(Hibernation) Mode.
33802 + The driver will automatically detect the value for this parameter if none is
33803 + specified.
33804 + - 0: Power Down disabled (default)
33805 + - 2: Power Down enabled
33806 + </td></tr>
33807
33808 + <tr>
33809 + <td>reload_ctl</td>
33810 + <td>Specifies whether dynamic reloading of the HFIR register is allowed during
33811 + run time. The driver will automatically detect the value for this parameter if
33812 + none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0
33813 + the core might misbehave.
33814 + - 0: Reload Control disabled (default)
33815 + - 1: Reload Control enabled
33816 + </td></tr>
33817 +
33818 + <tr>
33819 + <td>dev_out_nak</td>
33820 + <td>Specifies whether  Device OUT NAK enhancement enabled or no.
33821 + The driver will automatically detect the value for this parameter if
33822 + none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33823 + - 0: The core does not set NAK after Bulk OUT transfer complete (default)
33824 + - 1: The core sets NAK after Bulk OUT transfer complete
33825 + </td></tr>
33826 +
33827 + <tr>
33828 + <td>cont_on_bna</td>
33829 + <td>Specifies whether Enable Continue on BNA enabled or no. 
33830 + After receiving BNA interrupt the core disables the endpoint,when the
33831 + endpoint is re-enabled by the application the  
33832 + - 0: Core starts processing from the DOEPDMA descriptor (default)
33833 + - 1: Core starts processing from the descriptor which received the BNA.
33834 + This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33835 + </td></tr>
33836 +
33837 + <tr>
33838 + <td>ahb_single</td>
33839 + <td>This bit when programmed supports SINGLE transfers for remainder data
33840 + in a transfer for DMA mode of operation. 
33841 + - 0: The remainder data will be sent using INCR burst size (default)
33842 + - 1: The remainder data will be sent using SINGLE burst size.
33843 + </td></tr>
33844 +
33845 +<tr>
33846 + <td>adp_enable</td>
33847 + <td>Specifies whether ADP feature is enabled.
33848 + The driver will automatically detect the value for this parameter if none is
33849 + specified.
33850 + - 0: ADP feature disabled (default)
33851 + - 1: ADP feature enabled
33852 + </td></tr>
33853 +
33854 +  <tr>
33855 + <td>otg_ver</td>
33856 + <td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3
33857 + USB OTG device.
33858 + - 0: OTG 2.0 support disabled (default)
33859 + - 1: OTG 2.0 support enabled 
33860 + </td></tr>
33861 +
33862 +*/
33863 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.h b/drivers/usb/host/dwc_otg/dwc_otg_driver.h
33864 new file mode 100644
33865 index 0000000..8a0e41b
33866 --- /dev/null
33867 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h
33868 @@ -0,0 +1,86 @@
33869 +/* ==========================================================================
33870 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
33871 + * $Revision: #19 $
33872 + * $Date: 2010/11/15 $
33873 + * $Change: 1627671 $
33874 + *
33875 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33876 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33877 + * otherwise expressly agreed to in writing between Synopsys and you.
33878 + * 
33879 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33880 + * any End User Software License Agreement or Agreement for Licensed Product
33881 + * with Synopsys or any supplement thereto. You are permitted to use and
33882 + * redistribute this Software in source and binary forms, with or without
33883 + * modification, provided that redistributions of source code must retain this
33884 + * notice. You may not view, use, disclose, copy or distribute this file or
33885 + * any information contained herein except pursuant to this license grant from
33886 + * Synopsys. If you do not agree with this notice, including the disclaimer
33887 + * below, then you are not authorized to use the Software.
33888 + * 
33889 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33890 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33891 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33892 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33893 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33894 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33895 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33896 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33897 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33898 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33899 + * DAMAGE.
33900 + * ========================================================================== */
33901 +
33902 +#ifndef __DWC_OTG_DRIVER_H__
33903 +#define __DWC_OTG_DRIVER_H__
33904 +
33905 +/** @file
33906 + * This file contains the interface to the Linux driver.
33907 + */
33908 +#include "dwc_otg_os_dep.h"
33909 +#include "dwc_otg_core_if.h"
33910 +
33911 +/* Type declarations */
33912 +struct dwc_otg_pcd;
33913 +struct dwc_otg_hcd;
33914 +
33915 +/**
33916 + * This structure is a wrapper that encapsulates the driver components used to
33917 + * manage a single DWC_otg controller.
33918 + */
33919 +typedef struct dwc_otg_device {
33920 +       /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE
33921 +        * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD
33922 +        * require this. */
33923 +       struct os_dependent os_dep;
33924 +
33925 +       /** Pointer to the core interface structure. */
33926 +       dwc_otg_core_if_t *core_if;
33927 +
33928 +       /** Pointer to the PCD structure. */
33929 +       struct dwc_otg_pcd *pcd;
33930 +
33931 +       /** Pointer to the HCD structure. */
33932 +       struct dwc_otg_hcd *hcd;
33933 +
33934 +       /** Flag to indicate whether the common IRQ handler is installed. */
33935 +       uint8_t common_irq_installed;
33936 +
33937 +} dwc_otg_device_t;
33938 +
33939 +/*We must clear S3C24XX_EINTPEND external interrupt register 
33940 + * because after clearing in this register trigerred IRQ from 
33941 + * H/W core in kernel interrupt can be occured again before OTG
33942 + * handlers clear all IRQ sources of Core registers because of
33943 + * timing latencies and Low Level IRQ Type.
33944 + */
33945 +#ifdef CONFIG_MACH_IPMATE
33946 +#define  S3C2410X_CLEAR_EINTPEND()   \
33947 +do { \
33948 +       __raw_writel(1UL << 11,S3C24XX_EINTPEND); \
33949 +} while (0)
33950 +#else
33951 +#define  S3C2410X_CLEAR_EINTPEND()   do { } while (0)
33952 +#endif
33953 +
33954 +#endif
33955 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
33956 new file mode 100644
33957 index 0000000..434d0c4
33958 --- /dev/null
33959 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
33960 @@ -0,0 +1,3473 @@
33961 +
33962 +/* ==========================================================================
33963 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
33964 + * $Revision: #104 $
33965 + * $Date: 2011/10/24 $
33966 + * $Change: 1871159 $
33967 + *
33968 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33969 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33970 + * otherwise expressly agreed to in writing between Synopsys and you.
33971 + *
33972 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33973 + * any End User Software License Agreement or Agreement for Licensed Product
33974 + * with Synopsys or any supplement thereto. You are permitted to use and
33975 + * redistribute this Software in source and binary forms, with or without
33976 + * modification, provided that redistributions of source code must retain this
33977 + * notice. You may not view, use, disclose, copy or distribute this file or
33978 + * any information contained herein except pursuant to this license grant from
33979 + * Synopsys. If you do not agree with this notice, including the disclaimer
33980 + * below, then you are not authorized to use the Software.
33981 + *
33982 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33983 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33984 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33985 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33986 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33987 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33988 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33989 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33990 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33991 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33992 + * DAMAGE.
33993 + * ========================================================================== */
33994 +#ifndef DWC_DEVICE_ONLY
33995 +
33996 +/** @file
33997 + * This file implements HCD Core. All code in this file is portable and doesn't
33998 + * use any OS specific functions.
33999 + * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
34000 + * header file.
34001 + */
34002 +
34003 +#include "dwc_otg_hcd.h"
34004 +#include "dwc_otg_regs.h"
34005 +
34006 +extern bool microframe_schedule;
34007 +
34008 +//#define DEBUG_HOST_CHANNELS
34009 +#ifdef DEBUG_HOST_CHANNELS
34010 +static int last_sel_trans_num_per_scheduled = 0;
34011 +static int last_sel_trans_num_nonper_scheduled = 0;
34012 +static int last_sel_trans_num_avail_hc_at_start = 0;
34013 +static int last_sel_trans_num_avail_hc_at_end = 0;
34014 +#endif /* DEBUG_HOST_CHANNELS */
34015 +
34016 +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
34017 +{
34018 +       return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
34019 +}
34020 +
34021 +/**
34022 + * Connection timeout function.  An OTG host is required to display a
34023 + * message if the device does not connect within 10 seconds.
34024 + */
34025 +void dwc_otg_hcd_connect_timeout(void *ptr)
34026 +{
34027 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
34028 +       DWC_PRINTF("Connect Timeout\n");
34029 +       __DWC_ERROR("Device Not Connected/Responding\n");
34030 +}
34031 +
34032 +#if defined(DEBUG)
34033 +static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
34034 +{
34035 +       if (qh->channel != NULL) {
34036 +               dwc_hc_t *hc = qh->channel;
34037 +               dwc_list_link_t *item;
34038 +               dwc_otg_qh_t *qh_item;
34039 +               int num_channels = hcd->core_if->core_params->host_channels;
34040 +               int i;
34041 +
34042 +               dwc_otg_hc_regs_t *hc_regs;
34043 +               hcchar_data_t hcchar;
34044 +               hcsplt_data_t hcsplt;
34045 +               hctsiz_data_t hctsiz;
34046 +               uint32_t hcdma;
34047 +
34048 +               hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
34049 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
34050 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
34051 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
34052 +               hcdma = DWC_READ_REG32(&hc_regs->hcdma);
34053 +
34054 +               DWC_PRINTF("  Assigned to channel %p:\n", hc);
34055 +               DWC_PRINTF("    hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
34056 +                          hcsplt.d32);
34057 +               DWC_PRINTF("    hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
34058 +                          hcdma);
34059 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
34060 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
34061 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
34062 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
34063 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
34064 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
34065 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
34066 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
34067 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
34068 +               DWC_PRINTF("    qh: %p\n", hc->qh);
34069 +               DWC_PRINTF("  NP inactive sched:\n");
34070 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
34071 +                       qh_item =
34072 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34073 +                       DWC_PRINTF("    %p\n", qh_item);
34074 +               }
34075 +               DWC_PRINTF("  NP active sched:\n");
34076 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
34077 +                       qh_item =
34078 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34079 +                       DWC_PRINTF("    %p\n", qh_item);
34080 +               }
34081 +               DWC_PRINTF("  Channels: \n");
34082 +               for (i = 0; i < num_channels; i++) {
34083 +                       dwc_hc_t *hc = hcd->hc_ptr_array[i];
34084 +                       DWC_PRINTF("    %2d: %p\n", i, hc);
34085 +               }
34086 +       }
34087 +}
34088 +#else
34089 +#define dump_channel_info(hcd, qh)
34090 +#endif /* DEBUG */
34091 +
34092 +/**
34093 + * Work queue function for starting the HCD when A-Cable is connected.
34094 + * The hcd_start() must be called in a process context.
34095 + */
34096 +static void hcd_start_func(void *_vp)
34097 +{
34098 +       dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
34099 +
34100 +       DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
34101 +       if (hcd) {
34102 +               hcd->fops->start(hcd);
34103 +       }
34104 +}
34105 +
34106 +static void del_xfer_timers(dwc_otg_hcd_t * hcd)
34107 +{
34108 +#ifdef DEBUG
34109 +       int i;
34110 +       int num_channels = hcd->core_if->core_params->host_channels;
34111 +       for (i = 0; i < num_channels; i++) {
34112 +               DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
34113 +       }
34114 +#endif
34115 +}
34116 +
34117 +static void del_timers(dwc_otg_hcd_t * hcd)
34118 +{
34119 +       del_xfer_timers(hcd);
34120 +       DWC_TIMER_CANCEL(hcd->conn_timer);
34121 +}
34122 +
34123 +/**
34124 + * Processes all the URBs in a single list of QHs. Completes them with
34125 + * -ETIMEDOUT and frees the QTD.
34126 + */
34127 +static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
34128 +{
34129 +       dwc_list_link_t *qh_item;
34130 +       dwc_otg_qh_t *qh;
34131 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
34132 +
34133 +       DWC_LIST_FOREACH(qh_item, qh_list) {
34134 +               qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
34135 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
34136 +                                        &qh->qtd_list, qtd_list_entry) {
34137 +                       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
34138 +                       if (qtd->urb != NULL) {
34139 +                               hcd->fops->complete(hcd, qtd->urb->priv,
34140 +                                                   qtd->urb, -DWC_E_TIMEOUT);
34141 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
34142 +                       }
34143 +
34144 +               }
34145 +       }
34146 +}
34147 +
34148 +/**
34149 + * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
34150 + * and periodic schedules. The QTD associated with each URB is removed from
34151 + * the schedule and freed. This function may be called when a disconnect is
34152 + * detected or when the HCD is being stopped.
34153 + */
34154 +static void kill_all_urbs(dwc_otg_hcd_t * hcd)
34155 +{
34156 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
34157 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
34158 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
34159 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
34160 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
34161 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
34162 +}
34163 +
34164 +/**
34165 + * Start the connection timer.  An OTG host is required to display a
34166 + * message if the device does not connect within 10 seconds.  The
34167 + * timer is deleted if a port connect interrupt occurs before the
34168 + * timer expires.
34169 + */
34170 +static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
34171 +{
34172 +       DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
34173 +}
34174 +
34175 +/**
34176 + * HCD Callback function for disconnect of the HCD.
34177 + *
34178 + * @param p void pointer to the <code>struct usb_hcd</code>
34179 + */
34180 +static int32_t dwc_otg_hcd_session_start_cb(void *p)
34181 +{
34182 +       dwc_otg_hcd_t *dwc_otg_hcd;
34183 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34184 +       dwc_otg_hcd = p;
34185 +       dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
34186 +       return 1;
34187 +}
34188 +
34189 +/**
34190 + * HCD Callback function for starting the HCD when A-Cable is
34191 + * connected.
34192 + *
34193 + * @param p void pointer to the <code>struct usb_hcd</code>
34194 + */
34195 +static int32_t dwc_otg_hcd_start_cb(void *p)
34196 +{
34197 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34198 +       dwc_otg_core_if_t *core_if;
34199 +       hprt0_data_t hprt0;
34200 +
34201 +       core_if = dwc_otg_hcd->core_if;
34202 +
34203 +       if (core_if->op_state == B_HOST) {
34204 +               /*
34205 +                * Reset the port.  During a HNP mode switch the reset
34206 +                * needs to occur within 1ms and have a duration of at
34207 +                * least 50ms.
34208 +                */
34209 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
34210 +               hprt0.b.prtrst = 1;
34211 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34212 +       }
34213 +       DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
34214 +                                  hcd_start_func, dwc_otg_hcd, 50,
34215 +                                  "start hcd");
34216 +
34217 +       return 1;
34218 +}
34219 +
34220 +/**
34221 + * HCD Callback function for disconnect of the HCD.
34222 + *
34223 + * @param p void pointer to the <code>struct usb_hcd</code>
34224 + */
34225 +static int32_t dwc_otg_hcd_disconnect_cb(void *p)
34226 +{
34227 +       gintsts_data_t intr;
34228 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34229 +
34230 +       /*
34231 +        * Set status flags for the hub driver.
34232 +        */
34233 +       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
34234 +       dwc_otg_hcd->flags.b.port_connect_status = 0;
34235 +
34236 +       /*
34237 +        * Shutdown any transfers in process by clearing the Tx FIFO Empty
34238 +        * interrupt mask and status bits and disabling subsequent host
34239 +        * channel interrupts.
34240 +        */
34241 +       intr.d32 = 0;
34242 +       intr.b.nptxfempty = 1;
34243 +       intr.b.ptxfempty = 1;
34244 +       intr.b.hcintr = 1;
34245 +       DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
34246 +                        intr.d32, 0);
34247 +       DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
34248 +                        intr.d32, 0);
34249 +
34250 +       del_timers(dwc_otg_hcd);
34251 +
34252 +       /*
34253 +        * Turn off the vbus power only if the core has transitioned to device
34254 +        * mode. If still in host mode, need to keep power on to detect a
34255 +        * reconnection.
34256 +        */
34257 +       if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
34258 +               if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
34259 +                       hprt0_data_t hprt0 = {.d32 = 0 };
34260 +                       DWC_PRINTF("Disconnect: PortPower off\n");
34261 +                       hprt0.b.prtpwr = 0;
34262 +                       DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
34263 +                                       hprt0.d32);
34264 +               }
34265 +
34266 +               dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
34267 +       }
34268 +
34269 +       /* Respond with an error status to all URBs in the schedule. */
34270 +       kill_all_urbs(dwc_otg_hcd);
34271 +
34272 +       if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
34273 +               /* Clean up any host channels that were in use. */
34274 +               int num_channels;
34275 +               int i;
34276 +               dwc_hc_t *channel;
34277 +               dwc_otg_hc_regs_t *hc_regs;
34278 +               hcchar_data_t hcchar;
34279 +
34280 +               num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
34281 +
34282 +               if (!dwc_otg_hcd->core_if->dma_enable) {
34283 +                       /* Flush out any channel requests in slave mode. */
34284 +                       for (i = 0; i < num_channels; i++) {
34285 +                               channel = dwc_otg_hcd->hc_ptr_array[i];
34286 +                               if (DWC_CIRCLEQ_EMPTY_ENTRY
34287 +                                   (channel, hc_list_entry)) {
34288 +                                       hc_regs =
34289 +                                           dwc_otg_hcd->core_if->
34290 +                                           host_if->hc_regs[i];
34291 +                                       hcchar.d32 =
34292 +                                           DWC_READ_REG32(&hc_regs->hcchar);
34293 +                                       if (hcchar.b.chen) {
34294 +                                               hcchar.b.chen = 0;
34295 +                                               hcchar.b.chdis = 1;
34296 +                                               hcchar.b.epdir = 0;
34297 +                                               DWC_WRITE_REG32
34298 +                                                   (&hc_regs->hcchar,
34299 +                                                    hcchar.d32);
34300 +                                       }
34301 +                               }
34302 +                       }
34303 +               }
34304 +
34305 +               for (i = 0; i < num_channels; i++) {
34306 +                       channel = dwc_otg_hcd->hc_ptr_array[i];
34307 +                       if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
34308 +                               hc_regs =
34309 +                                   dwc_otg_hcd->core_if->host_if->hc_regs[i];
34310 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
34311 +                               if (hcchar.b.chen) {
34312 +                                       /* Halt the channel. */
34313 +                                       hcchar.b.chdis = 1;
34314 +                                       DWC_WRITE_REG32(&hc_regs->hcchar,
34315 +                                                       hcchar.d32);
34316 +                               }
34317 +
34318 +                               dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
34319 +                                                  channel);
34320 +                               DWC_CIRCLEQ_INSERT_TAIL
34321 +                                   (&dwc_otg_hcd->free_hc_list, channel,
34322 +                                    hc_list_entry);
34323 +                               /*
34324 +                                * Added for Descriptor DMA to prevent channel double cleanup
34325 +                                * in release_channel_ddma(). Which called from ep_disable
34326 +                                * when device disconnect.
34327 +                                */
34328 +                               channel->qh = NULL;
34329 +                       }
34330 +               }
34331 +       }
34332 +
34333 +       if (dwc_otg_hcd->fops->disconnect) {
34334 +               dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
34335 +       }
34336 +
34337 +       return 1;
34338 +}
34339 +
34340 +/**
34341 + * HCD Callback function for stopping the HCD.
34342 + *
34343 + * @param p void pointer to the <code>struct usb_hcd</code>
34344 + */
34345 +static int32_t dwc_otg_hcd_stop_cb(void *p)
34346 +{
34347 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34348 +
34349 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34350 +       dwc_otg_hcd_stop(dwc_otg_hcd);
34351 +       return 1;
34352 +}
34353 +
34354 +#ifdef CONFIG_USB_DWC_OTG_LPM
34355 +/**
34356 + * HCD Callback function for sleep of HCD.
34357 + *
34358 + * @param p void pointer to the <code>struct usb_hcd</code>
34359 + */
34360 +static int dwc_otg_hcd_sleep_cb(void *p)
34361 +{
34362 +       dwc_otg_hcd_t *hcd = p;
34363 +
34364 +       dwc_otg_hcd_free_hc_from_lpm(hcd);
34365 +
34366 +       return 0;
34367 +}
34368 +#endif
34369 +
34370 +/**
34371 + * HCD Callback function for Remote Wakeup.
34372 + *
34373 + * @param p void pointer to the <code>struct usb_hcd</code>
34374 + */
34375 +static int dwc_otg_hcd_rem_wakeup_cb(void *p)
34376 +{
34377 +       dwc_otg_hcd_t *hcd = p;
34378 +
34379 +       if (hcd->core_if->lx_state == DWC_OTG_L2) {
34380 +               hcd->flags.b.port_suspend_change = 1;
34381 +       }
34382 +#ifdef CONFIG_USB_DWC_OTG_LPM
34383 +       else {
34384 +               hcd->flags.b.port_l1_change = 1;
34385 +       }
34386 +#endif
34387 +       return 0;
34388 +}
34389 +
34390 +/**
34391 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
34392 + * stopped.
34393 + */
34394 +void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
34395 +{
34396 +       hprt0_data_t hprt0 = {.d32 = 0 };
34397 +
34398 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
34399
34400 +       /*
34401 +        * The root hub should be disconnected before this function is called.
34402 +        * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
34403 +        * and the QH lists (via ..._hcd_endpoint_disable).
34404 +        */
34405 +
34406 +       /* Turn off all host-specific interrupts. */
34407 +       dwc_otg_disable_host_interrupts(hcd->core_if);
34408 +
34409 +       /* Turn off the vbus power */
34410 +       DWC_PRINTF("PortPower off\n");
34411 +       hprt0.b.prtpwr = 0;
34412 +       DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
34413 +       dwc_mdelay(1);
34414 +}
34415 +
34416 +int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
34417 +                           dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
34418 +                           int atomic_alloc)
34419 +{
34420 +       dwc_irqflags_t flags;
34421 +       int retval = 0;
34422 +       dwc_otg_qtd_t *qtd;
34423 +       gintmsk_data_t intr_mask = {.d32 = 0 };
34424 +
34425 +#ifdef DEBUG /* integrity checks (Broadcom) */
34426 +       if (NULL == hcd->core_if) {
34427 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");
34428 +               /* No longer connected. */
34429 +               return -DWC_E_INVALID;
34430 +       }
34431 +#endif
34432 +       if (!hcd->flags.b.port_connect_status) {
34433 +               /* No longer connected. */
34434 +               DWC_ERROR("Not connected\n");
34435 +               return -DWC_E_NO_DEVICE;
34436 +       }
34437 +
34438 +       qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
34439 +       if (qtd == NULL) {
34440 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
34441 +               return -DWC_E_NO_MEMORY;
34442 +       }
34443 +#ifdef DEBUG /* integrity checks (Broadcom) */
34444 +       if (qtd->urb == NULL) {
34445 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");
34446 +               return -DWC_E_NO_MEMORY;
34447 +       }
34448 +       if (qtd->urb->priv == NULL) {
34449 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");
34450 +               return -DWC_E_NO_MEMORY;
34451 +       }
34452 +#endif
34453 +       retval =
34454 +           dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
34455 +            // creates a new queue in ep_handle if it doesn't exist already
34456 +       if (retval < 0) {
34457 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
34458 +                         "Error status %d\n", retval);
34459 +               dwc_otg_hcd_qtd_free(qtd);
34460 +       } else {
34461 +               qtd->qh = *ep_handle;
34462 +       }
34463 +       intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
34464 +       if (!intr_mask.b.sofintr && retval == 0) {
34465 +               dwc_otg_transaction_type_e tr_type;
34466 +               if ((qtd->qh->ep_type == UE_BULK)
34467 +                   && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
34468 +                       /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
34469 +                       return 0;
34470 +               }
34471 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34472 +               tr_type = dwc_otg_hcd_select_transactions(hcd);
34473 +               if (tr_type != DWC_OTG_TRANSACTION_NONE) {
34474 +                       dwc_otg_hcd_queue_transactions(hcd, tr_type);
34475 +               }
34476 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34477 +       }
34478 +
34479 +       return retval;
34480 +}
34481 +
34482 +int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
34483 +                           dwc_otg_hcd_urb_t * dwc_otg_urb)
34484 +{
34485 +       dwc_otg_qh_t *qh;
34486 +       dwc_otg_qtd_t *urb_qtd;
34487 +
34488 +#ifdef DEBUG /* integrity checks (Broadcom) */
34489 +
34490 +       if (hcd == NULL) {
34491 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");
34492 +               return -DWC_E_INVALID;
34493 +       }
34494 +       if (dwc_otg_urb == NULL) { 
34495 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");
34496 +               return -DWC_E_INVALID;
34497 +       }
34498 +       if (dwc_otg_urb->qtd == NULL) { 
34499 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");
34500 +               return -DWC_E_INVALID;
34501 +       }
34502 +       urb_qtd = dwc_otg_urb->qtd;
34503 +       if (urb_qtd->qh == NULL) { 
34504 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
34505 +               return -DWC_E_INVALID;
34506 +       }
34507 +#else
34508 +       urb_qtd = dwc_otg_urb->qtd;
34509 +#endif
34510 +       qh = urb_qtd->qh;
34511 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
34512 +               if (urb_qtd->in_process) {
34513 +                       dump_channel_info(hcd, qh);
34514 +               }
34515 +       }
34516 +#ifdef DEBUG /* integrity checks (Broadcom) */
34517 +       if (hcd->core_if == NULL) {
34518 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");
34519 +               return -DWC_E_INVALID;
34520 +       }
34521 +#endif
34522 +       if (urb_qtd->in_process && qh->channel) {
34523 +               /* The QTD is in process (it has been assigned to a channel). */
34524 +               if (hcd->flags.b.port_connect_status) {
34525 +                       /*
34526 +                        * If still connected (i.e. in host mode), halt the
34527 +                        * channel so it can be used for other transfers. If
34528 +                        * no longer connected, the host registers can't be
34529 +                        * written to halt the channel since the core is in
34530 +                        * device mode.
34531 +                        */
34532 +                       dwc_otg_hc_halt(hcd->core_if, qh->channel,
34533 +                                       DWC_OTG_HC_XFER_URB_DEQUEUE);
34534 +               }
34535 +       }
34536 +
34537 +       /*
34538 +        * Free the QTD and clean up the associated QH. Leave the QH in the
34539 +        * schedule if it has any remaining QTDs.
34540 +        */
34541 +
34542 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "
34543 +                    "delete %sQueue handler\n",
34544 +                    hcd->core_if->dma_desc_enable?"DMA ":"");
34545 +       if (!hcd->core_if->dma_desc_enable) {
34546 +               uint8_t b = urb_qtd->in_process;
34547 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34548 +               if (b) {
34549 +                       dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
34550 +                       qh->channel = NULL;
34551 +               } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
34552 +                       dwc_otg_hcd_qh_remove(hcd, qh);
34553 +               }
34554 +       } else {
34555 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34556 +       }
34557 +       return 0;
34558 +}
34559 +
34560 +int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
34561 +                                int retry)
34562 +{
34563 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34564 +       int retval = 0;
34565 +       dwc_irqflags_t flags;
34566 +
34567 +       if (retry < 0) {
34568 +               retval = -DWC_E_INVALID;
34569 +               goto done;
34570 +       }
34571 +
34572 +       if (!qh) {
34573 +               retval = -DWC_E_INVALID;
34574 +               goto done;
34575 +       }
34576 +
34577 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34578 +
34579 +       while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
34580 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34581 +               retry--;
34582 +               dwc_msleep(5);
34583 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34584 +       }
34585 +
34586 +       dwc_otg_hcd_qh_remove(hcd, qh);
34587 +
34588 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34589 +       /*
34590 +        * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
34591 +        * and qh_free to prevent stack dump on DWC_DMA_FREE() with
34592 +        * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
34593 +        * and dwc_otg_hcd_frame_list_alloc().
34594 +        */
34595 +       dwc_otg_hcd_qh_free(hcd, qh);
34596 +
34597 +done:
34598 +       return retval;
34599 +}
34600 +
34601 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
34602 +int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)
34603 +{
34604 +       int retval = 0;
34605 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34606 +       if (!qh)
34607 +               return -DWC_E_INVALID;
34608 +
34609 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
34610 +       return retval;
34611 +}
34612 +#endif
34613 +
34614 +/**
34615 + * HCD Callback structure for handling mode switching.
34616 + */
34617 +static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
34618 +       .start = dwc_otg_hcd_start_cb,
34619 +       .stop = dwc_otg_hcd_stop_cb,
34620 +       .disconnect = dwc_otg_hcd_disconnect_cb,
34621 +       .session_start = dwc_otg_hcd_session_start_cb,
34622 +       .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
34623 +#ifdef CONFIG_USB_DWC_OTG_LPM
34624 +       .sleep = dwc_otg_hcd_sleep_cb,
34625 +#endif
34626 +       .p = 0,
34627 +};
34628 +
34629 +/**
34630 + * Reset tasklet function
34631 + */
34632 +static void reset_tasklet_func(void *data)
34633 +{
34634 +       dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
34635 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
34636 +       hprt0_data_t hprt0;
34637 +
34638 +       DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
34639 +
34640 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
34641 +       hprt0.b.prtrst = 1;
34642 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34643 +       dwc_mdelay(60);
34644 +
34645 +       hprt0.b.prtrst = 0;
34646 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34647 +       dwc_otg_hcd->flags.b.port_reset_change = 1;
34648 +}
34649 +
34650 +static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
34651 +{
34652 +       dwc_list_link_t *item;
34653 +       dwc_otg_qh_t *qh;
34654 +       dwc_irqflags_t flags;
34655 +
34656 +       if (!qh_list->next) {
34657 +               /* The list hasn't been initialized yet. */
34658 +               return;
34659 +       }
34660 +       /*
34661 +        * Hold spinlock here. Not needed in that case if bellow 
34662 +        * function is being called from ISR 
34663 +        */
34664 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34665 +       /* Ensure there are no QTDs or URBs left. */
34666 +       kill_urbs_in_qh_list(hcd, qh_list);
34667 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34668 +
34669 +       DWC_LIST_FOREACH(item, qh_list) {
34670 +               qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34671 +               dwc_otg_hcd_qh_remove_and_free(hcd, qh);
34672 +       }
34673 +}
34674 +
34675 +/**
34676 + * Exit from Hibernation if Host did not detect SRP from connected SRP capable
34677 + * Device during SRP time by host power up.
34678 + */
34679 +void dwc_otg_hcd_power_up(void *ptr)
34680 +{
34681 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
34682 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
34683 +
34684 +       DWC_PRINTF("%s called\n", __FUNCTION__);
34685 +
34686 +       if (!core_if->hibernation_suspend) {
34687 +               DWC_PRINTF("Already exited from Hibernation\n");
34688 +               return;
34689 +       }
34690 +
34691 +       /* Switch on the voltage to the core */
34692 +       gpwrdn.b.pwrdnswtch = 1;
34693 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34694 +       dwc_udelay(10);
34695 +
34696 +       /* Reset the core */
34697 +       gpwrdn.d32 = 0;
34698 +       gpwrdn.b.pwrdnrstn = 1;
34699 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34700 +       dwc_udelay(10);
34701 +
34702 +       /* Disable power clamps */
34703 +       gpwrdn.d32 = 0;
34704 +       gpwrdn.b.pwrdnclmp = 1;
34705 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34706 +
34707 +       /* Remove reset the core signal */
34708 +       gpwrdn.d32 = 0;
34709 +       gpwrdn.b.pwrdnrstn = 1;
34710 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
34711 +       dwc_udelay(10);
34712 +
34713 +       /* Disable PMU interrupt */
34714 +       gpwrdn.d32 = 0;
34715 +       gpwrdn.b.pmuintsel = 1;
34716 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34717 +
34718 +       core_if->hibernation_suspend = 0;
34719 +
34720 +       /* Disable PMU */
34721 +       gpwrdn.d32 = 0;
34722 +       gpwrdn.b.pmuactv = 1;
34723 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34724 +       dwc_udelay(10);
34725 +
34726 +       /* Enable VBUS */
34727 +       gpwrdn.d32 = 0;
34728 +       gpwrdn.b.dis_vbus = 1;
34729 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34730 +
34731 +       core_if->op_state = A_HOST;
34732 +       dwc_otg_core_init(core_if);
34733 +       dwc_otg_enable_global_interrupts(core_if);
34734 +       cil_hcd_start(core_if);
34735 +}
34736 +
34737 +/**
34738 + * Frees secondary storage associated with the dwc_otg_hcd structure contained
34739 + * in the struct usb_hcd field.
34740 + */
34741 +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
34742 +{
34743 +       int i;
34744 +
34745 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
34746 +
34747 +       del_timers(dwc_otg_hcd);
34748 +
34749 +       /* Free memory for QH/QTD lists */
34750 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
34751 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
34752 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
34753 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
34754 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
34755 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
34756 +
34757 +       /* Free memory for the host channels. */
34758 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
34759 +               dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
34760 +
34761 +#ifdef DEBUG
34762 +               if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
34763 +                       DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
34764 +               }
34765 +#endif
34766 +               if (hc != NULL) {
34767 +                       DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
34768 +                                   i, hc);
34769 +                       DWC_FREE(hc);
34770 +               }
34771 +       }
34772 +
34773 +       if (dwc_otg_hcd->core_if->dma_enable) {
34774 +               if (dwc_otg_hcd->status_buf_dma) {
34775 +                       DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
34776 +                                    dwc_otg_hcd->status_buf,
34777 +                                    dwc_otg_hcd->status_buf_dma);
34778 +               }
34779 +       } else if (dwc_otg_hcd->status_buf != NULL) {
34780 +               DWC_FREE(dwc_otg_hcd->status_buf);
34781 +       }
34782 +       DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
34783 +       /* Set core_if's lock pointer to NULL */
34784 +       dwc_otg_hcd->core_if->lock = NULL;
34785 +
34786 +       DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
34787 +       DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
34788 +
34789 +#ifdef DWC_DEV_SRPCAP
34790 +       if (dwc_otg_hcd->core_if->power_down == 2 &&
34791 +           dwc_otg_hcd->core_if->pwron_timer) {
34792 +               DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
34793 +       }
34794 +#endif
34795 +       DWC_FREE(dwc_otg_hcd);
34796 +}
34797 +
34798 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd);
34799 +
34800 +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
34801 +{
34802 +       int retval = 0;
34803 +       int num_channels;
34804 +       int i;
34805 +       dwc_hc_t *channel;
34806 +
34807 +       hcd->lock = DWC_SPINLOCK_ALLOC();
34808 +        DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
34809 +                    hcd, core_if);
34810 +       if (!hcd->lock) {
34811 +               DWC_ERROR("Could not allocate lock for pcd");
34812 +               DWC_FREE(hcd);
34813 +               retval = -DWC_E_NO_MEMORY;
34814 +               goto out;
34815 +       }
34816 +       hcd->core_if = core_if;
34817 +
34818 +       /* Register the HCD CIL Callbacks */
34819 +       dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
34820 +                                          &hcd_cil_callbacks, hcd);
34821 +
34822 +       /* Initialize the non-periodic schedule. */
34823 +       DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
34824 +       DWC_LIST_INIT(&hcd->non_periodic_sched_active);
34825 +
34826 +       /* Initialize the periodic schedule. */
34827 +       DWC_LIST_INIT(&hcd->periodic_sched_inactive);
34828 +       DWC_LIST_INIT(&hcd->periodic_sched_ready);
34829 +       DWC_LIST_INIT(&hcd->periodic_sched_assigned);
34830 +       DWC_LIST_INIT(&hcd->periodic_sched_queued);
34831 +
34832 +       /*
34833 +        * Create a host channel descriptor for each host channel implemented
34834 +        * in the controller. Initialize the channel descriptor array.
34835 +        */
34836 +       DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
34837 +       num_channels = hcd->core_if->core_params->host_channels;
34838 +       DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
34839 +       for (i = 0; i < num_channels; i++) {
34840 +               channel = DWC_ALLOC(sizeof(dwc_hc_t));
34841 +               if (channel == NULL) {
34842 +                       retval = -DWC_E_NO_MEMORY;
34843 +                       DWC_ERROR("%s: host channel allocation failed\n",
34844 +                                 __func__);
34845 +                       dwc_otg_hcd_free(hcd);
34846 +                       goto out;
34847 +               }
34848 +               channel->hc_num = i;
34849 +               hcd->hc_ptr_array[i] = channel;
34850 +#ifdef DEBUG
34851 +               hcd->core_if->hc_xfer_timer[i] =
34852 +                   DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
34853 +                                   &hcd->core_if->hc_xfer_info[i]);
34854 +#endif
34855 +               DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
34856 +                           channel);
34857 +       }
34858 +
34859 +       /* Initialize the Connection timeout timer. */
34860 +       hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
34861 +                                         dwc_otg_hcd_connect_timeout, 0);
34862 +
34863 +       printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled");
34864 +       if (microframe_schedule)
34865 +               init_hcd_usecs(hcd);
34866 +
34867 +       /* Initialize reset tasklet. */
34868 +       hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
34869 +#ifdef DWC_DEV_SRPCAP
34870 +       if (hcd->core_if->power_down == 2) {
34871 +               /* Initialize Power on timer for Host power up in case hibernation */
34872 +               hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
34873 +                                                                       dwc_otg_hcd_power_up, core_if);
34874 +       }
34875 +#endif 
34876 +
34877 +       /*
34878 +        * Allocate space for storing data on status transactions. Normally no
34879 +        * data is sent, but this space acts as a bit bucket. This must be
34880 +        * done after usb_add_hcd since that function allocates the DMA buffer
34881 +        * pool.
34882 +        */
34883 +       if (hcd->core_if->dma_enable) {
34884 +               hcd->status_buf =
34885 +                   DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE,
34886 +                                 &hcd->status_buf_dma);
34887 +       } else {
34888 +               hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
34889 +       }
34890 +       if (!hcd->status_buf) {
34891 +               retval = -DWC_E_NO_MEMORY;
34892 +               DWC_ERROR("%s: status_buf allocation failed\n", __func__);
34893 +               dwc_otg_hcd_free(hcd);
34894 +               goto out;
34895 +       }
34896 +
34897 +       hcd->otg_port = 1;
34898 +       hcd->frame_list = NULL;
34899 +       hcd->frame_list_dma = 0;
34900 +       hcd->periodic_qh_count = 0;
34901 +out:
34902 +       return retval;
34903 +}
34904 +
34905 +void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
34906 +{
34907 +       /* Turn off all host-specific interrupts. */
34908 +       dwc_otg_disable_host_interrupts(hcd->core_if);
34909 +
34910 +       dwc_otg_hcd_free(hcd);
34911 +}
34912 +
34913 +/**
34914 + * Initializes dynamic portions of the DWC_otg HCD state.
34915 + */
34916 +static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
34917 +{
34918 +       int num_channels;
34919 +       int i;
34920 +       dwc_hc_t *channel;
34921 +       dwc_hc_t *channel_tmp;
34922 +
34923 +       hcd->flags.d32 = 0;
34924 +
34925 +       hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
34926 +       if (!microframe_schedule) {
34927 +               hcd->non_periodic_channels = 0;
34928 +               hcd->periodic_channels = 0;
34929 +       } else {
34930 +               hcd->available_host_channels = hcd->core_if->core_params->host_channels;
34931 +       }
34932 +       /*
34933 +        * Put all channels in the free channel list and clean up channel
34934 +        * states.
34935 +        */
34936 +       DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
34937 +                                &hcd->free_hc_list, hc_list_entry) {
34938 +               DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
34939 +       }
34940 +
34941 +       num_channels = hcd->core_if->core_params->host_channels;
34942 +       for (i = 0; i < num_channels; i++) {
34943 +               channel = hcd->hc_ptr_array[i];
34944 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
34945 +                                       hc_list_entry);
34946 +               dwc_otg_hc_cleanup(hcd->core_if, channel);
34947 +       }
34948 +
34949 +       /* Initialize the DWC core for host mode operation. */
34950 +       dwc_otg_core_host_init(hcd->core_if);
34951 +
34952 +       /* Set core_if's lock pointer to the hcd->lock */
34953 +       hcd->core_if->lock = hcd->lock;
34954 +}
34955 +
34956 +/**
34957 + * Assigns transactions from a QTD to a free host channel and initializes the
34958 + * host channel to perform the transactions. The host channel is removed from
34959 + * the free list.
34960 + *
34961 + * @param hcd The HCD state structure.
34962 + * @param qh Transactions from the first QTD for this QH are selected and
34963 + * assigned to a free host channel.
34964 + */
34965 +static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
34966 +{
34967 +       dwc_hc_t *hc;
34968 +       dwc_otg_qtd_t *qtd;
34969 +       dwc_otg_hcd_urb_t *urb;
34970 +       void* ptr = NULL;
34971 +
34972 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
34973 +       
34974 +       urb = qtd->urb;
34975 +
34976 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);
34977 +
34978 +       if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))
34979 +               urb->actual_length = urb->length;
34980 +
34981 +
34982 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
34983 +
34984 +       /* Remove the host channel from the free list. */
34985 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
34986 +
34987 +       qh->channel = hc;
34988 +
34989 +       qtd->in_process = 1;
34990 +
34991 +       /*
34992 +        * Use usb_pipedevice to determine device address. This address is
34993 +        * 0 before the SET_ADDRESS command and the correct address afterward.
34994 +        */
34995 +       hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
34996 +       hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
34997 +       hc->speed = qh->dev_speed;
34998 +       hc->max_packet = dwc_max_packet(qh->maxp);
34999 +
35000 +       hc->xfer_started = 0;
35001 +       hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
35002 +       hc->error_state = (qtd->error_count > 0);
35003 +       hc->halt_on_queue = 0;
35004 +       hc->halt_pending = 0;
35005 +       hc->requests = 0;
35006 +
35007 +       /*
35008 +        * The following values may be modified in the transfer type section
35009 +        * below. The xfer_len value may be reduced when the transfer is
35010 +        * started to accommodate the max widths of the XferSize and PktCnt
35011 +        * fields in the HCTSIZn register.
35012 +        */
35013 +
35014 +       hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
35015 +       if (hc->ep_is_in) {
35016 +               hc->do_ping = 0;
35017 +       } else {
35018 +               hc->do_ping = qh->ping_state;
35019 +       }
35020 +
35021 +       hc->data_pid_start = qh->data_toggle;
35022 +       hc->multi_count = 1;
35023 +
35024 +       if (hcd->core_if->dma_enable) {
35025 +               hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
35026 +
35027 +               /* For non-dword aligned case */
35028 +               if (((unsigned long)hc->xfer_buff & 0x3)
35029 +                   && !hcd->core_if->dma_desc_enable) {
35030 +                       ptr = (uint8_t *) urb->buf + urb->actual_length;
35031 +               }
35032 +       } else {
35033 +               hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
35034 +       }
35035 +       hc->xfer_len = urb->length - urb->actual_length;
35036 +       hc->xfer_count = 0;
35037 +
35038 +       /*
35039 +        * Set the split attributes
35040 +        */
35041 +       hc->do_split = 0;
35042 +       if (qh->do_split) {
35043 +               uint32_t hub_addr, port_addr;
35044 +               hc->do_split = 1;
35045 +               hc->xact_pos = qtd->isoc_split_pos;
35046 +               hc->complete_split = qtd->complete_split;
35047 +               hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
35048 +               hc->hub_addr = (uint8_t) hub_addr;
35049 +               hc->port_addr = (uint8_t) port_addr;
35050 +       }
35051 +
35052 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
35053 +       case UE_CONTROL:
35054 +               hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
35055 +               switch (qtd->control_phase) {
35056 +               case DWC_OTG_CONTROL_SETUP:
35057 +                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction\n");
35058 +                       hc->do_ping = 0;
35059 +                       hc->ep_is_in = 0;
35060 +                       hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
35061 +                       if (hcd->core_if->dma_enable) {
35062 +                               hc->xfer_buff = (uint8_t *) urb->setup_dma;
35063 +                       } else {
35064 +                               hc->xfer_buff = (uint8_t *) urb->setup_packet;
35065 +                       }
35066 +                       hc->xfer_len = 8;
35067 +                       ptr = NULL;
35068 +                       break;
35069 +               case DWC_OTG_CONTROL_DATA:
35070 +                       DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
35071 +                       hc->data_pid_start = qtd->data_toggle;
35072 +                       break;
35073 +               case DWC_OTG_CONTROL_STATUS:
35074 +                       /*
35075 +                        * Direction is opposite of data direction or IN if no
35076 +                        * data.
35077 +                        */
35078 +                       DWC_DEBUGPL(DBG_HCDV, "  Control status transaction\n");
35079 +                       if (urb->length == 0) {
35080 +                               hc->ep_is_in = 1;
35081 +                       } else {
35082 +                               hc->ep_is_in =
35083 +                                   dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
35084 +                       }
35085 +                       if (hc->ep_is_in) {
35086 +                               hc->do_ping = 0;
35087 +                       }
35088 +
35089 +                       hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
35090 +
35091 +                       hc->xfer_len = 0;
35092 +                       if (hcd->core_if->dma_enable) {
35093 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
35094 +                       } else {
35095 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf;
35096 +                       }
35097 +                       ptr = NULL;
35098 +                       break;
35099 +               }
35100 +               break;
35101 +       case UE_BULK:
35102 +               hc->ep_type = DWC_OTG_EP_TYPE_BULK;
35103 +               break;
35104 +       case UE_INTERRUPT:
35105 +               hc->ep_type = DWC_OTG_EP_TYPE_INTR;
35106 +               break;
35107 +       case UE_ISOCHRONOUS:
35108 +               {
35109 +                       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
35110 +
35111 +                       hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
35112 +
35113 +                       if (hcd->core_if->dma_desc_enable)
35114 +                               break;
35115 +
35116 +                       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
35117 +
35118 +                       frame_desc->status = 0;
35119 +
35120 +                       if (hcd->core_if->dma_enable) {
35121 +                               hc->xfer_buff = (uint8_t *) urb->dma;
35122 +                       } else {
35123 +                               hc->xfer_buff = (uint8_t *) urb->buf;
35124 +                       }
35125 +                       hc->xfer_buff +=
35126 +                           frame_desc->offset + qtd->isoc_split_offset;
35127 +                       hc->xfer_len =
35128 +                           frame_desc->length - qtd->isoc_split_offset;
35129 +
35130 +                       /* For non-dword aligned buffers */
35131 +                       if (((unsigned long)hc->xfer_buff & 0x3)
35132 +                           && hcd->core_if->dma_enable) {
35133 +                               ptr =
35134 +                                   (uint8_t *) urb->buf + frame_desc->offset +
35135 +                                   qtd->isoc_split_offset;
35136 +                       } else
35137 +                               ptr = NULL;
35138 +
35139 +                       if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
35140 +                               if (hc->xfer_len <= 188) {
35141 +                                       hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
35142 +                               } else {
35143 +                                       hc->xact_pos =
35144 +                                           DWC_HCSPLIT_XACTPOS_BEGIN;
35145 +                               }
35146 +                       }
35147 +               }
35148 +               break;
35149 +       }
35150 +       /* non DWORD-aligned buffer case */     
35151 +       if (ptr) {
35152 +               uint32_t buf_size;
35153 +               if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
35154 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
35155 +               } else {                                
35156 +                       buf_size = 4096;
35157 +               }
35158 +               if (!qh->dw_align_buf) {
35159 +                       qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,
35160 +                                                        &qh->dw_align_buf_dma);
35161 +                       if (!qh->dw_align_buf) {
35162 +                               DWC_ERROR
35163 +                                   ("%s: Failed to allocate memory to handle "
35164 +                                    "non-dword aligned buffer case\n",
35165 +                                    __func__);
35166 +                               return;
35167 +                       }
35168 +               }
35169 +               if (!hc->ep_is_in) {
35170 +                       dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
35171 +               }
35172 +               hc->align_buff = qh->dw_align_buf_dma;
35173 +       } else {
35174 +               hc->align_buff = 0;
35175 +       }
35176 +
35177 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
35178 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
35179 +               /*
35180 +                * This value may be modified when the transfer is started to
35181 +                * reflect the actual transfer length.
35182 +                */
35183 +               hc->multi_count = dwc_hb_mult(qh->maxp);
35184 +       }
35185 +
35186 +       if (hcd->core_if->dma_desc_enable)
35187 +               hc->desc_list_addr = qh->desc_list_dma;
35188 +
35189 +       dwc_otg_hc_init(hcd->core_if, hc);
35190 +       hc->qh = qh;
35191 +}
35192 +
35193 +/**
35194 + * This function selects transactions from the HCD transfer schedule and
35195 + * assigns them to available host channels. It is called from HCD interrupt
35196 + * handler functions.
35197 + *
35198 + * @param hcd The HCD state structure.
35199 + *
35200 + * @return The types of new transactions that were assigned to host channels.
35201 + */
35202 +dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
35203 +{
35204 +       dwc_list_link_t *qh_ptr;
35205 +       dwc_otg_qh_t *qh;
35206 +       int num_channels;
35207 +       dwc_irqflags_t flags;
35208 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
35209 +       dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
35210 +
35211 +#ifdef DEBUG_SOF
35212 +       DWC_DEBUGPL(DBG_HCD, "  Select Transactions\n");
35213 +#endif
35214 +
35215 +#ifdef DEBUG_HOST_CHANNELS
35216 +       last_sel_trans_num_per_scheduled = 0;
35217 +       last_sel_trans_num_nonper_scheduled = 0;
35218 +       last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels;
35219 +#endif /* DEBUG_HOST_CHANNELS */
35220 +
35221 +       /* Process entries in the periodic ready list. */
35222 +       qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
35223 +
35224 +       while (qh_ptr != &hcd->periodic_sched_ready &&
35225 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35226 +               if (microframe_schedule) {
35227 +                       // Make sure we leave one channel for non periodic transactions.
35228 +                       DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35229 +                       if (hcd->available_host_channels <= 1) {
35230 +                               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35231 +                               break;
35232 +                       }
35233 +                       hcd->available_host_channels--;
35234 +                       DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35235 +#ifdef DEBUG_HOST_CHANNELS
35236 +                       last_sel_trans_num_per_scheduled++;
35237 +#endif /* DEBUG_HOST_CHANNELS */
35238 +               }
35239 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35240 +               assign_and_init_hc(hcd, qh);
35241 +
35242 +               /*
35243 +                * Move the QH from the periodic ready schedule to the
35244 +                * periodic assigned schedule.
35245 +                */
35246 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
35247 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35248 +               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
35249 +                                  &qh->qh_list_entry);
35250 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35251 +
35252 +               ret_val = DWC_OTG_TRANSACTION_PERIODIC;
35253 +       }
35254 +
35255 +       /*
35256 +        * Process entries in the inactive portion of the non-periodic
35257 +        * schedule. Some free host channels may not be used if they are
35258 +        * reserved for periodic transfers.
35259 +        */
35260 +       qh_ptr = hcd->non_periodic_sched_inactive.next;
35261 +       num_channels = hcd->core_if->core_params->host_channels;
35262 +       while (qh_ptr != &hcd->non_periodic_sched_inactive &&
35263 +              (microframe_schedule || hcd->non_periodic_channels <
35264 +               num_channels - hcd->periodic_channels) &&
35265 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35266 +
35267 +               if (microframe_schedule) {
35268 +                               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35269 +                               if (hcd->available_host_channels < 1) {
35270 +                                       DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35271 +                                       break;
35272 +                               }
35273 +                               hcd->available_host_channels--;
35274 +                               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35275 +#ifdef DEBUG_HOST_CHANNELS
35276 +                               last_sel_trans_num_nonper_scheduled++;
35277 +#endif /* DEBUG_HOST_CHANNELS */
35278 +               }
35279 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35280 +
35281 +               assign_and_init_hc(hcd, qh);
35282 +
35283 +               /*
35284 +                * Move the QH from the non-periodic inactive schedule to the
35285 +                * non-periodic active schedule.
35286 +                */
35287 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
35288 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35289 +               DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
35290 +                                  &qh->qh_list_entry);
35291 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35292 +
35293 +               if (ret_val == DWC_OTG_TRANSACTION_NONE) {
35294 +                       ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
35295 +               } else {
35296 +                       ret_val = DWC_OTG_TRANSACTION_ALL;
35297 +               }
35298 +
35299 +               if (!microframe_schedule)
35300 +                       hcd->non_periodic_channels++;
35301 +       }
35302 +
35303 +#ifdef DEBUG_HOST_CHANNELS
35304 +       last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
35305 +#endif /* DEBUG_HOST_CHANNELS */
35306 +
35307 +       DWC_SPINLOCK_FREE(channel_lock);
35308 +       return ret_val;
35309 +}
35310 +
35311 +/**
35312 + * Attempts to queue a single transaction request for a host channel
35313 + * associated with either a periodic or non-periodic transfer. This function
35314 + * assumes that there is space available in the appropriate request queue. For
35315 + * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
35316 + * is available in the appropriate Tx FIFO.
35317 + *
35318 + * @param hcd The HCD state structure.
35319 + * @param hc Host channel descriptor associated with either a periodic or
35320 + * non-periodic transfer.
35321 + * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
35322 + * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
35323 + * transfers.
35324 + *
35325 + * @return 1 if a request is queued and more requests may be needed to
35326 + * complete the transfer, 0 if no more requests are required for this
35327 + * transfer, -1 if there is insufficient space in the Tx FIFO.
35328 + */
35329 +static int queue_transaction(dwc_otg_hcd_t * hcd,
35330 +                            dwc_hc_t * hc, uint16_t fifo_dwords_avail)
35331 +{
35332 +       int retval;
35333 +
35334 +       if (hcd->core_if->dma_enable) {
35335 +               if (hcd->core_if->dma_desc_enable) {
35336 +                       if (!hc->xfer_started
35337 +                           || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
35338 +                               dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
35339 +                               hc->qh->ping_state = 0;
35340 +                       }
35341 +               } else if (!hc->xfer_started) {
35342 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35343 +                       hc->qh->ping_state = 0;
35344 +               }
35345 +               retval = 0;
35346 +       } else if (hc->halt_pending) {
35347 +               /* Don't queue a request if the channel has been halted. */
35348 +               retval = 0;
35349 +       } else if (hc->halt_on_queue) {
35350 +               dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
35351 +               retval = 0;
35352 +       } else if (hc->do_ping) {
35353 +               if (!hc->xfer_started) {
35354 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35355 +               }
35356 +               retval = 0;
35357 +       } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
35358 +               if ((fifo_dwords_avail * 4) >= hc->max_packet) {
35359 +                       if (!hc->xfer_started) {
35360 +                               dwc_otg_hc_start_transfer(hcd->core_if, hc);
35361 +                               retval = 1;
35362 +                       } else {
35363 +                               retval =
35364 +                                   dwc_otg_hc_continue_transfer(hcd->core_if,
35365 +                                                                hc);
35366 +                       }
35367 +               } else {
35368 +                       retval = -1;
35369 +               }
35370 +       } else {
35371 +               if (!hc->xfer_started) {
35372 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35373 +                       retval = 1;
35374 +               } else {
35375 +                       retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
35376 +               }
35377 +       }
35378 +
35379 +       return retval;
35380 +}
35381 +
35382 +/**
35383 + * Processes periodic channels for the next frame and queues transactions for
35384 + * these channels to the DWC_otg controller. After queueing transactions, the
35385 + * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
35386 + * to queue as Periodic Tx FIFO or request queue space becomes available.
35387 + * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
35388 + */
35389 +static void process_periodic_channels(dwc_otg_hcd_t * hcd)
35390 +{
35391 +       hptxsts_data_t tx_status;
35392 +       dwc_list_link_t *qh_ptr;
35393 +       dwc_otg_qh_t *qh;
35394 +       int status;
35395 +       int no_queue_space = 0;
35396 +       int no_fifo_space = 0;
35397 +
35398 +       dwc_otg_host_global_regs_t *host_regs;
35399 +       host_regs = hcd->core_if->host_if->host_global_regs;
35400 +
35401 +       DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
35402 +#ifdef DEBUG
35403 +       tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35404 +       DWC_DEBUGPL(DBG_HCDV,
35405 +                   "  P Tx Req Queue Space Avail (before queue): %d\n",
35406 +                   tx_status.b.ptxqspcavail);
35407 +       DWC_DEBUGPL(DBG_HCDV, "  P Tx FIFO Space Avail (before queue): %d\n",
35408 +                   tx_status.b.ptxfspcavail);
35409 +#endif
35410 +
35411 +       qh_ptr = hcd->periodic_sched_assigned.next;
35412 +       while (qh_ptr != &hcd->periodic_sched_assigned) {
35413 +               tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35414 +               if (tx_status.b.ptxqspcavail == 0) {
35415 +                       no_queue_space = 1;
35416 +                       break;
35417 +               }
35418 +
35419 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35420 +
35421 +               /*
35422 +                * Set a flag if we're queuing high-bandwidth in slave mode.
35423 +                * The flag prevents any halts to get into the request queue in
35424 +                * the middle of multiple high-bandwidth packets getting queued.
35425 +                */
35426 +               if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
35427 +                       hcd->core_if->queuing_high_bandwidth = 1;
35428 +               }
35429 +               status =
35430 +                   queue_transaction(hcd, qh->channel,
35431 +                                     tx_status.b.ptxfspcavail);
35432 +               if (status < 0) {
35433 +                       no_fifo_space = 1;
35434 +                       break;
35435 +               }
35436 +
35437 +               /*
35438 +                * In Slave mode, stay on the current transfer until there is
35439 +                * nothing more to do or the high-bandwidth request count is
35440 +                * reached. In DMA mode, only need to queue one request. The
35441 +                * controller automatically handles multiple packets for
35442 +                * high-bandwidth transfers.
35443 +                */
35444 +               if (hcd->core_if->dma_enable || status == 0 ||
35445 +                   qh->channel->requests == qh->channel->multi_count) {
35446 +                       qh_ptr = qh_ptr->next;
35447 +                       /*
35448 +                        * Move the QH from the periodic assigned schedule to
35449 +                        * the periodic queued schedule.
35450 +                        */
35451 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
35452 +                                          &qh->qh_list_entry);
35453 +
35454 +                       /* done queuing high bandwidth */
35455 +                       hcd->core_if->queuing_high_bandwidth = 0;
35456 +               }
35457 +       }
35458 +
35459 +       if (!hcd->core_if->dma_enable) {
35460 +               dwc_otg_core_global_regs_t *global_regs;
35461 +               gintmsk_data_t intr_mask = {.d32 = 0 };
35462 +
35463 +               global_regs = hcd->core_if->core_global_regs;
35464 +               intr_mask.b.ptxfempty = 1;
35465 +#ifdef DEBUG
35466 +               tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35467 +               DWC_DEBUGPL(DBG_HCDV,
35468 +                           "  P Tx Req Queue Space Avail (after queue): %d\n",
35469 +                           tx_status.b.ptxqspcavail);
35470 +               DWC_DEBUGPL(DBG_HCDV,
35471 +                           "  P Tx FIFO Space Avail (after queue): %d\n",
35472 +                           tx_status.b.ptxfspcavail);
35473 +#endif
35474 +               if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
35475 +                   no_queue_space || no_fifo_space) {
35476 +                       /*
35477 +                        * May need to queue more transactions as the request
35478 +                        * queue or Tx FIFO empties. Enable the periodic Tx
35479 +                        * FIFO empty interrupt. (Always use the half-empty
35480 +                        * level to ensure that new requests are loaded as
35481 +                        * soon as possible.)
35482 +                        */
35483 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35484 +                                        intr_mask.d32);
35485 +               } else {
35486 +                       /*
35487 +                        * Disable the Tx FIFO empty interrupt since there are
35488 +                        * no more transactions that need to be queued right
35489 +                        * now. This function is called from interrupt
35490 +                        * handlers to queue more transactions as transfer
35491 +                        * states change.
35492 +                        */
35493 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35494 +                                        0);
35495 +               }
35496 +       }
35497 +}
35498 +
35499 +/**
35500 + * Processes active non-periodic channels and queues transactions for these
35501 + * channels to the DWC_otg controller. After queueing transactions, the NP Tx
35502 + * FIFO Empty interrupt is enabled if there are more transactions to queue as
35503 + * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
35504 + * FIFO Empty interrupt is disabled.
35505 + */
35506 +static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
35507 +{
35508 +       gnptxsts_data_t tx_status;
35509 +       dwc_list_link_t *orig_qh_ptr;
35510 +       dwc_otg_qh_t *qh;
35511 +       int status;
35512 +       int no_queue_space = 0;
35513 +       int no_fifo_space = 0;
35514 +       int more_to_do = 0;
35515 +
35516 +       dwc_otg_core_global_regs_t *global_regs =
35517 +           hcd->core_if->core_global_regs;
35518 +
35519 +       DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
35520 +#ifdef DEBUG
35521 +       tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35522 +       DWC_DEBUGPL(DBG_HCDV,
35523 +                   "  NP Tx Req Queue Space Avail (before queue): %d\n",
35524 +                   tx_status.b.nptxqspcavail);
35525 +       DWC_DEBUGPL(DBG_HCDV, "  NP Tx FIFO Space Avail (before queue): %d\n",
35526 +                   tx_status.b.nptxfspcavail);
35527 +#endif
35528 +       /*
35529 +        * Keep track of the starting point. Skip over the start-of-list
35530 +        * entry.
35531 +        */
35532 +       if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35533 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35534 +       }
35535 +       orig_qh_ptr = hcd->non_periodic_qh_ptr;
35536 +
35537 +       /*
35538 +        * Process once through the active list or until no more space is
35539 +        * available in the request queue or the Tx FIFO.
35540 +        */
35541 +       do {
35542 +               tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35543 +               if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
35544 +                       no_queue_space = 1;
35545 +                       break;
35546 +               }
35547 +
35548 +               qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
35549 +                                   qh_list_entry);
35550 +               status =
35551 +                   queue_transaction(hcd, qh->channel,
35552 +                                     tx_status.b.nptxfspcavail);
35553 +
35554 +               if (status > 0) {
35555 +                       more_to_do = 1;
35556 +               } else if (status < 0) {
35557 +                       no_fifo_space = 1;
35558 +                       break;
35559 +               }
35560 +
35561 +               /* Advance to next QH, skipping start-of-list entry. */
35562 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35563 +               if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35564 +                       hcd->non_periodic_qh_ptr =
35565 +                           hcd->non_periodic_qh_ptr->next;
35566 +               }
35567 +
35568 +       } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
35569 +
35570 +       if (!hcd->core_if->dma_enable) {
35571 +               gintmsk_data_t intr_mask = {.d32 = 0 };
35572 +               intr_mask.b.nptxfempty = 1;
35573 +
35574 +#ifdef DEBUG
35575 +               tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35576 +               DWC_DEBUGPL(DBG_HCDV,
35577 +                           "  NP Tx Req Queue Space Avail (after queue): %d\n",
35578 +                           tx_status.b.nptxqspcavail);
35579 +               DWC_DEBUGPL(DBG_HCDV,
35580 +                           "  NP Tx FIFO Space Avail (after queue): %d\n",
35581 +                           tx_status.b.nptxfspcavail);
35582 +#endif
35583 +               if (more_to_do || no_queue_space || no_fifo_space) {
35584 +                       /*
35585 +                        * May need to queue more transactions as the request
35586 +                        * queue or Tx FIFO empties. Enable the non-periodic
35587 +                        * Tx FIFO empty interrupt. (Always use the half-empty
35588 +                        * level to ensure that new requests are loaded as
35589 +                        * soon as possible.)
35590 +                        */
35591 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35592 +                                        intr_mask.d32);
35593 +               } else {
35594 +                       /*
35595 +                        * Disable the Tx FIFO empty interrupt since there are
35596 +                        * no more transactions that need to be queued right
35597 +                        * now. This function is called from interrupt
35598 +                        * handlers to queue more transactions as transfer
35599 +                        * states change.
35600 +                        */
35601 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35602 +                                        0);
35603 +               }
35604 +       }
35605 +}
35606 +
35607 +/**
35608 + * This function processes the currently active host channels and queues
35609 + * transactions for these channels to the DWC_otg controller. It is called
35610 + * from HCD interrupt handler functions.
35611 + *
35612 + * @param hcd The HCD state structure.
35613 + * @param tr_type The type(s) of transactions to queue (non-periodic,
35614 + * periodic, or both).
35615 + */
35616 +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
35617 +                                   dwc_otg_transaction_type_e tr_type)
35618 +{
35619 +#ifdef DEBUG_SOF
35620 +       DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
35621 +#endif
35622 +       /* Process host channels associated with periodic transfers. */
35623 +       if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
35624 +            tr_type == DWC_OTG_TRANSACTION_ALL) &&
35625 +           !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
35626 +
35627 +               process_periodic_channels(hcd);
35628 +       }
35629 +
35630 +       /* Process host channels associated with non-periodic transfers. */
35631 +       if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
35632 +           tr_type == DWC_OTG_TRANSACTION_ALL) {
35633 +               if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
35634 +                       process_non_periodic_channels(hcd);
35635 +               } else {
35636 +                       /*
35637 +                        * Ensure NP Tx FIFO empty interrupt is disabled when
35638 +                        * there are no non-periodic transfers to process.
35639 +                        */
35640 +                       gintmsk_data_t gintmsk = {.d32 = 0 };
35641 +                       gintmsk.b.nptxfempty = 1;
35642 +                       DWC_MODIFY_REG32(&hcd->core_if->
35643 +                                        core_global_regs->gintmsk, gintmsk.d32,
35644 +                                        0);
35645 +               }
35646 +       }
35647 +}
35648 +
35649 +#ifdef DWC_HS_ELECT_TST
35650 +/*
35651 + * Quick and dirty hack to implement the HS Electrical Test
35652 + * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
35653 + *
35654 + * This code was copied from our userspace app "hset". It sends a
35655 + * Get Device Descriptor control sequence in two parts, first the
35656 + * Setup packet by itself, followed some time later by the In and
35657 + * Ack packets. Rather than trying to figure out how to add this
35658 + * functionality to the normal driver code, we just hijack the
35659 + * hardware, using these two function to drive the hardware
35660 + * directly.
35661 + */
35662 +
35663 +static dwc_otg_core_global_regs_t *global_regs;
35664 +static dwc_otg_host_global_regs_t *hc_global_regs;
35665 +static dwc_otg_hc_regs_t *hc_regs;
35666 +static uint32_t *data_fifo;
35667 +
35668 +static void do_setup(void)
35669 +{
35670 +       gintsts_data_t gintsts;
35671 +       hctsiz_data_t hctsiz;
35672 +       hcchar_data_t hcchar;
35673 +       haint_data_t haint;
35674 +       hcint_data_t hcint;
35675 +
35676 +       /* Enable HAINTs */
35677 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35678 +
35679 +       /* Enable HCINTs */
35680 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35681 +
35682 +       /* Read GINTSTS */
35683 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35684 +
35685 +       /* Read HAINT */
35686 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35687 +
35688 +       /* Read HCINT */
35689 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35690 +
35691 +       /* Read HCCHAR */
35692 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35693 +
35694 +       /* Clear HCINT */
35695 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35696 +
35697 +       /* Clear HAINT */
35698 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35699 +
35700 +       /* Clear GINTSTS */
35701 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35702 +
35703 +       /* Read GINTSTS */
35704 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35705 +
35706 +       /*
35707 +        * Send Setup packet (Get Device Descriptor)
35708 +        */
35709 +
35710 +       /* Make sure channel is disabled */
35711 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35712 +       if (hcchar.b.chen) {
35713 +               hcchar.b.chdis = 1;
35714 +//              hcchar.b.chen = 1;
35715 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35716 +               //sleep(1);
35717 +               dwc_mdelay(1000);
35718 +
35719 +               /* Read GINTSTS */
35720 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35721 +
35722 +               /* Read HAINT */
35723 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35724 +
35725 +               /* Read HCINT */
35726 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35727 +
35728 +               /* Read HCCHAR */
35729 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35730 +
35731 +               /* Clear HCINT */
35732 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35733 +
35734 +               /* Clear HAINT */
35735 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35736 +
35737 +               /* Clear GINTSTS */
35738 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35739 +
35740 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35741 +       }
35742 +
35743 +       /* Set HCTSIZ */
35744 +       hctsiz.d32 = 0;
35745 +       hctsiz.b.xfersize = 8;
35746 +       hctsiz.b.pktcnt = 1;
35747 +       hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
35748 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35749 +
35750 +       /* Set HCCHAR */
35751 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35752 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35753 +       hcchar.b.epdir = 0;
35754 +       hcchar.b.epnum = 0;
35755 +       hcchar.b.mps = 8;
35756 +       hcchar.b.chen = 1;
35757 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35758 +
35759 +       /* Fill FIFO with Setup data for Get Device Descriptor */
35760 +       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35761 +       DWC_WRITE_REG32(data_fifo++, 0x01000680);
35762 +       DWC_WRITE_REG32(data_fifo++, 0x00080000);
35763 +
35764 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35765 +
35766 +       /* Wait for host channel interrupt */
35767 +       do {
35768 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35769 +       } while (gintsts.b.hcintr == 0);
35770 +
35771 +       /* Disable HCINTs */
35772 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
35773 +
35774 +       /* Disable HAINTs */
35775 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
35776 +
35777 +       /* Read HAINT */
35778 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35779 +
35780 +       /* Read HCINT */
35781 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35782 +
35783 +       /* Read HCCHAR */
35784 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35785 +
35786 +       /* Clear HCINT */
35787 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35788 +
35789 +       /* Clear HAINT */
35790 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35791 +
35792 +       /* Clear GINTSTS */
35793 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35794 +
35795 +       /* Read GINTSTS */
35796 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35797 +}
35798 +
35799 +static void do_in_ack(void)
35800 +{
35801 +       gintsts_data_t gintsts;
35802 +       hctsiz_data_t hctsiz;
35803 +       hcchar_data_t hcchar;
35804 +       haint_data_t haint;
35805 +       hcint_data_t hcint;
35806 +       host_grxsts_data_t grxsts;
35807 +
35808 +       /* Enable HAINTs */
35809 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35810 +
35811 +       /* Enable HCINTs */
35812 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35813 +
35814 +       /* Read GINTSTS */
35815 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35816 +
35817 +       /* Read HAINT */
35818 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35819 +
35820 +       /* Read HCINT */
35821 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35822 +
35823 +       /* Read HCCHAR */
35824 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35825 +
35826 +       /* Clear HCINT */
35827 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35828 +
35829 +       /* Clear HAINT */
35830 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35831 +
35832 +       /* Clear GINTSTS */
35833 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35834 +
35835 +       /* Read GINTSTS */
35836 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35837 +
35838 +       /*
35839 +        * Receive Control In packet
35840 +        */
35841 +
35842 +       /* Make sure channel is disabled */
35843 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35844 +       if (hcchar.b.chen) {
35845 +               hcchar.b.chdis = 1;
35846 +               hcchar.b.chen = 1;
35847 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35848 +               //sleep(1);
35849 +               dwc_mdelay(1000);
35850 +
35851 +               /* Read GINTSTS */
35852 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35853 +
35854 +               /* Read HAINT */
35855 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35856 +
35857 +               /* Read HCINT */
35858 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35859 +
35860 +               /* Read HCCHAR */
35861 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35862 +
35863 +               /* Clear HCINT */
35864 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35865 +
35866 +               /* Clear HAINT */
35867 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35868 +
35869 +               /* Clear GINTSTS */
35870 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35871 +
35872 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35873 +       }
35874 +
35875 +       /* Set HCTSIZ */
35876 +       hctsiz.d32 = 0;
35877 +       hctsiz.b.xfersize = 8;
35878 +       hctsiz.b.pktcnt = 1;
35879 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
35880 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35881 +
35882 +       /* Set HCCHAR */
35883 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35884 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35885 +       hcchar.b.epdir = 1;
35886 +       hcchar.b.epnum = 0;
35887 +       hcchar.b.mps = 8;
35888 +       hcchar.b.chen = 1;
35889 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35890 +
35891 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35892 +
35893 +       /* Wait for receive status queue interrupt */
35894 +       do {
35895 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35896 +       } while (gintsts.b.rxstsqlvl == 0);
35897 +
35898 +       /* Read RXSTS */
35899 +       grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35900 +
35901 +       /* Clear RXSTSQLVL in GINTSTS */
35902 +       gintsts.d32 = 0;
35903 +       gintsts.b.rxstsqlvl = 1;
35904 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35905 +
35906 +       switch (grxsts.b.pktsts) {
35907 +       case DWC_GRXSTS_PKTSTS_IN:
35908 +               /* Read the data into the host buffer */
35909 +               if (grxsts.b.bcnt > 0) {
35910 +                       int i;
35911 +                       int word_count = (grxsts.b.bcnt + 3) / 4;
35912 +
35913 +                       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35914 +
35915 +                       for (i = 0; i < word_count; i++) {
35916 +                               (void)DWC_READ_REG32(data_fifo++);
35917 +                       }
35918 +               }
35919 +               break;
35920 +
35921 +       default:
35922 +               break;
35923 +       }
35924 +
35925 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35926 +
35927 +       /* Wait for receive status queue interrupt */
35928 +       do {
35929 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35930 +       } while (gintsts.b.rxstsqlvl == 0);
35931 +
35932 +       /* Read RXSTS */
35933 +       grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35934 +
35935 +       /* Clear RXSTSQLVL in GINTSTS */
35936 +       gintsts.d32 = 0;
35937 +       gintsts.b.rxstsqlvl = 1;
35938 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35939 +
35940 +       switch (grxsts.b.pktsts) {
35941 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
35942 +               break;
35943 +
35944 +       default:
35945 +               break;
35946 +       }
35947 +
35948 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35949 +
35950 +       /* Wait for host channel interrupt */
35951 +       do {
35952 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35953 +       } while (gintsts.b.hcintr == 0);
35954 +
35955 +       /* Read HAINT */
35956 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35957 +
35958 +       /* Read HCINT */
35959 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35960 +
35961 +       /* Read HCCHAR */
35962 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35963 +
35964 +       /* Clear HCINT */
35965 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35966 +
35967 +       /* Clear HAINT */
35968 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35969 +
35970 +       /* Clear GINTSTS */
35971 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35972 +
35973 +       /* Read GINTSTS */
35974 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35975 +
35976 +//      usleep(100000);
35977 +//      mdelay(100);
35978 +       dwc_mdelay(1);
35979 +
35980 +       /*
35981 +        * Send handshake packet
35982 +        */
35983 +
35984 +       /* Read HAINT */
35985 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35986 +
35987 +       /* Read HCINT */
35988 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35989 +
35990 +       /* Read HCCHAR */
35991 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35992 +
35993 +       /* Clear HCINT */
35994 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35995 +
35996 +       /* Clear HAINT */
35997 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35998 +
35999 +       /* Clear GINTSTS */
36000 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
36001 +
36002 +       /* Read GINTSTS */
36003 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
36004 +
36005 +       /* Make sure channel is disabled */
36006 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
36007 +       if (hcchar.b.chen) {
36008 +               hcchar.b.chdis = 1;
36009 +               hcchar.b.chen = 1;
36010 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
36011 +               //sleep(1);
36012 +               dwc_mdelay(1000);
36013 +
36014 +               /* Read GINTSTS */
36015 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
36016 +
36017 +               /* Read HAINT */
36018 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
36019 +
36020 +               /* Read HCINT */
36021 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
36022 +
36023 +               /* Read HCCHAR */
36024 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
36025 +
36026 +               /* Clear HCINT */
36027 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
36028 +
36029 +               /* Clear HAINT */
36030 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
36031 +
36032 +               /* Clear GINTSTS */
36033 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
36034 +
36035 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
36036 +       }
36037 +
36038 +       /* Set HCTSIZ */
36039 +       hctsiz.d32 = 0;
36040 +       hctsiz.b.xfersize = 0;
36041 +       hctsiz.b.pktcnt = 1;
36042 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
36043 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
36044 +
36045 +       /* Set HCCHAR */
36046 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
36047 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
36048 +       hcchar.b.epdir = 0;
36049 +       hcchar.b.epnum = 0;
36050 +       hcchar.b.mps = 8;
36051 +       hcchar.b.chen = 1;
36052 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
36053 +
36054 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
36055 +
36056 +       /* Wait for host channel interrupt */
36057 +       do {
36058 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
36059 +       } while (gintsts.b.hcintr == 0);
36060 +
36061 +       /* Disable HCINTs */
36062 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
36063 +
36064 +       /* Disable HAINTs */
36065 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
36066 +
36067 +       /* Read HAINT */
36068 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
36069 +
36070 +       /* Read HCINT */
36071 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
36072 +
36073 +       /* Read HCCHAR */
36074 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
36075 +
36076 +       /* Clear HCINT */
36077 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
36078 +
36079 +       /* Clear HAINT */
36080 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
36081 +
36082 +       /* Clear GINTSTS */
36083 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
36084 +
36085 +       /* Read GINTSTS */
36086 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
36087 +}
36088 +#endif
36089 +
36090 +/** Handles hub class-specific requests. */
36091 +int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
36092 +                           uint16_t typeReq,
36093 +                           uint16_t wValue,
36094 +                           uint16_t wIndex, uint8_t * buf, uint16_t wLength)
36095 +{
36096 +       int retval = 0;
36097 +
36098 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
36099 +       usb_hub_descriptor_t *hub_desc;
36100 +       hprt0_data_t hprt0 = {.d32 = 0 };
36101 +
36102 +       uint32_t port_status;
36103 +
36104 +       switch (typeReq) {
36105 +       case UCR_CLEAR_HUB_FEATURE:
36106 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36107 +                           "ClearHubFeature 0x%x\n", wValue);
36108 +               switch (wValue) {
36109 +               case UHF_C_HUB_LOCAL_POWER:
36110 +               case UHF_C_HUB_OVER_CURRENT:
36111 +                       /* Nothing required here */
36112 +                       break;
36113 +               default:
36114 +                       retval = -DWC_E_INVALID;
36115 +                       DWC_ERROR("DWC OTG HCD - "
36116 +                                 "ClearHubFeature request %xh unknown\n",
36117 +                                 wValue);
36118 +               }
36119 +               break;
36120 +       case UCR_CLEAR_PORT_FEATURE:
36121 +#ifdef CONFIG_USB_DWC_OTG_LPM
36122 +               if (wValue != UHF_PORT_L1)
36123 +#endif
36124 +                       if (!wIndex || wIndex > 1)
36125 +                               goto error;
36126 +
36127 +               switch (wValue) {
36128 +               case UHF_PORT_ENABLE:
36129 +                       DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
36130 +                                   "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
36131 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36132 +                       hprt0.b.prtena = 1;
36133 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36134 +                       break;
36135 +               case UHF_PORT_SUSPEND:
36136 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36137 +                                   "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
36138 +
36139 +                       if (core_if->power_down == 2) {
36140 +                               dwc_otg_host_hibernation_restore(core_if, 0, 0);
36141 +                       } else {
36142 +                               DWC_WRITE_REG32(core_if->pcgcctl, 0);
36143 +                               dwc_mdelay(5);
36144 +
36145 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36146 +                               hprt0.b.prtres = 1;
36147 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36148 +                               hprt0.b.prtsusp = 0;
36149 +                               /* Clear Resume bit */
36150 +                               dwc_mdelay(100);
36151 +                               hprt0.b.prtres = 0;
36152 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36153 +                       }
36154 +                       break;
36155 +#ifdef CONFIG_USB_DWC_OTG_LPM
36156 +               case UHF_PORT_L1:
36157 +                       {
36158 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36159 +                               glpmcfg_data_t lpmcfg = {.d32 = 0 };
36160 +
36161 +                               lpmcfg.d32 =
36162 +                                   DWC_READ_REG32(&core_if->
36163 +                                                  core_global_regs->glpmcfg);
36164 +                               lpmcfg.b.en_utmi_sleep = 0;
36165 +                               lpmcfg.b.hird_thres &= (~(1 << 4));
36166 +                               lpmcfg.b.prt_sleep_sts = 1;
36167 +                               DWC_WRITE_REG32(&core_if->
36168 +                                               core_global_regs->glpmcfg,
36169 +                                               lpmcfg.d32);
36170 +
36171 +                               /* Clear Enbl_L1Gating bit. */
36172 +                               pcgcctl.b.enbl_sleep_gating = 1;
36173 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
36174 +                                                0);
36175 +
36176 +                               dwc_mdelay(5);
36177 +
36178 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36179 +                               hprt0.b.prtres = 1;
36180 +                               DWC_WRITE_REG32(core_if->host_if->hprt0,
36181 +                                               hprt0.d32);
36182 +                               /* This bit will be cleared in wakeup interrupt handle */
36183 +                               break;
36184 +                       }
36185 +#endif
36186 +               case UHF_PORT_POWER:
36187 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36188 +                                   "ClearPortFeature USB_PORT_FEAT_POWER\n");
36189 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36190 +                       hprt0.b.prtpwr = 0;
36191 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36192 +                       break;
36193 +               case UHF_PORT_INDICATOR:
36194 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36195 +                                   "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
36196 +                       /* Port inidicator not supported */
36197 +                       break;
36198 +               case UHF_C_PORT_CONNECTION:
36199 +                       /* Clears drivers internal connect status change
36200 +                        * flag */
36201 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36202 +                                   "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
36203 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 0;
36204 +                       break;
36205 +               case UHF_C_PORT_RESET:
36206 +                       /* Clears the driver's internal Port Reset Change
36207 +                        * flag */
36208 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36209 +                                   "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
36210 +                       dwc_otg_hcd->flags.b.port_reset_change = 0;
36211 +                       break;
36212 +               case UHF_C_PORT_ENABLE:
36213 +                       /* Clears the driver's internal Port
36214 +                        * Enable/Disable Change flag */
36215 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36216 +                                   "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
36217 +                       dwc_otg_hcd->flags.b.port_enable_change = 0;
36218 +                       break;
36219 +               case UHF_C_PORT_SUSPEND:
36220 +                       /* Clears the driver's internal Port Suspend
36221 +                        * Change flag, which is set when resume signaling on
36222 +                        * the host port is complete */
36223 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36224 +                                   "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
36225 +                       dwc_otg_hcd->flags.b.port_suspend_change = 0;
36226 +                       break;
36227 +#ifdef CONFIG_USB_DWC_OTG_LPM
36228 +               case UHF_C_PORT_L1:
36229 +                       dwc_otg_hcd->flags.b.port_l1_change = 0;
36230 +                       break;
36231 +#endif
36232 +               case UHF_C_PORT_OVER_CURRENT:
36233 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36234 +                                   "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
36235 +                       dwc_otg_hcd->flags.b.port_over_current_change = 0;
36236 +                       break;
36237 +               default:
36238 +                       retval = -DWC_E_INVALID;
36239 +                       DWC_ERROR("DWC OTG HCD - "
36240 +                                 "ClearPortFeature request %xh "
36241 +                                 "unknown or unsupported\n", wValue);
36242 +               }
36243 +               break;
36244 +       case UCR_GET_HUB_DESCRIPTOR:
36245 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36246 +                           "GetHubDescriptor\n");
36247 +               hub_desc = (usb_hub_descriptor_t *) buf;
36248 +               hub_desc->bDescLength = 9;
36249 +               hub_desc->bDescriptorType = 0x29;
36250 +               hub_desc->bNbrPorts = 1;
36251 +               USETW(hub_desc->wHubCharacteristics, 0x08);
36252 +               hub_desc->bPwrOn2PwrGood = 1;
36253 +               hub_desc->bHubContrCurrent = 0;
36254 +               hub_desc->DeviceRemovable[0] = 0;
36255 +               hub_desc->DeviceRemovable[1] = 0xff;
36256 +               break;
36257 +       case UCR_GET_HUB_STATUS:
36258 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36259 +                           "GetHubStatus\n");
36260 +               DWC_MEMSET(buf, 0, 4);
36261 +               break;
36262 +       case UCR_GET_PORT_STATUS:
36263 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36264 +                           "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
36265 +                           wIndex, dwc_otg_hcd->flags.d32);
36266 +               if (!wIndex || wIndex > 1)
36267 +                       goto error;
36268 +
36269 +               port_status = 0;
36270 +
36271 +               if (dwc_otg_hcd->flags.b.port_connect_status_change)
36272 +                       port_status |= (1 << UHF_C_PORT_CONNECTION);
36273 +
36274 +               if (dwc_otg_hcd->flags.b.port_enable_change)
36275 +                       port_status |= (1 << UHF_C_PORT_ENABLE);
36276 +
36277 +               if (dwc_otg_hcd->flags.b.port_suspend_change)
36278 +                       port_status |= (1 << UHF_C_PORT_SUSPEND);
36279 +
36280 +               if (dwc_otg_hcd->flags.b.port_l1_change)
36281 +                       port_status |= (1 << UHF_C_PORT_L1);
36282 +
36283 +               if (dwc_otg_hcd->flags.b.port_reset_change) {
36284 +                       port_status |= (1 << UHF_C_PORT_RESET);
36285 +               }
36286 +
36287 +               if (dwc_otg_hcd->flags.b.port_over_current_change) {
36288 +                       DWC_WARN("Overcurrent change detected\n");
36289 +                       port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
36290 +               }
36291 +
36292 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
36293 +                       /*
36294 +                        * The port is disconnected, which means the core is
36295 +                        * either in device mode or it soon will be. Just
36296 +                        * return 0's for the remainder of the port status
36297 +                        * since the port register can't be read if the core
36298 +                        * is in device mode.
36299 +                        */
36300 +                       *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36301 +                       break;
36302 +               }
36303 +
36304 +               hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
36305 +               DWC_DEBUGPL(DBG_HCDV, "  HPRT0: 0x%08x\n", hprt0.d32);
36306 +
36307 +               if (hprt0.b.prtconnsts)
36308 +                       port_status |= (1 << UHF_PORT_CONNECTION);
36309 +
36310 +               if (hprt0.b.prtena)
36311 +                       port_status |= (1 << UHF_PORT_ENABLE);
36312 +
36313 +               if (hprt0.b.prtsusp)
36314 +                       port_status |= (1 << UHF_PORT_SUSPEND);
36315 +
36316 +               if (hprt0.b.prtovrcurract)
36317 +                       port_status |= (1 << UHF_PORT_OVER_CURRENT);
36318 +
36319 +               if (hprt0.b.prtrst)
36320 +                       port_status |= (1 << UHF_PORT_RESET);
36321 +
36322 +               if (hprt0.b.prtpwr)
36323 +                       port_status |= (1 << UHF_PORT_POWER);
36324 +
36325 +               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
36326 +                       port_status |= (1 << UHF_PORT_HIGH_SPEED);
36327 +               else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
36328 +                       port_status |= (1 << UHF_PORT_LOW_SPEED);
36329 +
36330 +               if (hprt0.b.prttstctl)
36331 +                       port_status |= (1 << UHF_PORT_TEST);
36332 +               if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
36333 +                       port_status |= (1 << UHF_PORT_L1);
36334 +               }
36335 +               /*
36336 +                  For Synopsys HW emulation of Power down wkup_control asserts the 
36337 +                  hreset_n and prst_n on suspned. This causes the HPRT0 to be zero. 
36338 +                  We intentionally tell the software that port is in L2Suspend state. 
36339 +                  Only for STE.
36340 +               */
36341 +               if ((core_if->power_down == 2)
36342 +                   && (core_if->hibernation_suspend == 1)) {
36343 +                       port_status |= (1 << UHF_PORT_SUSPEND);
36344 +               }
36345 +               /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
36346 +
36347 +               *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36348 +
36349 +               break;
36350 +       case UCR_SET_HUB_FEATURE:
36351 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36352 +                           "SetHubFeature\n");
36353 +               /* No HUB features supported */
36354 +               break;
36355 +       case UCR_SET_PORT_FEATURE:
36356 +               if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
36357 +                       goto error;
36358 +
36359 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
36360 +                       /*
36361 +                        * The port is disconnected, which means the core is
36362 +                        * either in device mode or it soon will be. Just
36363 +                        * return without doing anything since the port
36364 +                        * register can't be written if the core is in device
36365 +                        * mode.
36366 +                        */
36367 +                       break;
36368 +               }
36369 +
36370 +               switch (wValue) {
36371 +               case UHF_PORT_SUSPEND:
36372 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36373 +                                   "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
36374 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
36375 +                               goto error;
36376 +                       }
36377 +                       if (core_if->power_down == 2) {
36378 +                               int timeout = 300;
36379 +                               dwc_irqflags_t flags;
36380 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36381 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
36382 +                               gusbcfg_data_t gusbcfg = {.d32 = 0 };
36383 +#ifdef DWC_DEV_SRPCAP
36384 +                               int32_t otg_cap_param = core_if->core_params->otg_cap;
36385 +#endif
36386 +                               DWC_PRINTF("Preparing for complete power-off\n");
36387 +
36388 +                               /* Save registers before hibernation */
36389 +                               dwc_otg_save_global_regs(core_if);
36390 +                               dwc_otg_save_host_regs(core_if);
36391 +
36392 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36393 +                               hprt0.b.prtsusp = 1;
36394 +                               hprt0.b.prtena = 0;
36395 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36396 +                               /* Spin hprt0.b.prtsusp to became 1 */
36397 +                               do {
36398 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36399 +                                       if (hprt0.b.prtsusp) {
36400 +                                               break;
36401 +                                       }
36402 +                                       dwc_mdelay(1);
36403 +                               } while (--timeout);
36404 +                               if (!timeout) {
36405 +                                       DWC_WARN("Suspend wasn't genereted\n");
36406 +                               }
36407 +                               dwc_udelay(10);
36408 +
36409 +                               /*
36410 +                                * We need to disable interrupts to prevent servicing of any IRQ
36411 +                                * during going to hibernation
36412 +                                */
36413 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36414 +                               core_if->lx_state = DWC_OTG_L2;
36415 +#ifdef DWC_DEV_SRPCAP
36416 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36417 +                               hprt0.b.prtpwr = 0;
36418 +                               hprt0.b.prtena = 0;
36419 +                               DWC_WRITE_REG32(core_if->host_if->hprt0,
36420 +                                               hprt0.d32);
36421 +#endif
36422 +                               gusbcfg.d32 =
36423 +                                   DWC_READ_REG32(&core_if->core_global_regs->
36424 +                                                  gusbcfg);
36425 +                               if (gusbcfg.b.ulpi_utmi_sel == 1) {
36426 +                                       /* ULPI interface */
36427 +                                       /* Suspend the Phy Clock */
36428 +                                       pcgcctl.d32 = 0;
36429 +                                       pcgcctl.b.stoppclk = 1;
36430 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36431 +                                                        pcgcctl.d32);
36432 +                                       dwc_udelay(10);
36433 +                                       gpwrdn.b.pmuactv = 1;
36434 +                                       DWC_MODIFY_REG32(&core_if->
36435 +                                                        core_global_regs->
36436 +                                                        gpwrdn, 0, gpwrdn.d32);
36437 +                               } else {
36438 +                                       /* UTMI+ Interface */
36439 +                                       gpwrdn.b.pmuactv = 1;
36440 +                                       DWC_MODIFY_REG32(&core_if->
36441 +                                                        core_global_regs->
36442 +                                                        gpwrdn, 0, gpwrdn.d32);
36443 +                                       dwc_udelay(10);
36444 +                                       pcgcctl.b.stoppclk = 1;
36445 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
36446 +                                       dwc_udelay(10);
36447 +                               }
36448 +#ifdef DWC_DEV_SRPCAP                          
36449 +                               gpwrdn.d32 = 0;
36450 +                               gpwrdn.b.dis_vbus = 1;
36451 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36452 +                                                gpwrdn, 0, gpwrdn.d32);
36453 +#endif
36454 +                               gpwrdn.d32 = 0;
36455 +                               gpwrdn.b.pmuintsel = 1;
36456 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36457 +                                                gpwrdn, 0, gpwrdn.d32);
36458 +                               dwc_udelay(10);
36459 +
36460 +                               gpwrdn.d32 = 0;
36461 +#ifdef DWC_DEV_SRPCAP
36462 +                               gpwrdn.b.srp_det_msk = 1;
36463 +#endif
36464 +                               gpwrdn.b.disconn_det_msk = 1;
36465 +                               gpwrdn.b.lnstchng_msk = 1;
36466 +                               gpwrdn.b.sts_chngint_msk = 1;
36467 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36468 +                                                gpwrdn, 0, gpwrdn.d32);
36469 +                               dwc_udelay(10);
36470 +
36471 +                               /* Enable Power Down Clamp and all interrupts in GPWRDN */
36472 +                               gpwrdn.d32 = 0;
36473 +                               gpwrdn.b.pwrdnclmp = 1;
36474 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36475 +                                                gpwrdn, 0, gpwrdn.d32);
36476 +                               dwc_udelay(10);
36477 +
36478 +                               /* Switch off VDD */
36479 +                               gpwrdn.d32 = 0;
36480 +                               gpwrdn.b.pwrdnswtch = 1;
36481 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36482 +                                                gpwrdn, 0, gpwrdn.d32);
36483 +
36484 +#ifdef DWC_DEV_SRPCAP
36485 +                               if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
36486 +                               {
36487 +                                       core_if->pwron_timer_started = 1;
36488 +                                       DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );
36489 +                               }
36490 +#endif
36491 +                               /* Save gpwrdn register for further usage if stschng interrupt */
36492 +                               core_if->gr_backup->gpwrdn_local =
36493 +                                               DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
36494 +
36495 +                               /* Set flag to indicate that we are in hibernation */
36496 +                               core_if->hibernation_suspend = 1;
36497 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);
36498 +
36499 +                               DWC_PRINTF("Host hibernation completed\n");
36500 +                               // Exit from case statement
36501 +                               break;
36502 +
36503 +                       }
36504 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
36505 +                           dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36506 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
36507 +                               gotgctl.b.hstsethnpen = 1;
36508 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36509 +                                                gotgctl, 0, gotgctl.d32);
36510 +                               core_if->op_state = A_SUSPEND;
36511 +                       }
36512 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36513 +                       hprt0.b.prtsusp = 1;
36514 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36515 +                       {
36516 +                               dwc_irqflags_t flags;
36517 +                               /* Update lx_state */
36518 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36519 +                               core_if->lx_state = DWC_OTG_L2;
36520 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
36521 +                       }
36522 +                       /* Suspend the Phy Clock */
36523 +                       {
36524 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36525 +                               pcgcctl.b.stoppclk = 1;
36526 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36527 +                                                pcgcctl.d32);
36528 +                               dwc_udelay(10);
36529 +                       }
36530 +
36531 +                       /* For HNP the bus must be suspended for at least 200ms. */
36532 +                       if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36533 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36534 +                               pcgcctl.b.stoppclk = 1;
36535 +                DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36536 +                               dwc_mdelay(200);
36537 +                       }
36538 +
36539 +                       /** @todo - check how sw can wait for 1 sec to check asesvld??? */
36540 +#if 0 //vahrama !!!!!!!!!!!!!!!!!!
36541 +                       if (core_if->adp_enable) {
36542 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
36543 +                               gpwrdn_data_t gpwrdn;
36544 +
36545 +                               while (gotgctl.b.asesvld == 1) {
36546 +                                       gotgctl.d32 =
36547 +                                           DWC_READ_REG32(&core_if->
36548 +                                                          core_global_regs->
36549 +                                                          gotgctl);
36550 +                                       dwc_mdelay(100);
36551 +                               }
36552 +
36553 +                               /* Enable Power Down Logic */
36554 +                               gpwrdn.d32 = 0;
36555 +                               gpwrdn.b.pmuactv = 1;
36556 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36557 +                                                gpwrdn, 0, gpwrdn.d32);
36558 +
36559 +                               /* Unmask SRP detected interrupt from Power Down Logic */
36560 +                               gpwrdn.d32 = 0;
36561 +                               gpwrdn.b.srp_det_msk = 1;
36562 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36563 +                                                gpwrdn, 0, gpwrdn.d32);
36564 +
36565 +                               dwc_otg_adp_probe_start(core_if);
36566 +                       }
36567 +#endif
36568 +                       break;
36569 +               case UHF_PORT_POWER:
36570 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36571 +                                   "SetPortFeature - USB_PORT_FEAT_POWER\n");
36572 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36573 +                       hprt0.b.prtpwr = 1;
36574 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36575 +                       break;
36576 +               case UHF_PORT_RESET:
36577 +                       if ((core_if->power_down == 2)
36578 +                           && (core_if->hibernation_suspend == 1)) {
36579 +                               /* If we are going to exit from Hibernated
36580 +                                * state via USB RESET.
36581 +                                */
36582 +                               dwc_otg_host_hibernation_restore(core_if, 0, 1);
36583 +                       } else {
36584 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36585 +
36586 +                               DWC_DEBUGPL(DBG_HCD,
36587 +                                           "DWC OTG HCD HUB CONTROL - "
36588 +                                           "SetPortFeature - USB_PORT_FEAT_RESET\n");
36589 +                               {
36590 +                                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
36591 +                                       pcgcctl.b.enbl_sleep_gating = 1;
36592 +                                       pcgcctl.b.stoppclk = 1;
36593 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36594 +                                       DWC_WRITE_REG32(core_if->pcgcctl, 0);
36595 +                               }
36596 +#ifdef CONFIG_USB_DWC_OTG_LPM
36597 +                               {
36598 +                                       glpmcfg_data_t lpmcfg;
36599 +                                       lpmcfg.d32 =
36600 +                                               DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36601 +                                       if (lpmcfg.b.prt_sleep_sts) {
36602 +                                               lpmcfg.b.en_utmi_sleep = 0;
36603 +                                               lpmcfg.b.hird_thres &= (~(1 << 4));
36604 +                                               DWC_WRITE_REG32
36605 +                                                   (&core_if->core_global_regs->glpmcfg,
36606 +                                                    lpmcfg.d32);
36607 +                                               dwc_mdelay(1);
36608 +                                       }
36609 +                               }
36610 +#endif
36611 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36612 +                               /* Clear suspend bit if resetting from suspended state. */
36613 +                               hprt0.b.prtsusp = 0;
36614 +                               /* When B-Host the Port reset bit is set in
36615 +                                * the Start HCD Callback function, so that
36616 +                                * the reset is started within 1ms of the HNP
36617 +                                * success interrupt. */
36618 +                               if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
36619 +                                       hprt0.b.prtpwr = 1;
36620 +                                       hprt0.b.prtrst = 1;
36621 +                                       DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);
36622 +                                       DWC_WRITE_REG32(core_if->host_if->hprt0,
36623 +                                                       hprt0.d32);
36624 +                               }
36625 +                               /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
36626 +                               dwc_mdelay(60);
36627 +                               hprt0.b.prtrst = 0;
36628 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36629 +                               core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
36630 +                       }
36631 +                       break;
36632 +#ifdef DWC_HS_ELECT_TST
36633 +               case UHF_PORT_TEST:
36634 +                       {
36635 +                               uint32_t t;
36636 +                               gintmsk_data_t gintmsk;
36637 +
36638 +                               t = (wIndex >> 8);      /* MSB wIndex USB */
36639 +                               DWC_DEBUGPL(DBG_HCD,
36640 +                                           "DWC OTG HCD HUB CONTROL - "
36641 +                                           "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
36642 +                                           t);
36643 +                               DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
36644 +                               if (t < 6) {
36645 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36646 +                                       hprt0.b.prttstctl = t;
36647 +                                       DWC_WRITE_REG32(core_if->host_if->hprt0,
36648 +                                                       hprt0.d32);
36649 +                               } else {
36650 +                                       /* Setup global vars with reg addresses (quick and
36651 +                                        * dirty hack, should be cleaned up)
36652 +                                        */
36653 +                                       global_regs = core_if->core_global_regs;
36654 +                                       hc_global_regs =
36655 +                                           core_if->host_if->host_global_regs;
36656 +                                       hc_regs =
36657 +                                           (dwc_otg_hc_regs_t *) ((char *)
36658 +                                                                  global_regs +
36659 +                                                                  0x500);
36660 +                                       data_fifo =
36661 +                                           (uint32_t *) ((char *)global_regs +
36662 +                                                         0x1000);
36663 +
36664 +                                       if (t == 6) {   /* HS_HOST_PORT_SUSPEND_RESUME */
36665 +                                               /* Save current interrupt mask */
36666 +                                               gintmsk.d32 =
36667 +                                                   DWC_READ_REG32
36668 +                                                   (&global_regs->gintmsk);
36669 +
36670 +                                               /* Disable all interrupts while we muck with
36671 +                                                * the hardware directly
36672 +                                                */
36673 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36674 +
36675 +                                               /* 15 second delay per the test spec */
36676 +                                               dwc_mdelay(15000);
36677 +
36678 +                                               /* Drive suspend on the root port */
36679 +                                               hprt0.d32 =
36680 +                                                   dwc_otg_read_hprt0(core_if);
36681 +                                               hprt0.b.prtsusp = 1;
36682 +                                               hprt0.b.prtres = 0;
36683 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36684 +
36685 +                                               /* 15 second delay per the test spec */
36686 +                                               dwc_mdelay(15000);
36687 +
36688 +                                               /* Drive resume on the root port */
36689 +                                               hprt0.d32 =
36690 +                                                   dwc_otg_read_hprt0(core_if);
36691 +                                               hprt0.b.prtsusp = 0;
36692 +                                               hprt0.b.prtres = 1;
36693 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36694 +                                               dwc_mdelay(100);
36695 +
36696 +                                               /* Clear the resume bit */
36697 +                                               hprt0.b.prtres = 0;
36698 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36699 +
36700 +                                               /* Restore interrupts */
36701 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36702 +                                       } else if (t == 7) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
36703 +                                               /* Save current interrupt mask */
36704 +                                               gintmsk.d32 =
36705 +                                                   DWC_READ_REG32
36706 +                                                   (&global_regs->gintmsk);
36707 +
36708 +                                               /* Disable all interrupts while we muck with
36709 +                                                * the hardware directly
36710 +                                                */
36711 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36712 +
36713 +                                               /* 15 second delay per the test spec */
36714 +                                               dwc_mdelay(15000);
36715 +
36716 +                                               /* Send the Setup packet */
36717 +                                               do_setup();
36718 +
36719 +                                               /* 15 second delay so nothing else happens for awhile */
36720 +                                               dwc_mdelay(15000);
36721 +
36722 +                                               /* Restore interrupts */
36723 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36724 +                                       } else if (t == 8) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
36725 +                                               /* Save current interrupt mask */
36726 +                                               gintmsk.d32 =
36727 +                                                   DWC_READ_REG32
36728 +                                                   (&global_regs->gintmsk);
36729 +
36730 +                                               /* Disable all interrupts while we muck with
36731 +                                                * the hardware directly
36732 +                                                */
36733 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36734 +
36735 +                                               /* Send the Setup packet */
36736 +                                               do_setup();
36737 +
36738 +                                               /* 15 second delay so nothing else happens for awhile */
36739 +                                               dwc_mdelay(15000);
36740 +
36741 +                                               /* Send the In and Ack packets */
36742 +                                               do_in_ack();
36743 +
36744 +                                               /* 15 second delay so nothing else happens for awhile */
36745 +                                               dwc_mdelay(15000);
36746 +
36747 +                                               /* Restore interrupts */
36748 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36749 +                                       }
36750 +                               }
36751 +                               break;
36752 +                       }
36753 +#endif /* DWC_HS_ELECT_TST */
36754 +
36755 +               case UHF_PORT_INDICATOR:
36756 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36757 +                                   "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
36758 +                       /* Not supported */
36759 +                       break;
36760 +               default:
36761 +                       retval = -DWC_E_INVALID;
36762 +                       DWC_ERROR("DWC OTG HCD - "
36763 +                                 "SetPortFeature request %xh "
36764 +                                 "unknown or unsupported\n", wValue);
36765 +                       break;
36766 +               }
36767 +               break;
36768 +#ifdef CONFIG_USB_DWC_OTG_LPM
36769 +       case UCR_SET_AND_TEST_PORT_FEATURE:
36770 +               if (wValue != UHF_PORT_L1) {
36771 +                       goto error;
36772 +               }
36773 +               {
36774 +                       int portnum, hird, devaddr, remwake;
36775 +                       glpmcfg_data_t lpmcfg;
36776 +                       uint32_t time_usecs;
36777 +                       gintsts_data_t gintsts;
36778 +                       gintmsk_data_t gintmsk;
36779 +
36780 +                       if (!dwc_otg_get_param_lpm_enable(core_if)) {
36781 +                               goto error;
36782 +                       }
36783 +                       if (wValue != UHF_PORT_L1 || wLength != 1) {
36784 +                               goto error;
36785 +                       }
36786 +                       /* Check if the port currently is in SLEEP state */
36787 +                       lpmcfg.d32 =
36788 +                           DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36789 +                       if (lpmcfg.b.prt_sleep_sts) {
36790 +                               DWC_INFO("Port is already in sleep mode\n");
36791 +                               buf[0] = 0;     /* Return success */
36792 +                               break;
36793 +                       }
36794 +
36795 +                       portnum = wIndex & 0xf;
36796 +                       hird = (wIndex >> 4) & 0xf;
36797 +                       devaddr = (wIndex >> 8) & 0x7f;
36798 +                       remwake = (wIndex >> 15);
36799 +
36800 +                       if (portnum != 1) {
36801 +                               retval = -DWC_E_INVALID;
36802 +                               DWC_WARN
36803 +                                   ("Wrong port number(%d) in SetandTestPortFeature request\n",
36804 +                                    portnum);
36805 +                               break;
36806 +                       }
36807 +
36808 +                       DWC_PRINTF
36809 +                           ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
36810 +                            portnum, hird, devaddr, remwake);
36811 +                       /* Disable LPM interrupt */
36812 +                       gintmsk.d32 = 0;
36813 +                       gintmsk.b.lpmtranrcvd = 1;
36814 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
36815 +                                        gintmsk.d32, 0);
36816 +
36817 +                       if (dwc_otg_hcd_send_lpm
36818 +                           (dwc_otg_hcd, devaddr, hird, remwake)) {
36819 +                               retval = -DWC_E_INVALID;
36820 +                               break;
36821 +                       }
36822 +
36823 +                       time_usecs = 10 * (lpmcfg.b.retry_count + 1);
36824 +                       /* We will consider timeout if time_usecs microseconds pass,
36825 +                        * and we don't receive LPM transaction status.
36826 +                        * After receiving non-error responce(ACK/NYET/STALL) from device,
36827 +                        *  core will set lpmtranrcvd bit.
36828 +                        */
36829 +                       do {
36830 +                               gintsts.d32 =
36831 +                                   DWC_READ_REG32(&core_if->core_global_regs->gintsts);
36832 +                               if (gintsts.b.lpmtranrcvd) {
36833 +                                       break;
36834 +                               }
36835 +                               dwc_udelay(1);
36836 +                       } while (--time_usecs);
36837 +                       /* lpm_int bit will be cleared in LPM interrupt handler */
36838 +
36839 +                       /* Now fill status
36840 +                        * 0x00 - Success
36841 +                        * 0x10 - NYET
36842 +                        * 0x11 - Timeout
36843 +                        */
36844 +                       if (!gintsts.b.lpmtranrcvd) {
36845 +                               buf[0] = 0x3;   /* Completion code is Timeout */
36846 +                               dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
36847 +                       } else {
36848 +                               lpmcfg.d32 =
36849 +                                   DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36850 +                               if (lpmcfg.b.lpm_resp == 0x3) {
36851 +                                       /* ACK responce from the device */
36852 +                                       buf[0] = 0x00;  /* Success */
36853 +                               } else if (lpmcfg.b.lpm_resp == 0x2) {
36854 +                                       /* NYET responce from the device */
36855 +                                       buf[0] = 0x2;
36856 +                               } else {
36857 +                                       /* Otherwise responce with Timeout */
36858 +                                       buf[0] = 0x3;
36859 +                               }
36860 +                       }
36861 +                       DWC_PRINTF("Device responce to LPM trans is %x\n",
36862 +                                  lpmcfg.b.lpm_resp);
36863 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
36864 +                                        gintmsk.d32);
36865 +
36866 +                       break;
36867 +               }
36868 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36869 +       default:
36870 +error:
36871 +               retval = -DWC_E_INVALID;
36872 +               DWC_WARN("DWC OTG HCD - "
36873 +                        "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
36874 +                        typeReq, wIndex, wValue);
36875 +               break;
36876 +       }
36877 +
36878 +       return retval;
36879 +}
36880 +
36881 +#ifdef CONFIG_USB_DWC_OTG_LPM
36882 +/** Returns index of host channel to perform LPM transaction. */
36883 +int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
36884 +{
36885 +       dwc_otg_core_if_t *core_if = hcd->core_if;
36886 +       dwc_hc_t *hc;
36887 +       hcchar_data_t hcchar;
36888 +       gintmsk_data_t gintmsk = {.d32 = 0 };
36889 +
36890 +       if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
36891 +               DWC_PRINTF("No free channel to select for LPM transaction\n");
36892 +               return -1;
36893 +       }
36894 +
36895 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
36896 +
36897 +       /* Mask host channel interrupts. */
36898 +       gintmsk.b.hcintr = 1;
36899 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
36900 +
36901 +       /* Fill fields that core needs for LPM transaction */
36902 +       hcchar.b.devaddr = devaddr;
36903 +       hcchar.b.epnum = 0;
36904 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
36905 +       hcchar.b.mps = 64;
36906 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
36907 +       hcchar.b.epdir = 0;     /* OUT */
36908 +       DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
36909 +                       hcchar.d32);
36910 +
36911 +       /* Remove the host channel from the free list. */
36912 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
36913 +
36914 +       DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
36915 +
36916 +       return hc->hc_num;
36917 +}
36918 +
36919 +/** Release hc after performing LPM transaction */
36920 +void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
36921 +{
36922 +       dwc_hc_t *hc;
36923 +       glpmcfg_data_t lpmcfg;
36924 +       uint8_t hc_num;
36925 +
36926 +       lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36927 +       hc_num = lpmcfg.b.lpm_chan_index;
36928 +
36929 +       hc = hcd->hc_ptr_array[hc_num];
36930 +
36931 +       DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
36932 +       /* Return host channel to free list */
36933 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
36934 +}
36935 +
36936 +int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
36937 +                        uint8_t bRemoteWake)
36938 +{
36939 +       glpmcfg_data_t lpmcfg;
36940 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
36941 +       int channel;
36942 +
36943 +       channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
36944 +       if (channel < 0) {
36945 +               return channel;
36946 +       }
36947 +
36948 +       pcgcctl.b.enbl_sleep_gating = 1;
36949 +       DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
36950 +
36951 +       /* Read LPM config register */
36952 +       lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36953 +
36954 +       /* Program LPM transaction fields */
36955 +       lpmcfg.b.rem_wkup_en = bRemoteWake;
36956 +       lpmcfg.b.hird = hird;
36957 +       lpmcfg.b.hird_thres = 0x1c;
36958 +       lpmcfg.b.lpm_chan_index = channel;
36959 +       lpmcfg.b.en_utmi_sleep = 1;
36960 +       /* Program LPM config register */
36961 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36962 +
36963 +       /* Send LPM transaction */
36964 +       lpmcfg.b.send_lpm = 1;
36965 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36966 +
36967 +       return 0;
36968 +}
36969 +
36970 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36971 +
36972 +int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
36973 +{
36974 +       int retval;
36975 +
36976 +       if (port != 1) {
36977 +               return -DWC_E_INVALID;
36978 +       }
36979 +
36980 +       retval = (hcd->flags.b.port_connect_status_change ||
36981 +                 hcd->flags.b.port_reset_change ||
36982 +                 hcd->flags.b.port_enable_change ||
36983 +                 hcd->flags.b.port_suspend_change ||
36984 +                 hcd->flags.b.port_over_current_change);
36985 +#ifdef DEBUG
36986 +       if (retval) {
36987 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
36988 +                           " Root port status changed\n");
36989 +               DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",
36990 +                           hcd->flags.b.port_connect_status_change);
36991 +               DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",
36992 +                           hcd->flags.b.port_reset_change);
36993 +               DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",
36994 +                           hcd->flags.b.port_enable_change);
36995 +               DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",
36996 +                           hcd->flags.b.port_suspend_change);
36997 +               DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",
36998 +                           hcd->flags.b.port_over_current_change);
36999 +       }
37000 +#endif
37001 +       return retval;
37002 +}
37003 +
37004 +int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
37005 +{
37006 +       hfnum_data_t hfnum;
37007 +       hfnum.d32 =
37008 +           DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->
37009 +                          hfnum);
37010 +
37011 +#ifdef DEBUG_SOF
37012 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
37013 +                   hfnum.b.frnum);
37014 +#endif
37015 +       return hfnum.b.frnum;
37016 +}
37017 +
37018 +int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
37019 +                     struct dwc_otg_hcd_function_ops *fops)
37020 +{
37021 +       int retval = 0;
37022 +
37023 +       hcd->fops = fops;
37024 +       if (!dwc_otg_is_device_mode(hcd->core_if) && 
37025 +               (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
37026 +               dwc_otg_hcd_reinit(hcd);
37027 +       } else {
37028 +               retval = -DWC_E_NO_DEVICE;
37029 +       }
37030 +
37031 +       return retval;
37032 +}
37033 +
37034 +void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
37035 +{
37036 +       return hcd->priv;
37037 +}
37038 +
37039 +void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
37040 +{
37041 +       hcd->priv = priv_data;
37042 +}
37043 +
37044 +uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
37045 +{
37046 +       return hcd->otg_port;
37047 +}
37048 +
37049 +uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
37050 +{
37051 +       uint32_t is_b_host;
37052 +       if (hcd->core_if->op_state == B_HOST) {
37053 +               is_b_host = 1;
37054 +       } else {
37055 +               is_b_host = 0;
37056 +       }
37057 +
37058 +       return is_b_host;
37059 +}
37060 +
37061 +dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
37062 +                                        int iso_desc_count, int atomic_alloc)
37063 +{
37064 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
37065 +       uint32_t size;
37066 +
37067 +       size =
37068 +           sizeof(*dwc_otg_urb) +
37069 +           iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
37070 +       if (atomic_alloc)
37071 +               dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
37072 +       else
37073 +               dwc_otg_urb = DWC_ALLOC(size);
37074 +
37075 +        if (NULL != dwc_otg_urb)
37076 +                dwc_otg_urb->packet_count = iso_desc_count;
37077 +        else {
37078 +                dwc_otg_urb->packet_count = 0;
37079 +                if (size != 0) {
37080 +                        DWC_ERROR("**** DWC OTG HCD URB alloc - "
37081 +                                  "%salloc of %db failed\n",
37082 +                                  atomic_alloc?"atomic ":"", size);
37083 +                }
37084 +        }
37085 +
37086 +       return dwc_otg_urb;
37087 +}
37088 +
37089 +void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
37090 +                                 uint8_t dev_addr, uint8_t ep_num,
37091 +                                 uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
37092 +{
37093 +       dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
37094 +                             ep_type, ep_dir, mps);
37095 +#if 0
37096 +       DWC_PRINTF
37097 +           ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
37098 +            dev_addr, ep_num, ep_dir, ep_type, mps);
37099 +#endif
37100 +}
37101 +
37102 +void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
37103 +                               void *urb_handle, void *buf, dwc_dma_t dma,
37104 +                               uint32_t buflen, void *setup_packet,
37105 +                               dwc_dma_t setup_dma, uint32_t flags,
37106 +                               uint16_t interval)
37107 +{
37108 +       dwc_otg_urb->priv = urb_handle;
37109 +       dwc_otg_urb->buf = buf;
37110 +       dwc_otg_urb->dma = dma;
37111 +       dwc_otg_urb->length = buflen;
37112 +       dwc_otg_urb->setup_packet = setup_packet;
37113 +       dwc_otg_urb->setup_dma = setup_dma;
37114 +       dwc_otg_urb->flags = flags;
37115 +       dwc_otg_urb->interval = interval;
37116 +       dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
37117 +}
37118 +
37119 +uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
37120 +{
37121 +       return dwc_otg_urb->status;
37122 +}
37123 +
37124 +uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
37125 +{
37126 +       return dwc_otg_urb->actual_length;
37127 +}
37128 +
37129 +uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
37130 +{
37131 +       return dwc_otg_urb->error_count;
37132 +}
37133 +
37134 +void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
37135 +                                        int desc_num, uint32_t offset,
37136 +                                        uint32_t length)
37137 +{
37138 +       dwc_otg_urb->iso_descs[desc_num].offset = offset;
37139 +       dwc_otg_urb->iso_descs[desc_num].length = length;
37140 +}
37141 +
37142 +uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
37143 +                                            int desc_num)
37144 +{
37145 +       return dwc_otg_urb->iso_descs[desc_num].status;
37146 +}
37147 +
37148 +uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
37149 +                                                   dwc_otg_urb, int desc_num)
37150 +{
37151 +       return dwc_otg_urb->iso_descs[desc_num].actual_length;
37152 +}
37153 +
37154 +int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
37155 +{
37156 +       int allocated = 0;
37157 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37158 +
37159 +       if (qh) {
37160 +               if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
37161 +                       allocated = 1;
37162 +               }
37163 +       }
37164 +       return allocated;
37165 +}
37166 +
37167 +int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
37168 +{
37169 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37170 +       int freed = 0;
37171 +       DWC_ASSERT(qh, "qh is not allocated\n");
37172 +
37173 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
37174 +               freed = 1;
37175 +       }
37176 +
37177 +       return freed;
37178 +}
37179 +
37180 +uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
37181 +{
37182 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37183 +       DWC_ASSERT(qh, "qh is not allocated\n");
37184 +       return qh->usecs;
37185 +}
37186 +
37187 +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
37188 +{
37189 +#ifdef DEBUG
37190 +       int num_channels;
37191 +       int i;
37192 +       gnptxsts_data_t np_tx_status;
37193 +       hptxsts_data_t p_tx_status;
37194 +
37195 +       num_channels = hcd->core_if->core_params->host_channels;
37196 +       DWC_PRINTF("\n");
37197 +       DWC_PRINTF
37198 +           ("************************************************************\n");
37199 +       DWC_PRINTF("HCD State:\n");
37200 +       DWC_PRINTF("  Num channels: %d\n", num_channels);
37201 +       for (i = 0; i < num_channels; i++) {
37202 +               dwc_hc_t *hc = hcd->hc_ptr_array[i];
37203 +               DWC_PRINTF("  Channel %d:\n", i);
37204 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
37205 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
37206 +               DWC_PRINTF("    speed: %d\n", hc->speed);
37207 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
37208 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
37209 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
37210 +               DWC_PRINTF("    multi_count: %d\n", hc->multi_count);
37211 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
37212 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
37213 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
37214 +               DWC_PRINTF("    xfer_count: %d\n", hc->xfer_count);
37215 +               DWC_PRINTF("    halt_on_queue: %d\n", hc->halt_on_queue);
37216 +               DWC_PRINTF("    halt_pending: %d\n", hc->halt_pending);
37217 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
37218 +               DWC_PRINTF("    do_split: %d\n", hc->do_split);
37219 +               DWC_PRINTF("    complete_split: %d\n", hc->complete_split);
37220 +               DWC_PRINTF("    hub_addr: %d\n", hc->hub_addr);
37221 +               DWC_PRINTF("    port_addr: %d\n", hc->port_addr);
37222 +               DWC_PRINTF("    xact_pos: %d\n", hc->xact_pos);
37223 +               DWC_PRINTF("    requests: %d\n", hc->requests);
37224 +               DWC_PRINTF("    qh: %p\n", hc->qh);
37225 +               if (hc->xfer_started) {
37226 +                       hfnum_data_t hfnum;
37227 +                       hcchar_data_t hcchar;
37228 +                       hctsiz_data_t hctsiz;
37229 +                       hcint_data_t hcint;
37230 +                       hcintmsk_data_t hcintmsk;
37231 +                       hfnum.d32 =
37232 +                           DWC_READ_REG32(&hcd->core_if->
37233 +                                          host_if->host_global_regs->hfnum);
37234 +                       hcchar.d32 =
37235 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37236 +                                          hc_regs[i]->hcchar);
37237 +                       hctsiz.d32 =
37238 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37239 +                                          hc_regs[i]->hctsiz);
37240 +                       hcint.d32 =
37241 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37242 +                                          hc_regs[i]->hcint);
37243 +                       hcintmsk.d32 =
37244 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37245 +                                          hc_regs[i]->hcintmsk);
37246 +                       DWC_PRINTF("    hfnum: 0x%08x\n", hfnum.d32);
37247 +                       DWC_PRINTF("    hcchar: 0x%08x\n", hcchar.d32);
37248 +                       DWC_PRINTF("    hctsiz: 0x%08x\n", hctsiz.d32);
37249 +                       DWC_PRINTF("    hcint: 0x%08x\n", hcint.d32);
37250 +                       DWC_PRINTF("    hcintmsk: 0x%08x\n", hcintmsk.d32);
37251 +               }
37252 +               if (hc->xfer_started && hc->qh) {
37253 +                       dwc_otg_qtd_t *qtd;
37254 +                       dwc_otg_hcd_urb_t *urb;
37255 +                       
37256 +                       DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
37257 +                               if (!qtd->in_process)
37258 +                                       break;
37259 +                               
37260 +                               urb = qtd->urb;
37261 +                       DWC_PRINTF("    URB Info:\n");
37262 +                       DWC_PRINTF("      qtd: %p, urb: %p\n", qtd, urb);
37263 +                       if (urb) {
37264 +                               DWC_PRINTF("      Dev: %d, EP: %d %s\n",
37265 +                                          dwc_otg_hcd_get_dev_addr(&urb->
37266 +                                                                   pipe_info),
37267 +                                          dwc_otg_hcd_get_ep_num(&urb->
37268 +                                                                 pipe_info),
37269 +                                          dwc_otg_hcd_is_pipe_in(&urb->
37270 +                                                                 pipe_info) ?
37271 +                                          "IN" : "OUT");
37272 +                               DWC_PRINTF("      Max packet size: %d\n",
37273 +                                          dwc_otg_hcd_get_mps(&urb->
37274 +                                                              pipe_info));
37275 +                               DWC_PRINTF("      transfer_buffer: %p\n",
37276 +                                          urb->buf);
37277 +                               DWC_PRINTF("      transfer_dma: %p\n",
37278 +                                          (void *)urb->dma);
37279 +                               DWC_PRINTF("      transfer_buffer_length: %d\n",
37280 +                                          urb->length);
37281 +                                       DWC_PRINTF("      actual_length: %d\n",
37282 +                                                  urb->actual_length);
37283 +                               }
37284 +                       }
37285 +               }
37286 +       }
37287 +       DWC_PRINTF("  non_periodic_channels: %d\n", hcd->non_periodic_channels);
37288 +       DWC_PRINTF("  periodic_channels: %d\n", hcd->periodic_channels);
37289 +       DWC_PRINTF("  periodic_usecs: %d\n", hcd->periodic_usecs);
37290 +       np_tx_status.d32 =
37291 +           DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
37292 +       DWC_PRINTF("  NP Tx Req Queue Space Avail: %d\n",
37293 +                  np_tx_status.b.nptxqspcavail);
37294 +       DWC_PRINTF("  NP Tx FIFO Space Avail: %d\n",
37295 +                  np_tx_status.b.nptxfspcavail);
37296 +       p_tx_status.d32 =
37297 +           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
37298 +       DWC_PRINTF("  P Tx Req Queue Space Avail: %d\n",
37299 +                  p_tx_status.b.ptxqspcavail);
37300 +       DWC_PRINTF("  P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
37301 +       dwc_otg_hcd_dump_frrem(hcd);
37302 +       dwc_otg_dump_global_registers(hcd->core_if);
37303 +       dwc_otg_dump_host_registers(hcd->core_if);
37304 +       DWC_PRINTF
37305 +           ("************************************************************\n");
37306 +       DWC_PRINTF("\n");
37307 +#endif
37308 +}
37309 +
37310 +#ifdef DEBUG
37311 +void dwc_print_setup_data(uint8_t * setup)
37312 +{
37313 +       int i;
37314 +       if (CHK_DEBUG_LEVEL(DBG_HCD)) {
37315 +               DWC_PRINTF("Setup Data = MSB ");
37316 +               for (i = 7; i >= 0; i--)
37317 +                       DWC_PRINTF("%02x ", setup[i]);
37318 +               DWC_PRINTF("\n");
37319 +               DWC_PRINTF("  bmRequestType Tranfer = %s\n",
37320 +                          (setup[0] & 0x80) ? "Device-to-Host" :
37321 +                          "Host-to-Device");
37322 +               DWC_PRINTF("  bmRequestType Type = ");
37323 +               switch ((setup[0] & 0x60) >> 5) {
37324 +               case 0:
37325 +                       DWC_PRINTF("Standard\n");
37326 +                       break;
37327 +               case 1:
37328 +                       DWC_PRINTF("Class\n");
37329 +                       break;
37330 +               case 2:
37331 +                       DWC_PRINTF("Vendor\n");
37332 +                       break;
37333 +               case 3:
37334 +                       DWC_PRINTF("Reserved\n");
37335 +                       break;
37336 +               }
37337 +               DWC_PRINTF("  bmRequestType Recipient = ");
37338 +               switch (setup[0] & 0x1f) {
37339 +               case 0:
37340 +                       DWC_PRINTF("Device\n");
37341 +                       break;
37342 +               case 1:
37343 +                       DWC_PRINTF("Interface\n");
37344 +                       break;
37345 +               case 2:
37346 +                       DWC_PRINTF("Endpoint\n");
37347 +                       break;
37348 +               case 3:
37349 +                       DWC_PRINTF("Other\n");
37350 +                       break;
37351 +               default:
37352 +                       DWC_PRINTF("Reserved\n");
37353 +                       break;
37354 +               }
37355 +               DWC_PRINTF("  bRequest = 0x%0x\n", setup[1]);
37356 +               DWC_PRINTF("  wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
37357 +               DWC_PRINTF("  wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
37358 +               DWC_PRINTF("  wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
37359 +       }
37360 +}
37361 +#endif
37362 +
37363 +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
37364 +{
37365 +#if 0
37366 +       DWC_PRINTF("Frame remaining at SOF:\n");
37367 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37368 +                  hcd->frrem_samples, hcd->frrem_accum,
37369 +                  (hcd->frrem_samples > 0) ?
37370 +                  hcd->frrem_accum / hcd->frrem_samples : 0);
37371 +
37372 +       DWC_PRINTF("\n");
37373 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
37374 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37375 +                  hcd->core_if->hfnum_7_samples,
37376 +                  hcd->core_if->hfnum_7_frrem_accum,
37377 +                  (hcd->core_if->hfnum_7_samples >
37378 +                   0) ? hcd->core_if->hfnum_7_frrem_accum /
37379 +                  hcd->core_if->hfnum_7_samples : 0);
37380 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
37381 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37382 +                  hcd->core_if->hfnum_0_samples,
37383 +                  hcd->core_if->hfnum_0_frrem_accum,
37384 +                  (hcd->core_if->hfnum_0_samples >
37385 +                   0) ? hcd->core_if->hfnum_0_frrem_accum /
37386 +                  hcd->core_if->hfnum_0_samples : 0);
37387 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
37388 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37389 +                  hcd->core_if->hfnum_other_samples,
37390 +                  hcd->core_if->hfnum_other_frrem_accum,
37391 +                  (hcd->core_if->hfnum_other_samples >
37392 +                   0) ? hcd->core_if->hfnum_other_frrem_accum /
37393 +                  hcd->core_if->hfnum_other_samples : 0);
37394 +
37395 +       DWC_PRINTF("\n");
37396 +       DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
37397 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37398 +                  hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
37399 +                  (hcd->hfnum_7_samples_a > 0) ?
37400 +                  hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
37401 +       DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
37402 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37403 +                  hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
37404 +                  (hcd->hfnum_0_samples_a > 0) ?
37405 +                  hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
37406 +       DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
37407 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37408 +                  hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
37409 +                  (hcd->hfnum_other_samples_a > 0) ?
37410 +                  hcd->hfnum_other_frrem_accum_a /
37411 +                  hcd->hfnum_other_samples_a : 0);
37412 +
37413 +       DWC_PRINTF("\n");
37414 +       DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
37415 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37416 +                  hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
37417 +                  (hcd->hfnum_7_samples_b > 0) ?
37418 +                  hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
37419 +       DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
37420 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37421 +                  hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
37422 +                  (hcd->hfnum_0_samples_b > 0) ?
37423 +                  hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
37424 +       DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
37425 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37426 +                  hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
37427 +                  (hcd->hfnum_other_samples_b > 0) ?
37428 +                  hcd->hfnum_other_frrem_accum_b /
37429 +                  hcd->hfnum_other_samples_b : 0);
37430 +#endif
37431 +}
37432 +
37433 +#endif /* DWC_DEVICE_ONLY */
37434 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
37435 new file mode 100644
37436 index 0000000..8075595
37437 --- /dev/null
37438 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
37439 @@ -0,0 +1,824 @@
37440 +/* ==========================================================================
37441 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
37442 + * $Revision: #58 $
37443 + * $Date: 2011/09/15 $
37444 + * $Change: 1846647 $
37445 + *
37446 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
37447 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
37448 + * otherwise expressly agreed to in writing between Synopsys and you.
37449 + *
37450 + * The Software IS NOT an item of Licensed Software or Licensed Product under
37451 + * any End User Software License Agreement or Agreement for Licensed Product
37452 + * with Synopsys or any supplement thereto. You are permitted to use and
37453 + * redistribute this Software in source and binary forms, with or without
37454 + * modification, provided that redistributions of source code must retain this
37455 + * notice. You may not view, use, disclose, copy or distribute this file or
37456 + * any information contained herein except pursuant to this license grant from
37457 + * Synopsys. If you do not agree with this notice, including the disclaimer
37458 + * below, then you are not authorized to use the Software.
37459 + *
37460 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
37461 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37462 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37463 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
37464 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37465 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37466 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37467 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37468 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37469 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
37470 + * DAMAGE.
37471 + * ========================================================================== */
37472 +#ifndef DWC_DEVICE_ONLY
37473 +#ifndef __DWC_HCD_H__
37474 +#define __DWC_HCD_H__
37475 +
37476 +#include "dwc_otg_os_dep.h"
37477 +#include "usb.h"
37478 +#include "dwc_otg_hcd_if.h"
37479 +#include "dwc_otg_core_if.h"
37480 +#include "dwc_list.h"
37481 +#include "dwc_otg_cil.h"
37482 +
37483 +/**
37484 + * @file
37485 + *
37486 + * This file contains the structures, constants, and interfaces for
37487 + * the Host Contoller Driver (HCD).
37488 + *
37489 + * The Host Controller Driver (HCD) is responsible for translating requests
37490 + * from the USB Driver into the appropriate actions on the DWC_otg controller.
37491 + * It isolates the USBD from the specifics of the controller by providing an
37492 + * API to the USBD.
37493 + */
37494 +
37495 +struct dwc_otg_hcd_pipe_info {
37496 +       uint8_t dev_addr;
37497 +       uint8_t ep_num;
37498 +       uint8_t pipe_type;
37499 +       uint8_t pipe_dir;
37500 +       uint16_t mps;
37501 +};
37502 +
37503 +struct dwc_otg_hcd_iso_packet_desc {
37504 +       uint32_t offset;
37505 +       uint32_t length;
37506 +       uint32_t actual_length;
37507 +       uint32_t status;
37508 +};
37509 +
37510 +struct dwc_otg_qtd;
37511 +
37512 +struct dwc_otg_hcd_urb {
37513 +       void *priv;
37514 +       struct dwc_otg_qtd *qtd;
37515 +       void *buf;
37516 +       dwc_dma_t dma;
37517 +       void *setup_packet;
37518 +       dwc_dma_t setup_dma;
37519 +       uint32_t length;
37520 +       uint32_t actual_length;
37521 +       uint32_t status;
37522 +       uint32_t error_count;
37523 +       uint32_t packet_count;
37524 +       uint32_t flags;
37525 +       uint16_t interval;
37526 +       struct dwc_otg_hcd_pipe_info pipe_info;
37527 +       struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
37528 +};
37529 +
37530 +static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
37531 +{
37532 +       return pipe->ep_num;
37533 +}
37534 +
37535 +static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
37536 +                                               *pipe)
37537 +{
37538 +       return pipe->pipe_type;
37539 +}
37540 +
37541 +static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
37542 +{
37543 +       return pipe->mps;
37544 +}
37545 +
37546 +static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
37547 +                                              *pipe)
37548 +{
37549 +       return pipe->dev_addr;
37550 +}
37551 +
37552 +static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
37553 +                                              *pipe)
37554 +{
37555 +       return (pipe->pipe_type == UE_ISOCHRONOUS);
37556 +}
37557 +
37558 +static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
37559 +                                             *pipe)
37560 +{
37561 +       return (pipe->pipe_type == UE_INTERRUPT);
37562 +}
37563 +
37564 +static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
37565 +                                              *pipe)
37566 +{
37567 +       return (pipe->pipe_type == UE_BULK);
37568 +}
37569 +
37570 +static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
37571 +                                                 *pipe)
37572 +{
37573 +       return (pipe->pipe_type == UE_CONTROL);
37574 +}
37575 +
37576 +static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
37577 +{
37578 +       return (pipe->pipe_dir == UE_DIR_IN);
37579 +}
37580 +
37581 +static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
37582 +                                             *pipe)
37583 +{
37584 +       return (!dwc_otg_hcd_is_pipe_in(pipe));
37585 +}
37586 +
37587 +static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
37588 +                                        uint8_t devaddr, uint8_t ep_num,
37589 +                                        uint8_t pipe_type, uint8_t pipe_dir,
37590 +                                        uint16_t mps)
37591 +{
37592 +       pipe->dev_addr = devaddr;
37593 +       pipe->ep_num = ep_num;
37594 +       pipe->pipe_type = pipe_type;
37595 +       pipe->pipe_dir = pipe_dir;
37596 +       pipe->mps = mps;
37597 +}
37598 +
37599 +/**
37600 + * Phases for control transfers.
37601 + */
37602 +typedef enum dwc_otg_control_phase {
37603 +       DWC_OTG_CONTROL_SETUP,
37604 +       DWC_OTG_CONTROL_DATA,
37605 +       DWC_OTG_CONTROL_STATUS
37606 +} dwc_otg_control_phase_e;
37607 +
37608 +/** Transaction types. */
37609 +typedef enum dwc_otg_transaction_type {
37610 +       DWC_OTG_TRANSACTION_NONE,
37611 +       DWC_OTG_TRANSACTION_PERIODIC,
37612 +       DWC_OTG_TRANSACTION_NON_PERIODIC,
37613 +       DWC_OTG_TRANSACTION_ALL
37614 +} dwc_otg_transaction_type_e;
37615 +
37616 +struct dwc_otg_qh;
37617 +
37618 +/**
37619 + * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
37620 + * interrupt, or isochronous transfer. A single QTD is created for each URB
37621 + * (of one of these types) submitted to the HCD. The transfer associated with
37622 + * a QTD may require one or multiple transactions.
37623 + *
37624 + * A QTD is linked to a Queue Head, which is entered in either the
37625 + * non-periodic or periodic schedule for execution. When a QTD is chosen for
37626 + * execution, some or all of its transactions may be executed. After
37627 + * execution, the state of the QTD is updated. The QTD may be retired if all
37628 + * its transactions are complete or if an error occurred. Otherwise, it
37629 + * remains in the schedule so more transactions can be executed later.
37630 + */
37631 +typedef struct dwc_otg_qtd {
37632 +       /**
37633 +        * Determines the PID of the next data packet for the data phase of
37634 +        * control transfers. Ignored for other transfer types.<br>
37635 +        * One of the following values:
37636 +        *      - DWC_OTG_HC_PID_DATA0
37637 +        *      - DWC_OTG_HC_PID_DATA1
37638 +        */
37639 +       uint8_t data_toggle;
37640 +
37641 +       /** Current phase for control transfers (Setup, Data, or Status). */
37642 +       dwc_otg_control_phase_e control_phase;
37643 +
37644 +       /** Keep track of the current split type
37645 +        * for FS/LS endpoints on a HS Hub */
37646 +       uint8_t complete_split;
37647 +
37648 +       /** How many bytes transferred during SSPLIT OUT */
37649 +       uint32_t ssplit_out_xfer_count;
37650 +
37651 +       /**
37652 +        * Holds the number of bus errors that have occurred for a transaction
37653 +        * within this transfer.
37654 +        */
37655 +       uint8_t error_count;
37656 +
37657 +       /**
37658 +        * Index of the next frame descriptor for an isochronous transfer. A
37659 +        * frame descriptor describes the buffer position and length of the
37660 +        * data to be transferred in the next scheduled (micro)frame of an
37661 +        * isochronous transfer. It also holds status for that transaction.
37662 +        * The frame index starts at 0.
37663 +        */
37664 +       uint16_t isoc_frame_index;
37665 +
37666 +       /** Position of the ISOC split on full/low speed */
37667 +       uint8_t isoc_split_pos;
37668 +
37669 +       /** Position of the ISOC split in the buffer for the current frame */
37670 +       uint16_t isoc_split_offset;
37671 +
37672 +       /** URB for this transfer */
37673 +       struct dwc_otg_hcd_urb *urb;
37674 +
37675 +       struct dwc_otg_qh *qh;
37676 +
37677 +       /** This list of QTDs */
37678 +        DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
37679 +
37680 +       /** Indicates if this QTD is currently processed by HW. */
37681 +       uint8_t in_process;
37682 +
37683 +       /** Number of DMA descriptors for this QTD */
37684 +       uint8_t n_desc;
37685 +
37686 +       /** 
37687 +        * Last activated frame(packet) index. 
37688 +        * Used in Descriptor DMA mode only.
37689 +        */
37690 +       uint16_t isoc_frame_index_last;
37691 +
37692 +} dwc_otg_qtd_t;
37693 +
37694 +DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
37695 +
37696 +/**
37697 + * A Queue Head (QH) holds the static characteristics of an endpoint and
37698 + * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
37699 + * be entered in either the non-periodic or periodic schedule.
37700 + */
37701 +typedef struct dwc_otg_qh {
37702 +       /**
37703 +        * Endpoint type.
37704 +        * One of the following values:
37705 +        *      - UE_CONTROL
37706 +        *      - UE_BULK
37707 +        *      - UE_INTERRUPT
37708 +        *      - UE_ISOCHRONOUS
37709 +        */
37710 +       uint8_t ep_type;
37711 +       uint8_t ep_is_in;
37712 +
37713 +       /** wMaxPacketSize Field of Endpoint Descriptor. */
37714 +       uint16_t maxp;
37715 +
37716 +       /**
37717 +        * Device speed.
37718 +        * One of the following values:
37719 +        *      - DWC_OTG_EP_SPEED_LOW
37720 +        *      - DWC_OTG_EP_SPEED_FULL
37721 +        *      - DWC_OTG_EP_SPEED_HIGH
37722 +        */
37723 +       uint8_t dev_speed;
37724 +
37725 +       /**
37726 +        * Determines the PID of the next data packet for non-control
37727 +        * transfers. Ignored for control transfers.<br>
37728 +        * One of the following values:
37729 +        *      - DWC_OTG_HC_PID_DATA0
37730 +        *      - DWC_OTG_HC_PID_DATA1
37731 +        */
37732 +       uint8_t data_toggle;
37733 +
37734 +       /** Ping state if 1. */
37735 +       uint8_t ping_state;
37736 +
37737 +       /**
37738 +        * List of QTDs for this QH.
37739 +        */
37740 +       struct dwc_otg_qtd_list qtd_list;
37741 +
37742 +       /** Host channel currently processing transfers for this QH. */
37743 +       struct dwc_hc *channel;
37744 +
37745 +       /** Full/low speed endpoint on high-speed hub requires split. */
37746 +       uint8_t do_split;
37747 +
37748 +       /** @name Periodic schedule information */
37749 +       /** @{ */
37750 +
37751 +       /** Bandwidth in microseconds per (micro)frame. */
37752 +       uint16_t usecs;
37753 +
37754 +       /** Interval between transfers in (micro)frames. */
37755 +       uint16_t interval;
37756 +
37757 +       /**
37758 +        * (micro)frame to initialize a periodic transfer. The transfer
37759 +        * executes in the following (micro)frame.
37760 +        */
37761 +       uint16_t sched_frame;
37762 +
37763 +       /** (micro)frame at which last start split was initialized. */
37764 +       uint16_t start_split_frame;
37765 +
37766 +       /** @} */
37767 +
37768 +       /** 
37769 +        * Used instead of original buffer if 
37770 +        * it(physical address) is not dword-aligned.
37771 +        */
37772 +       uint8_t *dw_align_buf;
37773 +       dwc_dma_t dw_align_buf_dma;
37774 +
37775 +       /** Entry for QH in either the periodic or non-periodic schedule. */
37776 +       dwc_list_link_t qh_list_entry;
37777 +
37778 +       /** @name Descriptor DMA support */
37779 +       /** @{ */
37780 +
37781 +       /** Descriptor List. */
37782 +       dwc_otg_host_dma_desc_t *desc_list;
37783 +
37784 +       /** Descriptor List physical address. */
37785 +       dwc_dma_t desc_list_dma;
37786 +
37787 +       /** 
37788 +        * Xfer Bytes array.
37789 +        * Each element corresponds to a descriptor and indicates 
37790 +        * original XferSize size value for the descriptor.
37791 +        */
37792 +       uint32_t *n_bytes;
37793 +
37794 +       /** Actual number of transfer descriptors in a list. */
37795 +       uint16_t ntd;
37796 +
37797 +       /** First activated isochronous transfer descriptor index. */
37798 +       uint8_t td_first;
37799 +       /** Last activated isochronous transfer descriptor index. */
37800 +       uint8_t td_last;
37801 +
37802 +       /** @} */
37803 +
37804 +
37805 +       uint16_t speed;
37806 +       uint16_t frame_usecs[8];
37807 +} dwc_otg_qh_t;
37808 +
37809 +DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
37810 +
37811 +/**
37812 + * This structure holds the state of the HCD, including the non-periodic and
37813 + * periodic schedules.
37814 + */
37815 +struct dwc_otg_hcd {
37816 +       /** The DWC otg device pointer */
37817 +       struct dwc_otg_device *otg_dev;
37818 +       /** DWC OTG Core Interface Layer */
37819 +       dwc_otg_core_if_t *core_if;
37820 +
37821 +       /** Function HCD driver callbacks */
37822 +       struct dwc_otg_hcd_function_ops *fops;
37823 +
37824 +       /** Internal DWC HCD Flags */
37825 +       volatile union dwc_otg_hcd_internal_flags {
37826 +               uint32_t d32;
37827 +               struct {
37828 +                       unsigned port_connect_status_change:1;
37829 +                       unsigned port_connect_status:1;
37830 +                       unsigned port_reset_change:1;
37831 +                       unsigned port_enable_change:1;
37832 +                       unsigned port_suspend_change:1;
37833 +                       unsigned port_over_current_change:1;
37834 +                       unsigned port_l1_change:1;
37835 +                       unsigned reserved:26;
37836 +               } b;
37837 +       } flags;
37838 +
37839 +       /**
37840 +        * Inactive items in the non-periodic schedule. This is a list of
37841 +        * Queue Heads. Transfers associated with these Queue Heads are not
37842 +        * currently assigned to a host channel.
37843 +        */
37844 +       dwc_list_link_t non_periodic_sched_inactive;
37845 +
37846 +       /**
37847 +        * Active items in the non-periodic schedule. This is a list of
37848 +        * Queue Heads. Transfers associated with these Queue Heads are
37849 +        * currently assigned to a host channel.
37850 +        */
37851 +       dwc_list_link_t non_periodic_sched_active;
37852 +
37853 +       /**
37854 +        * Pointer to the next Queue Head to process in the active
37855 +        * non-periodic schedule.
37856 +        */
37857 +       dwc_list_link_t *non_periodic_qh_ptr;
37858 +
37859 +       /**
37860 +        * Inactive items in the periodic schedule. This is a list of QHs for
37861 +        * periodic transfers that are _not_ scheduled for the next frame.
37862 +        * Each QH in the list has an interval counter that determines when it
37863 +        * needs to be scheduled for execution. This scheduling mechanism
37864 +        * allows only a simple calculation for periodic bandwidth used (i.e.
37865 +        * must assume that all periodic transfers may need to execute in the
37866 +        * same frame). However, it greatly simplifies scheduling and should
37867 +        * be sufficient for the vast majority of OTG hosts, which need to
37868 +        * connect to a small number of peripherals at one time.
37869 +        *
37870 +        * Items move from this list to periodic_sched_ready when the QH
37871 +        * interval counter is 0 at SOF.
37872 +        */
37873 +       dwc_list_link_t periodic_sched_inactive;
37874 +
37875 +       /**
37876 +        * List of periodic QHs that are ready for execution in the next
37877 +        * frame, but have not yet been assigned to host channels.
37878 +        *
37879 +        * Items move from this list to periodic_sched_assigned as host
37880 +        * channels become available during the current frame.
37881 +        */
37882 +       dwc_list_link_t periodic_sched_ready;
37883 +
37884 +       /**
37885 +        * List of periodic QHs to be executed in the next frame that are
37886 +        * assigned to host channels.
37887 +        *
37888 +        * Items move from this list to periodic_sched_queued as the
37889 +        * transactions for the QH are queued to the DWC_otg controller.
37890 +        */
37891 +       dwc_list_link_t periodic_sched_assigned;
37892 +
37893 +       /**
37894 +        * List of periodic QHs that have been queued for execution.
37895 +        *
37896 +        * Items move from this list to either periodic_sched_inactive or
37897 +        * periodic_sched_ready when the channel associated with the transfer
37898 +        * is released. If the interval for the QH is 1, the item moves to
37899 +        * periodic_sched_ready because it must be rescheduled for the next
37900 +        * frame. Otherwise, the item moves to periodic_sched_inactive.
37901 +        */
37902 +       dwc_list_link_t periodic_sched_queued;
37903 +
37904 +       /**
37905 +        * Total bandwidth claimed so far for periodic transfers. This value
37906 +        * is in microseconds per (micro)frame. The assumption is that all
37907 +        * periodic transfers may occur in the same (micro)frame.
37908 +        */
37909 +       uint16_t periodic_usecs;
37910 +
37911 +       /**
37912 +        * Total bandwidth claimed so far for all periodic transfers
37913 +        * in a frame.
37914 +        * This will include a mixture of HS and FS transfers.
37915 +        * Units are microseconds per (micro)frame.
37916 +        * We have a budget per frame and have to schedule
37917 +        * transactions accordingly.
37918 +        * Watch out for the fact that things are actually scheduled for the
37919 +        * "next frame".
37920 +        */
37921 +       uint16_t                frame_usecs[8];
37922 +
37923 +
37924 +       /**
37925 +        * Frame number read from the core at SOF. The value ranges from 0 to
37926 +        * DWC_HFNUM_MAX_FRNUM.
37927 +        */
37928 +       uint16_t frame_number;
37929 +
37930 +       /**
37931 +        * Count of periodic QHs, if using several eps. For SOF enable/disable.
37932 +        */
37933 +       uint16_t periodic_qh_count;
37934 +
37935 +       /**
37936 +        * Free host channels in the controller. This is a list of
37937 +        * dwc_hc_t items.
37938 +        */
37939 +       struct hc_list free_hc_list;
37940 +       /**
37941 +        * Number of host channels assigned to periodic transfers. Currently
37942 +        * assuming that there is a dedicated host channel for each periodic
37943 +        * transaction and at least one host channel available for
37944 +        * non-periodic transactions.
37945 +        */
37946 +       int periodic_channels; /* microframe_schedule==0 */
37947 +
37948 +       /**
37949 +        * Number of host channels assigned to non-periodic transfers.
37950 +        */
37951 +       int non_periodic_channels; /* microframe_schedule==0 */
37952 +
37953 +       /**
37954 +        * Number of host channels assigned to non-periodic transfers.
37955 +        */
37956 +       int available_host_channels;
37957 +
37958 +       /**
37959 +        * Array of pointers to the host channel descriptors. Allows accessing
37960 +        * a host channel descriptor given the host channel number. This is
37961 +        * useful in interrupt handlers.
37962 +        */
37963 +       struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
37964 +
37965 +       /**
37966 +        * Buffer to use for any data received during the status phase of a
37967 +        * control transfer. Normally no data is transferred during the status
37968 +        * phase. This buffer is used as a bit bucket.
37969 +        */
37970 +       uint8_t *status_buf;
37971 +
37972 +       /**
37973 +        * DMA address for status_buf.
37974 +        */
37975 +       dma_addr_t status_buf_dma;
37976 +#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
37977 +
37978 +       /**
37979 +        * Connection timer. An OTG host must display a message if the device
37980 +        * does not connect. Started when the VBus power is turned on via
37981 +        * sysfs attribute "buspower".
37982 +        */
37983 +       dwc_timer_t *conn_timer;
37984 +
37985 +       /* Tasket to do a reset */
37986 +       dwc_tasklet_t *reset_tasklet;
37987 +
37988 +       /*  */
37989 +       dwc_spinlock_t *lock;
37990 +
37991 +       /**
37992 +        * Private data that could be used by OS wrapper.
37993 +        */
37994 +       void *priv;
37995 +
37996 +       uint8_t otg_port;
37997 +
37998 +       /** Frame List */
37999 +       uint32_t *frame_list;
38000 +
38001 +       /** Frame List DMA address */
38002 +       dma_addr_t frame_list_dma;
38003 +
38004 +#ifdef DEBUG
38005 +       uint32_t frrem_samples;
38006 +       uint64_t frrem_accum;
38007 +
38008 +       uint32_t hfnum_7_samples_a;
38009 +       uint64_t hfnum_7_frrem_accum_a;
38010 +       uint32_t hfnum_0_samples_a;
38011 +       uint64_t hfnum_0_frrem_accum_a;
38012 +       uint32_t hfnum_other_samples_a;
38013 +       uint64_t hfnum_other_frrem_accum_a;
38014 +
38015 +       uint32_t hfnum_7_samples_b;
38016 +       uint64_t hfnum_7_frrem_accum_b;
38017 +       uint32_t hfnum_0_samples_b;
38018 +       uint64_t hfnum_0_frrem_accum_b;
38019 +       uint32_t hfnum_other_samples_b;
38020 +       uint64_t hfnum_other_frrem_accum_b;
38021 +#endif
38022 +};
38023 +
38024 +/** @name Transaction Execution Functions */
38025 +/** @{ */
38026 +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
38027 +                                                                 * hcd);
38028 +extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
38029 +                                          dwc_otg_transaction_type_e tr_type);
38030 +
38031 +/** @} */
38032 +
38033 +/** @name Interrupt Handler Functions */
38034 +/** @{ */
38035 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38036 +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38037 +extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
38038 +                                                        dwc_otg_hcd);
38039 +extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
38040 +                                                       dwc_otg_hcd);
38041 +extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
38042 +                                                          dwc_otg_hcd);
38043 +extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
38044 +                                                          dwc_otg_hcd);
38045 +extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38046 +extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
38047 +                                                            dwc_otg_hcd);
38048 +extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38049 +extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38050 +extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
38051 +                                           uint32_t num);
38052 +extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38053 +extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
38054 +                                                      dwc_otg_hcd);
38055 +/** @} */
38056 +
38057 +/** @name Schedule Queue Functions */
38058 +/** @{ */
38059 +
38060 +/* Implemented in dwc_otg_hcd_queue.c */
38061 +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
38062 +                                          dwc_otg_hcd_urb_t * urb, int atomic_alloc);
38063 +extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38064 +extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38065 +extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38066 +extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38067 +                                     int sched_csplit);
38068 +
38069 +/** Remove and free a QH */
38070 +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
38071 +                                                 dwc_otg_qh_t * qh)
38072 +{
38073 +       dwc_irqflags_t flags;
38074 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
38075 +       dwc_otg_hcd_qh_remove(hcd, qh);
38076 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
38077 +       dwc_otg_hcd_qh_free(hcd, qh);
38078 +}
38079 +
38080 +/** Allocates memory for a QH structure.
38081 + * @return Returns the memory allocate or NULL on error. */
38082 +static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
38083 +{
38084 +       if (atomic_alloc)
38085 +               return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
38086 +       else
38087 +               return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
38088 +}
38089 +
38090 +extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
38091 +                                            int atomic_alloc);
38092 +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
38093 +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
38094 +                              dwc_otg_qh_t ** qh, int atomic_alloc);
38095 +
38096 +/** Allocates memory for a QTD structure.
38097 + * @return Returns the memory allocate or NULL on error. */
38098 +static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
38099 +{
38100 +       if (atomic_alloc)
38101 +               return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
38102 +       else
38103 +               return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
38104 +}
38105 +
38106 +/** Frees the memory for a QTD structure.  QTD should already be removed from
38107 + * list.
38108 + * @param qtd QTD to free.*/
38109 +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
38110 +{
38111 +       DWC_FREE(qtd);
38112 +}
38113 +
38114 +/** Removes a QTD from list.
38115 + * @param hcd HCD instance.
38116 + * @param qtd QTD to remove from list.
38117 + * @param qh QTD belongs to.
38118 + */
38119 +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
38120 +                                         dwc_otg_qtd_t * qtd,
38121 +                                         dwc_otg_qh_t * qh)
38122 +{
38123 +       DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
38124 +}
38125 +
38126 +/** Remove and free a QTD 
38127 +  * Need to disable IRQ and hold hcd lock while calling this function out of 
38128 +  * interrupt servicing chain */
38129 +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
38130 +                                                  dwc_otg_qtd_t * qtd,
38131 +                                                  dwc_otg_qh_t * qh)
38132 +{
38133 +       dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
38134 +       dwc_otg_hcd_qtd_free(qtd);
38135 +}
38136 +
38137 +/** @} */
38138 +
38139 +/** @name Descriptor DMA Supporting Functions */
38140 +/** @{ */
38141 +
38142 +extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38143 +extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
38144 +                                          dwc_hc_t * hc,
38145 +                                          dwc_otg_hc_regs_t * hc_regs,
38146 +                                          dwc_otg_halt_status_e halt_status);
38147 +
38148 +extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38149 +extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38150 +
38151 +/** @} */
38152 +
38153 +/** @name Internal Functions */
38154 +/** @{ */
38155 +dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
38156 +/** @} */
38157 +
38158 +#ifdef CONFIG_USB_DWC_OTG_LPM
38159 +extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
38160 +                                          uint8_t devaddr);
38161 +extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
38162 +#endif
38163 +
38164 +/** Gets the QH that contains the list_head */
38165 +#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
38166 +
38167 +/** Gets the QTD that contains the list_head */
38168 +#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
38169 +
38170 +/** Check if QH is non-periodic  */
38171 +#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
38172 +                                    (_qh_ptr_->ep_type == UE_CONTROL))
38173 +
38174 +/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
38175 +#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
38176 +
38177 +/** Packet size for any kind of endpoint descriptor */
38178 +#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
38179 +
38180 +/**
38181 + * Returns true if _frame1 is less than or equal to _frame2. The comparison is
38182 + * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
38183 + * frame number when the max frame number is reached.
38184 + */
38185 +static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
38186 +{
38187 +       return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
38188 +           (DWC_HFNUM_MAX_FRNUM >> 1);
38189 +}
38190 +
38191 +/**
38192 + * Returns true if _frame1 is greater than _frame2. The comparison is done
38193 + * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
38194 + * number when the max frame number is reached.
38195 + */
38196 +static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
38197 +{
38198 +       return (frame1 != frame2) &&
38199 +           (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
38200 +            (DWC_HFNUM_MAX_FRNUM >> 1));
38201 +}
38202 +
38203 +/**
38204 + * Increments _frame by the amount specified by _inc. The addition is done
38205 + * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
38206 + */
38207 +static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
38208 +{
38209 +       return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
38210 +}
38211 +
38212 +static inline uint16_t dwc_full_frame_num(uint16_t frame)
38213 +{
38214 +       return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
38215 +}
38216 +
38217 +static inline uint16_t dwc_micro_frame_num(uint16_t frame)
38218 +{
38219 +       return frame & 0x7;
38220 +}
38221 +
38222 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
38223 +                                 dwc_otg_hc_regs_t * hc_regs,
38224 +                                 dwc_otg_qtd_t * qtd);
38225 +
38226 +#ifdef DEBUG
38227 +/**
38228 + * Macro to sample the remaining PHY clocks left in the current frame. This
38229 + * may be used during debugging to determine the average time it takes to
38230 + * execute sections of code. There are two possible sample points, "a" and
38231 + * "b", so the _letter argument must be one of these values.
38232 + *
38233 + * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
38234 + * example, "cat /sys/devices/lm0/hcd_frrem".
38235 + */
38236 +#define dwc_sample_frrem(_hcd, _qh, _letter) \
38237 +{ \
38238 +       hfnum_data_t hfnum; \
38239 +       dwc_otg_qtd_t *qtd; \
38240 +       qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
38241 +       if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
38242 +               hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
38243 +               switch (hfnum.b.frnum & 0x7) { \
38244 +               case 7: \
38245 +                       _hcd->hfnum_7_samples_##_letter++; \
38246 +                       _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
38247 +                       break; \
38248 +               case 0: \
38249 +                       _hcd->hfnum_0_samples_##_letter++; \
38250 +                       _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
38251 +                       break; \
38252 +               default: \
38253 +                       _hcd->hfnum_other_samples_##_letter++; \
38254 +                       _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
38255 +                       break; \
38256 +               } \
38257 +       } \
38258 +}
38259 +#else
38260 +#define dwc_sample_frrem(_hcd, _qh, _letter)
38261 +#endif
38262 +#endif
38263 +#endif /* DWC_DEVICE_ONLY */
38264 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
38265 new file mode 100644
38266 index 0000000..d0d5fa1
38267 --- /dev/null
38268 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
38269 @@ -0,0 +1,1133 @@
38270 +/*==========================================================================
38271 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
38272 + * $Revision: #10 $
38273 + * $Date: 2011/10/20 $
38274 + * $Change: 1869464 $
38275 + *
38276 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
38277 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
38278 + * otherwise expressly agreed to in writing between Synopsys and you.
38279 + *
38280 + * The Software IS NOT an item of Licensed Software or Licensed Product under
38281 + * any End User Software License Agreement or Agreement for Licensed Product
38282 + * with Synopsys or any supplement thereto. You are permitted to use and
38283 + * redistribute this Software in source and binary forms, with or without
38284 + * modification, provided that redistributions of source code must retain this
38285 + * notice. You may not view, use, disclose, copy or distribute this file or
38286 + * any information contained herein except pursuant to this license grant from
38287 + * Synopsys. If you do not agree with this notice, including the disclaimer
38288 + * below, then you are not authorized to use the Software.
38289 + *
38290 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
38291 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38292 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38293 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
38294 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38295 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
38296 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38297 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38298 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38299 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38300 + * DAMAGE.
38301 + * ========================================================================== */
38302 +#ifndef DWC_DEVICE_ONLY
38303 +
38304 +/** @file
38305 + * This file contains Descriptor DMA support implementation for host mode.
38306 + */
38307 +
38308 +#include "dwc_otg_hcd.h"
38309 +#include "dwc_otg_regs.h"
38310 +
38311 +extern bool microframe_schedule;
38312 +
38313 +static inline uint8_t frame_list_idx(uint16_t frame)
38314 +{
38315 +       return (frame & (MAX_FRLIST_EN_NUM - 1));
38316 +}
38317 +
38318 +static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed)
38319 +{
38320 +       return (idx + inc) &
38321 +           (((speed ==
38322 +              DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
38323 +             MAX_DMA_DESC_NUM_GENERIC) - 1);
38324 +}
38325 +
38326 +static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed)
38327 +{
38328 +       return (idx - inc) &
38329 +           (((speed ==
38330 +              DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
38331 +             MAX_DMA_DESC_NUM_GENERIC) - 1);
38332 +}
38333 +
38334 +static inline uint16_t max_desc_num(dwc_otg_qh_t * qh)
38335 +{
38336 +       return (((qh->ep_type == UE_ISOCHRONOUS)
38337 +                && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH))
38338 +               ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC);
38339 +}
38340 +static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh)
38341 +{
38342 +       return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)
38343 +               ? ((qh->interval + 8 - 1) / 8)
38344 +               : qh->interval);
38345 +}
38346 +
38347 +static int desc_list_alloc(dwc_otg_qh_t * qh)
38348 +{
38349 +       int retval = 0;
38350 +
38351 +       qh->desc_list = (dwc_otg_host_dma_desc_t *)
38352 +           DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh),
38353 +                         &qh->desc_list_dma);
38354 +
38355 +       if (!qh->desc_list) {
38356 +               retval = -DWC_E_NO_MEMORY;
38357 +               DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__);
38358 +               
38359 +       }
38360 +
38361 +       dwc_memset(qh->desc_list, 0x00,
38362 +                  sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
38363 +
38364 +       qh->n_bytes =
38365 +           (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh));
38366 +
38367 +       if (!qh->n_bytes) {
38368 +               retval = -DWC_E_NO_MEMORY;
38369 +               DWC_ERROR
38370 +                   ("%s: Failed to allocate array for descriptors' size actual values\n",
38371 +                    __func__);
38372 +
38373 +       }
38374 +       return retval;
38375 +
38376 +}
38377 +
38378 +static void desc_list_free(dwc_otg_qh_t * qh)
38379 +{
38380 +       if (qh->desc_list) {
38381 +               DWC_DMA_FREE(max_desc_num(qh), qh->desc_list,
38382 +                            qh->desc_list_dma);
38383 +               qh->desc_list = NULL;
38384 +       }
38385 +
38386 +       if (qh->n_bytes) {
38387 +               DWC_FREE(qh->n_bytes);
38388 +               qh->n_bytes = NULL;
38389 +       }
38390 +}
38391 +
38392 +static int frame_list_alloc(dwc_otg_hcd_t * hcd)
38393 +{
38394 +       int retval = 0;
38395 +       if (hcd->frame_list)
38396 +               return 0;
38397 +
38398 +       hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM,
38399 +                                       &hcd->frame_list_dma);
38400 +       if (!hcd->frame_list) {
38401 +               retval = -DWC_E_NO_MEMORY;
38402 +               DWC_ERROR("%s: Frame List allocation failed\n", __func__);
38403 +       }
38404 +
38405 +       dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM);
38406 +
38407 +       return retval;
38408 +}
38409 +
38410 +static void frame_list_free(dwc_otg_hcd_t * hcd)
38411 +{
38412 +       if (!hcd->frame_list)
38413 +               return;
38414 +       
38415 +       DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma);
38416 +       hcd->frame_list = NULL;
38417 +}
38418 +
38419 +static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en)
38420 +{
38421 +
38422 +       hcfg_data_t hcfg;
38423 +
38424 +       hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
38425 +
38426 +       if (hcfg.b.perschedena) {
38427 +               /* already enabled */
38428 +               return;
38429 +       }
38430 +
38431 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr,
38432 +                       hcd->frame_list_dma);
38433 +
38434 +       switch (fr_list_en) {
38435 +       case 64:
38436 +               hcfg.b.frlisten = 3;
38437 +               break;
38438 +       case 32:
38439 +               hcfg.b.frlisten = 2;
38440 +               break;
38441 +       case 16:
38442 +               hcfg.b.frlisten = 1;
38443 +               break;
38444 +       case 8:
38445 +               hcfg.b.frlisten = 0;
38446 +               break;
38447 +       default:
38448 +               break;
38449 +       }
38450 +
38451 +       hcfg.b.perschedena = 1;
38452 +
38453 +       DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n");
38454 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
38455 +
38456 +}
38457 +
38458 +static void per_sched_disable(dwc_otg_hcd_t * hcd)
38459 +{
38460 +       hcfg_data_t hcfg;
38461 +
38462 +       hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
38463 +       
38464 +       if (!hcfg.b.perschedena) {
38465 +               /* already disabled */
38466 +               return;
38467 +       }
38468 +       hcfg.b.perschedena = 0;
38469 +
38470 +       DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n");
38471 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
38472 +}
38473 +
38474 +/* 
38475 + * Activates/Deactivates FrameList entries for the channel 
38476 + * based on endpoint servicing period.
38477 + */
38478 +void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable)
38479 +{
38480 +       uint16_t i, j, inc;
38481 +       dwc_hc_t *hc = NULL;
38482 +
38483 +       if (!qh->channel) {
38484 +               DWC_ERROR("qh->channel = %p", qh->channel);
38485 +               return;
38486 +       }
38487 +
38488 +       if (!hcd) {
38489 +               DWC_ERROR("------hcd = %p", hcd);
38490 +               return;
38491 +       }
38492 +
38493 +       if (!hcd->frame_list) {
38494 +               DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list);
38495 +               return;
38496 +       }
38497 +
38498 +       hc = qh->channel;
38499 +       inc = frame_incr_val(qh);
38500 +       if (qh->ep_type == UE_ISOCHRONOUS)
38501 +               i = frame_list_idx(qh->sched_frame);
38502 +       else
38503 +               i = 0;
38504 +
38505 +       j = i;
38506 +       do {
38507 +               if (enable)
38508 +                       hcd->frame_list[j] |= (1 << hc->hc_num);
38509 +               else
38510 +                       hcd->frame_list[j] &= ~(1 << hc->hc_num);
38511 +               j = (j + inc) & (MAX_FRLIST_EN_NUM - 1);
38512 +       }
38513 +       while (j != i);
38514 +       if (!enable)
38515 +               return;
38516 +       hc->schinfo = 0;
38517 +       if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) {
38518 +               j = 1;
38519 +               /* TODO - check this */
38520 +               inc = (8 + qh->interval - 1) / qh->interval;
38521 +               for (i = 0; i < inc; i++) {
38522 +                       hc->schinfo |= j;
38523 +                       j = j << qh->interval;
38524 +               }
38525 +       } else {
38526 +               hc->schinfo = 0xff;
38527 +       }
38528 +}
38529 +
38530 +#if 1
38531 +void dump_frame_list(dwc_otg_hcd_t * hcd)
38532 +{
38533 +       int i = 0;
38534 +       DWC_PRINTF("--FRAME LIST (hex) --\n");
38535 +       for (i = 0; i < MAX_FRLIST_EN_NUM; i++) {
38536 +               DWC_PRINTF("%x\t", hcd->frame_list[i]);
38537 +               if (!(i % 8) && i)
38538 +                       DWC_PRINTF("\n");
38539 +       }
38540 +       DWC_PRINTF("\n----\n");
38541 +
38542 +}
38543 +#endif
38544 +
38545 +static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38546 +{
38547 +       dwc_irqflags_t flags;
38548 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
38549 +
38550 +       dwc_hc_t *hc = qh->channel;
38551 +       if (dwc_qh_is_non_per(qh)) {
38552 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
38553 +               if (!microframe_schedule)
38554 +                       hcd->non_periodic_channels--;
38555 +               else
38556 +                       hcd->available_host_channels++;
38557 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
38558 +       } else
38559 +               update_frame_list(hcd, qh, 0);
38560 +
38561 +       /* 
38562 +        * The condition is added to prevent double cleanup try in case of device
38563 +        * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb().
38564 +        */
38565 +       if (hc->qh) {
38566 +               dwc_otg_hc_cleanup(hcd->core_if, hc);
38567 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
38568 +               hc->qh = NULL;
38569 +       }
38570 +
38571 +       qh->channel = NULL;
38572 +       qh->ntd = 0;
38573 +
38574 +       if (qh->desc_list) {
38575 +               dwc_memset(qh->desc_list, 0x00,
38576 +                          sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
38577 +       }
38578 +       DWC_SPINLOCK_FREE(channel_lock);
38579 +}
38580 +
38581 +/** 
38582 + * Initializes a QH structure's Descriptor DMA related members.
38583 + * Allocates memory for descriptor list.
38584 + * On first periodic QH, allocates memory for FrameList 
38585 + * and enables periodic scheduling.
38586 + *
38587 + * @param hcd The HCD state structure for the DWC OTG controller.
38588 + * @param qh The QH to init.
38589 + *
38590 + * @return 0 if successful, negative error code otherwise.
38591 + */
38592 +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38593 +{
38594 +       int retval = 0;
38595 +
38596 +       if (qh->do_split) {
38597 +               DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n");
38598 +               return -1;
38599 +       }
38600 +
38601 +       retval = desc_list_alloc(qh);
38602 +
38603 +       if ((retval == 0)
38604 +           && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) {
38605 +               if (!hcd->frame_list) {
38606 +                       retval = frame_list_alloc(hcd);
38607 +                       /* Enable periodic schedule on first periodic QH */
38608 +                       if (retval == 0)
38609 +                               per_sched_enable(hcd, MAX_FRLIST_EN_NUM);
38610 +               }
38611 +       }
38612 +
38613 +       qh->ntd = 0;
38614 +
38615 +       return retval;
38616 +}
38617 +
38618 +/** 
38619 + * Frees descriptor list memory associated with the QH. 
38620 + * If QH is periodic and the last, frees FrameList memory 
38621 + * and disables periodic scheduling. 
38622 + *
38623 + * @param hcd The HCD state structure for the DWC OTG controller.
38624 + * @param qh The QH to init.
38625 + */
38626 +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38627 +{
38628 +       desc_list_free(qh);
38629 +
38630 +       /* 
38631 +        * Channel still assigned due to some reasons. 
38632 +        * Seen on Isoc URB dequeue. Channel halted but no subsequent
38633 +        * ChHalted interrupt to release the channel. Afterwards
38634 +        * when it comes here from endpoint disable routine
38635 +        * channel remains assigned.
38636 +        */
38637 +       if (qh->channel)
38638 +               release_channel_ddma(hcd, qh);
38639 +
38640 +       if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)
38641 +           && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) {
38642 +
38643 +               per_sched_disable(hcd);
38644 +               frame_list_free(hcd);
38645 +       }
38646 +}
38647 +
38648 +static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx)
38649 +{
38650 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
38651 +               /* 
38652 +                * Descriptor set(8 descriptors) index
38653 +                * which is 8-aligned.
38654 +                */
38655 +               return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
38656 +       } else {
38657 +               return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1));
38658 +       }
38659 +}
38660 +
38661 +/* 
38662 + * Determine starting frame for Isochronous transfer. 
38663 + * Few frames skipped to prevent race condition with HC. 
38664 + */
38665 +static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38666 +                                  uint8_t * skip_frames)
38667 +{
38668 +       uint16_t frame = 0;
38669 +       hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd);
38670 +       
38671 +       /* sched_frame is always frame number(not uFrame) both in FS and HS !! */
38672 +       
38673 +       /* 
38674 +        * skip_frames is used to limit activated descriptors number
38675 +        * to avoid the situation when HC services the last activated
38676 +        * descriptor firstly.
38677 +        * Example for FS:
38678 +        * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor
38679 +        * corresponding to curr_frame+1, the descriptor corresponding to frame 2
38680 +        * will be fetched. If the number of descriptors is max=64 (or greather) the
38681 +        * list will be fully programmed with Active descriptors and it is possible
38682 +        * case(rare) that the latest descriptor(considering rollback) corresponding
38683 +        * to frame 2 will be serviced first. HS case is more probable because, in fact,
38684 +        * up to 11 uframes(16 in the code) may be skipped.
38685 +        */
38686 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
38687 +               /* 
38688 +                * Consider uframe counter also, to start xfer asap.
38689 +                * If half of the frame elapsed skip 2 frames otherwise
38690 +                * just 1 frame. 
38691 +                * Starting descriptor index must be 8-aligned, so
38692 +                * if the current frame is near to complete the next one
38693 +                * is skipped as well.
38694 +                */
38695 +
38696 +               if (dwc_micro_frame_num(hcd->frame_number) >= 5) {
38697 +                       *skip_frames = 2 * 8;
38698 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
38699 +               } else {
38700 +                       *skip_frames = 1 * 8;
38701 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
38702 +               }
38703 +
38704 +               frame = dwc_full_frame_num(frame);
38705 +       } else {
38706 +               /* 
38707 +                * Two frames are skipped for FS - the current and the next.
38708 +                * But for descriptor programming, 1 frame(descriptor) is enough,
38709 +                * see example above.
38710 +                */
38711 +               *skip_frames = 1;
38712 +               frame = dwc_frame_num_inc(hcd->frame_number, 2);
38713 +       }
38714 +
38715 +       return frame;
38716 +}
38717 +
38718 +/* 
38719 + * Calculate initial descriptor index for isochronous transfer
38720 + * based on scheduled frame. 
38721 + */
38722 +static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38723 +{
38724 +       uint16_t frame = 0, fr_idx, fr_idx_tmp;
38725 +       uint8_t skip_frames = 0;
38726 +       /* 
38727 +        * With current ISOC processing algorithm the channel is being
38728 +        * released when no more QTDs in the list(qh->ntd == 0).
38729 +        * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. 
38730 +        *
38731 +        * So qh->channel != NULL branch is not used and just not removed from the
38732 +        * source file. It is required for another possible approach which is,
38733 +        * do not disable and release the channel when ISOC session completed, 
38734 +        * just move QH to inactive schedule until new QTD arrives. 
38735 +        * On new QTD, the QH moved back to 'ready' schedule,
38736 +        * starting frame and therefore starting desc_index are recalculated.
38737 +        * In this case channel is released only on ep_disable.
38738 +        */
38739 +
38740 +       /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */
38741 +       if (qh->channel) {
38742 +               frame = calc_starting_frame(hcd, qh, &skip_frames);
38743 +               /* 
38744 +                * Calculate initial descriptor index based on FrameList current bitmap
38745 +                * and servicing period.
38746 +                */
38747 +               fr_idx_tmp = frame_list_idx(frame);
38748 +               fr_idx =
38749 +                   (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) -
38750 +                    fr_idx_tmp)
38751 +                   % frame_incr_val(qh);
38752 +               fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM;
38753 +       } else {
38754 +               qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames);
38755 +               fr_idx = frame_list_idx(qh->sched_frame);
38756 +       }
38757 +
38758 +       qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx);
38759 +
38760 +       return skip_frames;
38761 +}
38762 +
38763 +#define        ISOC_URB_GIVEBACK_ASAP
38764 +
38765 +#define MAX_ISOC_XFER_SIZE_FS 1023
38766 +#define MAX_ISOC_XFER_SIZE_HS 3072
38767 +#define DESCNUM_THRESHOLD 4
38768 +
38769 +static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38770 +                              uint8_t skip_frames)
38771 +{
38772 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
38773 +       dwc_otg_qtd_t *qtd;
38774 +       dwc_otg_host_dma_desc_t *dma_desc;
38775 +       uint16_t idx, inc, n_desc, ntd_max, max_xfer_size;
38776 +
38777 +       idx = qh->td_last;
38778 +       inc = qh->interval;
38779 +       n_desc = 0;
38780 +
38781 +       ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval;
38782 +       if (skip_frames && !qh->channel)
38783 +               ntd_max = ntd_max - skip_frames / qh->interval;
38784 +
38785 +       max_xfer_size =
38786 +           (qh->dev_speed ==
38787 +            DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS :
38788 +           MAX_ISOC_XFER_SIZE_FS;
38789 +
38790 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
38791 +               while ((qh->ntd < ntd_max)
38792 +                      && (qtd->isoc_frame_index_last <
38793 +                          qtd->urb->packet_count)) {
38794 +
38795 +                       dma_desc = &qh->desc_list[idx];
38796 +                       dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t));
38797 +
38798 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
38799 +
38800 +                       if (frame_desc->length > max_xfer_size)
38801 +                               qh->n_bytes[idx] = max_xfer_size;
38802 +                       else
38803 +                               qh->n_bytes[idx] = frame_desc->length;
38804 +                       dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];
38805 +                       dma_desc->status.b_isoc.a = 1;
38806 +                       dma_desc->status.b_isoc.sts = 0;
38807 +
38808 +                       dma_desc->buf = qtd->urb->dma + frame_desc->offset;
38809 +
38810 +                       qh->ntd++;
38811 +
38812 +                       qtd->isoc_frame_index_last++;
38813 +
38814 +#ifdef ISOC_URB_GIVEBACK_ASAP
38815 +                       /* 
38816 +                        * Set IOC for each descriptor corresponding to the 
38817 +                        * last frame of the URB.
38818 +                        */
38819 +                       if (qtd->isoc_frame_index_last ==
38820 +                           qtd->urb->packet_count)
38821 +                               dma_desc->status.b_isoc.ioc = 1;
38822 +
38823 +#endif
38824 +                       idx = desclist_idx_inc(idx, inc, qh->dev_speed);
38825 +                       n_desc++;
38826 +
38827 +               }
38828 +               qtd->in_process = 1;
38829 +       }
38830 +
38831 +       qh->td_last = idx;
38832 +
38833 +#ifdef ISOC_URB_GIVEBACK_ASAP
38834 +       /* Set IOC for the last descriptor if descriptor list is full */
38835 +       if (qh->ntd == ntd_max) {
38836 +               idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
38837 +               qh->desc_list[idx].status.b_isoc.ioc = 1;
38838 +       }
38839 +#else
38840 +       /* 
38841 +        * Set IOC bit only for one descriptor. 
38842 +        * Always try to be ahead of HW processing,
38843 +        * i.e. on IOC generation driver activates next descriptors but
38844 +        * core continues to process descriptors followed the one with IOC set.
38845 +        */
38846 +
38847 +       if (n_desc > DESCNUM_THRESHOLD) {
38848 +               /* 
38849 +                * Move IOC "up". Required even if there is only one QTD 
38850 +                * in the list, cause QTDs migth continue to be queued,
38851 +                * but during the activation it was only one queued.
38852 +                * Actually more than one QTD might be in the list if this function called 
38853 +                * from XferCompletion - QTDs was queued during HW processing of the previous
38854 +                * descriptor chunk.
38855 +                */
38856 +               idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed);
38857 +       } else {
38858 +               /* 
38859 +                * Set the IOC for the latest descriptor
38860 +                * if either number of descriptor is not greather than threshold
38861 +                * or no more new descriptors activated.
38862 +                */
38863 +               idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
38864 +       }
38865 +
38866 +       qh->desc_list[idx].status.b_isoc.ioc = 1;
38867 +#endif
38868 +}
38869 +
38870 +static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38871 +{
38872 +
38873 +       dwc_hc_t *hc;
38874 +       dwc_otg_host_dma_desc_t *dma_desc;
38875 +       dwc_otg_qtd_t *qtd;
38876 +       int num_packets, len, n_desc = 0;
38877 +
38878 +       hc = qh->channel;
38879 +
38880 +       /* 
38881 +        * Start with hc->xfer_buff initialized in 
38882 +        * assign_and_init_hc(), then if SG transfer consists of multiple URBs,
38883 +        * this pointer re-assigned to the buffer of the currently processed QTD.
38884 +        * For non-SG request there is always one QTD active.
38885 +        */
38886 +
38887 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
38888 +
38889 +               if (n_desc) {
38890 +                       /* SG request - more than 1 QTDs */
38891 +                       hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;
38892 +                       hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;
38893 +               }
38894 +
38895 +               qtd->n_desc = 0;
38896 +
38897 +               do {
38898 +                       dma_desc = &qh->desc_list[n_desc];
38899 +                       len = hc->xfer_len;
38900 +
38901 +                       if (len > MAX_DMA_DESC_SIZE)
38902 +                               len = MAX_DMA_DESC_SIZE - hc->max_packet + 1;
38903 +
38904 +                       if (hc->ep_is_in) {
38905 +                               if (len > 0) {
38906 +                                       num_packets = (len + hc->max_packet - 1) / hc->max_packet;
38907 +                               } else {
38908 +                                       /* Need 1 packet for transfer length of 0. */
38909 +                                       num_packets = 1;
38910 +                               }
38911 +                               /* Always program an integral # of max packets for IN transfers. */
38912 +                               len = num_packets * hc->max_packet;
38913 +                       }
38914 +
38915 +                       dma_desc->status.b.n_bytes = len;
38916 +
38917 +                       qh->n_bytes[n_desc] = len;
38918 +
38919 +                       if ((qh->ep_type == UE_CONTROL)
38920 +                           && (qtd->control_phase == DWC_OTG_CONTROL_SETUP))
38921 +                               dma_desc->status.b.sup = 1;     /* Setup Packet */
38922 +
38923 +                       dma_desc->status.b.a = 1;       /* Active descriptor */
38924 +                       dma_desc->status.b.sts = 0;
38925 +
38926 +                       dma_desc->buf =
38927 +                           ((unsigned long)hc->xfer_buff & 0xffffffff);
38928 +
38929 +                       /* 
38930 +                        * Last descriptor(or single) of IN transfer 
38931 +                        * with actual size less than MaxPacket.
38932 +                        */
38933 +                       if (len > hc->xfer_len) {
38934 +                               hc->xfer_len = 0;
38935 +                       } else {
38936 +                               hc->xfer_buff += len;
38937 +                               hc->xfer_len -= len;
38938 +                       }
38939 +
38940 +                       qtd->n_desc++;
38941 +                       n_desc++;
38942 +               }
38943 +               while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC));
38944 +               
38945 +
38946 +               qtd->in_process = 1;
38947 +
38948 +               if (qh->ep_type == UE_CONTROL)
38949 +                       break;
38950 +
38951 +               if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
38952 +                       break;
38953 +       }
38954 +
38955 +       if (n_desc) {
38956 +               /* Request Transfer Complete interrupt for the last descriptor */
38957 +               qh->desc_list[n_desc - 1].status.b.ioc = 1;
38958 +               /* End of List indicator */
38959 +               qh->desc_list[n_desc - 1].status.b.eol = 1;
38960 +
38961 +               hc->ntd = n_desc;
38962 +       }
38963 +}
38964 +
38965 +/** 
38966 + * For Control and Bulk endpoints initializes descriptor list
38967 + * and starts the transfer.
38968 + *
38969 + * For Interrupt and Isochronous endpoints initializes descriptor list
38970 + * then updates FrameList, marking appropriate entries as active.
38971 + * In case of Isochronous, the starting descriptor index is calculated based
38972 + * on the scheduled frame, but only on the first transfer descriptor within a session.
38973 + * Then starts the transfer via enabling the channel. 
38974 + * For Isochronous endpoint the channel is not halted on XferComplete 
38975 + * interrupt so remains assigned to the endpoint(QH) until session is done.
38976 + *
38977 + * @param hcd The HCD state structure for the DWC OTG controller.
38978 + * @param qh The QH to init.
38979 + *
38980 + * @return 0 if successful, negative error code otherwise.
38981 + */
38982 +void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38983 +{
38984 +       /* Channel is already assigned */
38985 +       dwc_hc_t *hc = qh->channel;
38986 +       uint8_t skip_frames = 0;
38987 +
38988 +       switch (hc->ep_type) {
38989 +       case DWC_OTG_EP_TYPE_CONTROL:
38990 +       case DWC_OTG_EP_TYPE_BULK:
38991 +               init_non_isoc_dma_desc(hcd, qh);
38992 +
38993 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38994 +               break;
38995 +       case DWC_OTG_EP_TYPE_INTR:
38996 +               init_non_isoc_dma_desc(hcd, qh);
38997 +
38998 +               update_frame_list(hcd, qh, 1);
38999 +
39000 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
39001 +               break;
39002 +       case DWC_OTG_EP_TYPE_ISOC:
39003 +
39004 +               if (!qh->ntd)
39005 +                       skip_frames = recalc_initial_desc_idx(hcd, qh);
39006 +
39007 +               init_isoc_dma_desc(hcd, qh, skip_frames);
39008 +
39009 +               if (!hc->xfer_started) {
39010 +
39011 +                       update_frame_list(hcd, qh, 1);
39012 +
39013 +                       /* 
39014 +                        * Always set to max, instead of actual size.
39015 +                        * Otherwise ntd will be changed with 
39016 +                        * channel being enabled. Not recommended.
39017 +                        *
39018 +                        */
39019 +                       hc->ntd = max_desc_num(qh);
39020 +                       /* Enable channel only once for ISOC */
39021 +                       dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
39022 +               }
39023 +
39024 +               break;
39025 +       default:
39026 +
39027 +               break;
39028 +       }
39029 +}
39030 +
39031 +static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
39032 +                                   dwc_hc_t * hc,
39033 +                                   dwc_otg_hc_regs_t * hc_regs,
39034 +                                   dwc_otg_halt_status_e halt_status)
39035 +{
39036 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
39037 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
39038 +       dwc_otg_qh_t *qh;
39039 +       dwc_otg_host_dma_desc_t *dma_desc;
39040 +       uint16_t idx, remain;
39041 +       uint8_t urb_compl;
39042 +
39043 +       qh = hc->qh;
39044 +       idx = qh->td_first;
39045 +
39046 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
39047 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry)
39048 +                   qtd->in_process = 0;
39049 +               return;
39050 +       } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) ||
39051 +                  (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) {
39052 +               /* 
39053 +                * Channel is halted in these error cases.
39054 +                * Considered as serious issues.
39055 +                * Complete all URBs marking all frames as failed, 
39056 +                * irrespective whether some of the descriptors(frames) succeeded or no.
39057 +                * Pass error code to completion routine as well, to
39058 +                * update urb->status, some of class drivers might use it to stop
39059 +                * queing transfer requests.
39060 +                */
39061 +               int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR)
39062 +                   ? (-DWC_E_IO)
39063 +                   : (-DWC_E_OVERFLOW);
39064 +                                               
39065 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
39066 +                       for (idx = 0; idx < qtd->urb->packet_count; idx++) {
39067 +                               frame_desc = &qtd->urb->iso_descs[idx];
39068 +                               frame_desc->status = err;
39069 +                       }
39070 +                       hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err);
39071 +                       dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
39072 +               }
39073 +               return;
39074 +       }
39075 +
39076 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
39077 +
39078 +               if (!qtd->in_process)
39079 +                       break;
39080 +
39081 +               urb_compl = 0;
39082 +
39083 +               do {
39084 +
39085 +                       dma_desc = &qh->desc_list[idx];
39086 +                       
39087 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
39088 +                       remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0;
39089 +
39090 +                       if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) {
39091 +                               /* 
39092 +                                * XactError or, unable to complete all the transactions 
39093 +                                * in the scheduled micro-frame/frame, 
39094 +                                * both indicated by DMA_DESC_STS_PKTERR.
39095 +                                */
39096 +                               qtd->urb->error_count++;
39097 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
39098 +                               frame_desc->status = -DWC_E_PROTOCOL;
39099 +                       } else {
39100 +                               /* Success */
39101 +                                                               
39102 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
39103 +                               frame_desc->status = 0;
39104 +                       }
39105 +
39106 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
39107 +                               /*
39108 +                                * urb->status is not used for isoc transfers here.
39109 +                                * The individual frame_desc status are used instead.
39110 +                                */
39111 +
39112 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
39113 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
39114 +
39115 +                               /* 
39116 +                                * This check is necessary because urb_dequeue can be called 
39117 +                                * from urb complete callback(sound driver example).
39118 +                                * All pending URBs are dequeued there, so no need for
39119 +                                * further processing.
39120 +                                */
39121 +                               if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {   
39122 +                                       return;
39123 +                               }
39124 +
39125 +                               urb_compl = 1;
39126 +
39127 +                       }
39128 +
39129 +                       qh->ntd--;
39130 +
39131 +                       /* Stop if IOC requested descriptor reached */
39132 +                       if (dma_desc->status.b_isoc.ioc) {
39133 +                               idx = desclist_idx_inc(idx, qh->interval, hc->speed);   
39134 +                               goto stop_scan;
39135 +                       }
39136 +
39137 +                       idx = desclist_idx_inc(idx, qh->interval, hc->speed);
39138 +
39139 +                       if (urb_compl)
39140 +                               break;
39141 +               }
39142 +               while (idx != qh->td_first);
39143 +       }
39144 +stop_scan:
39145 +       qh->td_first = idx;
39146 +}
39147 +
39148 +uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
39149 +                                      dwc_hc_t * hc,
39150 +                                      dwc_otg_qtd_t * qtd,
39151 +                                      dwc_otg_host_dma_desc_t * dma_desc,
39152 +                                      dwc_otg_halt_status_e halt_status,
39153 +                                      uint32_t n_bytes, uint8_t * xfer_done)
39154 +{
39155 +
39156 +       uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0;
39157 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
39158 +
39159 +       if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
39160 +               urb->status = -DWC_E_IO;
39161 +               return 1;
39162 +       }
39163 +       if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) {
39164 +               switch (halt_status) {
39165 +               case DWC_OTG_HC_XFER_STALL:
39166 +                       urb->status = -DWC_E_PIPE;
39167 +                       break;
39168 +               case DWC_OTG_HC_XFER_BABBLE_ERR:
39169 +                       urb->status = -DWC_E_OVERFLOW;
39170 +                       break;
39171 +               case DWC_OTG_HC_XFER_XACT_ERR:
39172 +                       urb->status = -DWC_E_PROTOCOL;
39173 +                       break;
39174 +               default:        
39175 +                       DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__,
39176 +                                 halt_status);
39177 +                       break;
39178 +               }
39179 +               return 1;
39180 +       }
39181 +
39182 +       if (dma_desc->status.b.a == 1) {
39183 +               DWC_DEBUGPL(DBG_HCDV,
39184 +                           "Active descriptor encountered on channel %d\n",
39185 +                           hc->hc_num);
39186 +               return 0;
39187 +       }
39188 +
39189 +       if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {
39190 +               if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
39191 +                       urb->actual_length += n_bytes - remain;
39192 +                       if (remain || urb->actual_length == urb->length) {
39193 +                               /* 
39194 +                                * For Control Data stage do not set urb->status=0 to prevent
39195 +                                * URB callback. Set it when Status phase done. See below.
39196 +                                */
39197 +                               *xfer_done = 1;
39198 +                       }
39199 +
39200 +               } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) {
39201 +                       urb->status = 0;
39202 +                       *xfer_done = 1;
39203 +               }
39204 +               /* No handling for SETUP stage */
39205 +       } else {
39206 +               /* BULK and INTR */
39207 +               urb->actual_length += n_bytes - remain;
39208 +               if (remain || urb->actual_length == urb->length) {
39209 +                       urb->status = 0;
39210 +                       *xfer_done = 1;
39211 +               }
39212 +       }
39213 +
39214 +       return 0;
39215 +}
39216 +
39217 +static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
39218 +                                       dwc_hc_t * hc,
39219 +                                       dwc_otg_hc_regs_t * hc_regs,
39220 +                                       dwc_otg_halt_status_e halt_status)
39221 +{
39222 +       dwc_otg_hcd_urb_t *urb = NULL;
39223 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
39224 +       dwc_otg_qh_t *qh;
39225 +       dwc_otg_host_dma_desc_t *dma_desc;
39226 +       uint32_t n_bytes, n_desc, i;
39227 +       uint8_t failed = 0, xfer_done;
39228 +
39229 +       n_desc = 0;
39230 +
39231 +       qh = hc->qh;
39232 +
39233 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
39234 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
39235 +                       qtd->in_process = 0;
39236 +               }
39237 +               return;
39238 +       }
39239 +
39240 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
39241 +
39242 +               urb = qtd->urb;
39243 +
39244 +               n_bytes = 0;
39245 +               xfer_done = 0;
39246 +
39247 +               for (i = 0; i < qtd->n_desc; i++) {
39248 +                       dma_desc = &qh->desc_list[n_desc];
39249 +
39250 +                       n_bytes = qh->n_bytes[n_desc];
39251 +
39252 +                       failed =
39253 +                           update_non_isoc_urb_state_ddma(hcd, hc, qtd,
39254 +                                                          dma_desc,
39255 +                                                          halt_status, n_bytes,
39256 +                                                          &xfer_done);
39257 +
39258 +                       if (failed
39259 +                           || (xfer_done
39260 +                               && (urb->status != -DWC_E_IN_PROGRESS))) {
39261 +
39262 +                               hcd->fops->complete(hcd, urb->priv, urb,
39263 +                                                   urb->status);
39264 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
39265 +
39266 +                               if (failed)
39267 +                                       goto stop_scan;
39268 +                       } else if (qh->ep_type == UE_CONTROL) {
39269 +                               if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) {
39270 +                                       if (urb->length > 0) {
39271 +                                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
39272 +                                       } else {
39273 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
39274 +                                       }
39275 +                                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction done\n");
39276 +                               } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
39277 +                                       if (xfer_done) {
39278 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
39279 +                                               DWC_DEBUGPL(DBG_HCDV, "  Control data transfer done\n");
39280 +                                       } else if (i + 1 == qtd->n_desc) {
39281 +                                               /* 
39282 +                                                * Last descriptor for Control data stage which is
39283 +                                                * not completed yet.
39284 +                                                */
39285 +                                               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
39286 +                                       }
39287 +                               }
39288 +                       }
39289 +
39290 +                       n_desc++;
39291 +               }
39292 +
39293 +       }
39294 +
39295 +stop_scan:
39296 +
39297 +       if (qh->ep_type != UE_CONTROL) {
39298 +               /* 
39299 +                * Resetting the data toggle for bulk
39300 +                * and interrupt endpoints in case of stall. See handle_hc_stall_intr() 
39301 +                */
39302 +               if (halt_status == DWC_OTG_HC_XFER_STALL)
39303 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
39304 +               else
39305 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
39306 +       }
39307 +
39308 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
39309 +               hcint_data_t hcint;
39310 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
39311 +               if (hcint.b.nyet) {
39312 +                       /*
39313 +                        * Got a NYET on the last transaction of the transfer. It
39314 +                        * means that the endpoint should be in the PING state at the
39315 +                        * beginning of the next transfer.
39316 +                        */
39317 +                       qh->ping_state = 1;
39318 +                       clear_hc_int(hc_regs, nyet);
39319 +               }
39320 +
39321 +       }
39322 +
39323 +}
39324 +
39325 +/**
39326 + * This function is called from interrupt handlers.
39327 + * Scans the descriptor list, updates URB's status and
39328 + * calls completion routine for the URB if it's done.
39329 + * Releases the channel to be used by other transfers.
39330 + * In case of Isochronous endpoint the channel is not halted until 
39331 + * the end of the session, i.e. QTD list is empty.
39332 + * If periodic channel released the FrameList is updated accordingly.
39333 + *
39334 + * Calls transaction selection routines to activate pending transfers.
39335 + *
39336 + * @param hcd The HCD state structure for the DWC OTG controller.
39337 + * @param hc Host channel, the transfer is completed on.
39338 + * @param hc_regs Host channel registers.
39339 + * @param halt_status Reason the channel is being halted, 
39340 + *                   or just XferComplete for isochronous transfer
39341 + */
39342 +void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
39343 +                                   dwc_hc_t * hc,
39344 +                                   dwc_otg_hc_regs_t * hc_regs,
39345 +                                   dwc_otg_halt_status_e halt_status)
39346 +{
39347 +       uint8_t continue_isoc_xfer = 0;
39348 +       dwc_otg_transaction_type_e tr_type;
39349 +       dwc_otg_qh_t *qh = hc->qh;
39350 +
39351 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
39352 +
39353 +               complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
39354 +
39355 +               /* Release the channel if halted or session completed */
39356 +               if (halt_status != DWC_OTG_HC_XFER_COMPLETE ||
39357 +                   DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
39358 +
39359 +                       /* Halt the channel if session completed */
39360 +                       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
39361 +                               dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
39362 +                       }
39363 +
39364 +                       release_channel_ddma(hcd, qh);
39365 +                       dwc_otg_hcd_qh_remove(hcd, qh);
39366 +               } else {
39367 +                       /* Keep in assigned schedule to continue transfer */
39368 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
39369 +                                          &qh->qh_list_entry);
39370 +                       continue_isoc_xfer = 1;
39371 +
39372 +               }
39373 +               /** @todo Consider the case when period exceeds FrameList size.
39374 +                *  Frame Rollover interrupt should be used. 
39375 +                */
39376 +       } else {
39377 +               /* Scan descriptor list to complete the URB(s), then release the channel */
39378 +               complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
39379 +
39380 +               release_channel_ddma(hcd, qh);
39381 +               dwc_otg_hcd_qh_remove(hcd, qh);
39382 +
39383 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
39384 +                       /* Add back to inactive non-periodic schedule on normal completion */
39385 +                       dwc_otg_hcd_qh_add(hcd, qh);
39386 +               }
39387 +
39388 +       }
39389 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
39390 +       if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) {
39391 +               if (continue_isoc_xfer) {
39392 +                       if (tr_type == DWC_OTG_TRANSACTION_NONE) {
39393 +                               tr_type = DWC_OTG_TRANSACTION_PERIODIC;
39394 +                       } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) {
39395 +                               tr_type = DWC_OTG_TRANSACTION_ALL;
39396 +                       }
39397 +               }
39398 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
39399 +       }
39400 +}
39401 +
39402 +#endif /* DWC_DEVICE_ONLY */
39403 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
39404 new file mode 100644
39405 index 0000000..b3dc806
39406 --- /dev/null
39407 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
39408 @@ -0,0 +1,412 @@
39409 +/* ==========================================================================
39410 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
39411 + * $Revision: #12 $
39412 + * $Date: 2011/10/26 $
39413 + * $Change: 1873028 $
39414 + *
39415 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39416 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39417 + * otherwise expressly agreed to in writing between Synopsys and you.
39418 + *
39419 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39420 + * any End User Software License Agreement or Agreement for Licensed Product
39421 + * with Synopsys or any supplement thereto. You are permitted to use and
39422 + * redistribute this Software in source and binary forms, with or without
39423 + * modification, provided that redistributions of source code must retain this
39424 + * notice. You may not view, use, disclose, copy or distribute this file or
39425 + * any information contained herein except pursuant to this license grant from
39426 + * Synopsys. If you do not agree with this notice, including the disclaimer
39427 + * below, then you are not authorized to use the Software.
39428 + *
39429 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39430 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39431 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39432 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39433 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39434 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39435 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39436 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39437 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39438 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39439 + * DAMAGE.
39440 + * ========================================================================== */
39441 +#ifndef DWC_DEVICE_ONLY
39442 +#ifndef __DWC_HCD_IF_H__
39443 +#define __DWC_HCD_IF_H__
39444 +
39445 +#include "dwc_otg_core_if.h"
39446 +
39447 +/** @file
39448 + * This file defines DWC_OTG HCD Core API.
39449 + */
39450 +
39451 +struct dwc_otg_hcd;
39452 +typedef struct dwc_otg_hcd dwc_otg_hcd_t;
39453 +
39454 +struct dwc_otg_hcd_urb;
39455 +typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t;
39456 +
39457 +/** @name HCD Function Driver Callbacks */
39458 +/** @{ */
39459 +
39460 +/** This function is called whenever core switches to host mode. */
39461 +typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd);
39462 +
39463 +/** This function is called when device has been disconnected */
39464 +typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd);
39465 +
39466 +/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */
39467 +typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39468 +                                                  void *urb_handle,
39469 +                                                  uint32_t * hub_addr,
39470 +                                                  uint32_t * port_addr);
39471 +/** Via this function HCD core gets device speed */
39472 +typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39473 +                                               void *urb_handle);
39474 +
39475 +/** This function is called when urb is completed */
39476 +typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd,
39477 +                                             void *urb_handle,
39478 +                                             dwc_otg_hcd_urb_t * dwc_otg_urb,
39479 +                                             int32_t status);
39480 +
39481 +/** Via this function HCD core gets b_hnp_enable parameter */
39482 +typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd);
39483 +
39484 +struct dwc_otg_hcd_function_ops {
39485 +       dwc_otg_hcd_start_cb_t start;
39486 +       dwc_otg_hcd_disconnect_cb_t disconnect;
39487 +       dwc_otg_hcd_hub_info_from_urb_cb_t hub_info;
39488 +       dwc_otg_hcd_speed_from_urb_cb_t speed;
39489 +       dwc_otg_hcd_complete_urb_cb_t complete;
39490 +       dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable;
39491 +};
39492 +/** @} */
39493 +
39494 +/** @name HCD Core API */
39495 +/** @{ */
39496 +/** This function allocates dwc_otg_hcd structure and returns pointer on it. */
39497 +extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void);
39498 +
39499 +/** This function should be called to initiate HCD Core.
39500 + *
39501 + * @param hcd The HCD
39502 + * @param core_if The DWC_OTG Core
39503 + *
39504 + * Returns -DWC_E_NO_MEMORY if no enough memory.
39505 + * Returns 0 on success  
39506 + */
39507 +extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if);
39508 +
39509 +/** Frees HCD
39510 + *
39511 + * @param hcd The HCD
39512 + */
39513 +extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
39514 +
39515 +/** This function should be called on every hardware interrupt.
39516 + *
39517 + * @param dwc_otg_hcd The HCD
39518 + *
39519 + * Returns non zero if interrupt is handled
39520 + * Return 0 if interrupt is not handled
39521 + */
39522 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
39523 +
39524 +/**
39525 + * Returns private data set by
39526 + * dwc_otg_hcd_set_priv_data function.
39527 + *
39528 + * @param hcd The HCD
39529 + */
39530 +extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd);
39531 +
39532 +/**
39533 + * Set private data.
39534 + *
39535 + * @param hcd The HCD
39536 + * @param priv_data pointer to be stored in private data
39537 + */
39538 +extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data);
39539 +
39540 +/**
39541 + * This function initializes the HCD Core.
39542 + *
39543 + * @param hcd The HCD
39544 + * @param fops The Function Driver Operations data structure containing pointers to all callbacks.
39545 + *
39546 + * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode.
39547 + * Returns 0 on success
39548 + */
39549 +extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
39550 +                            struct dwc_otg_hcd_function_ops *fops);
39551 +
39552 +/**
39553 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
39554 + * stopped. 
39555 + *
39556 + * @param hcd The HCD
39557 + */
39558 +extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd);
39559 +
39560 +/**
39561 + * Handles hub class-specific requests.
39562 + *
39563 + * @param dwc_otg_hcd The HCD
39564 + * @param typeReq Request Type
39565 + * @param wValue wValue from control request
39566 + * @param wIndex wIndex from control request
39567 + * @param buf data buffer 
39568 + * @param wLength data buffer length
39569 + *
39570 + * Returns -DWC_E_INVALID if invalid argument is passed
39571 + * Returns 0 on success
39572 + */
39573 +extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
39574 +                                  uint16_t typeReq, uint16_t wValue,
39575 +                                  uint16_t wIndex, uint8_t * buf,
39576 +                                  uint16_t wLength);
39577 +
39578 +/**
39579 + * Returns otg port number.
39580 + *
39581 + * @param hcd The HCD
39582 + */
39583 +extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd);
39584 +
39585 +/**
39586 + * Returns OTG version - either 1.3 or 2.0.
39587 + *
39588 + * @param core_if The core_if structure pointer
39589 + */
39590 +extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if);
39591 +
39592 +/**
39593 + * Returns 1 if currently core is acting as B host, and 0 otherwise.
39594 + *
39595 + * @param hcd The HCD
39596 + */
39597 +extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd);
39598 +
39599 +/**
39600 + * Returns current frame number.
39601 + *
39602 + * @param hcd The HCD
39603 + */
39604 +extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd);
39605 +
39606 +/**
39607 + * Dumps hcd state.
39608 + *
39609 + * @param hcd The HCD
39610 + */
39611 +extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd);
39612 +
39613 +/**
39614 + * Dump the average frame remaining at SOF. This can be used to
39615 + * determine average interrupt latency. Frame remaining is also shown for
39616 + * start transfer and two additional sample points.
39617 + * Currently this function is not implemented.
39618 + *
39619 + * @param hcd The HCD
39620 + */
39621 +extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd);
39622 +
39623 +/**
39624 + * Sends LPM transaction to the local device.
39625 + *
39626 + * @param hcd The HCD
39627 + * @param devaddr Device Address
39628 + * @param hird Host initiated resume duration
39629 + * @param bRemoteWake Value of bRemoteWake field in LPM transaction
39630 + *
39631 + * Returns negative value if sending LPM transaction was not succeeded.
39632 + * Returns 0 on success.
39633 + */
39634 +extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr,
39635 +                               uint8_t hird, uint8_t bRemoteWake);
39636 +
39637 +/* URB interface */
39638 +
39639 +/**
39640 + * Allocates memory for dwc_otg_hcd_urb structure.
39641 + * Allocated memory should be freed by call of DWC_FREE.
39642 + *
39643 + * @param hcd The HCD
39644 + * @param iso_desc_count Count of ISOC descriptors
39645 + * @param atomic_alloc Specefies whether to perform atomic allocation.
39646 + */
39647 +extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
39648 +                                               int iso_desc_count,
39649 +                                               int atomic_alloc);
39650 +
39651 +/**
39652 + * Set pipe information in URB.
39653 + *
39654 + * @param hcd_urb DWC_OTG URB
39655 + * @param devaddr Device Address
39656 + * @param ep_num Endpoint Number
39657 + * @param ep_type Endpoint Type
39658 + * @param ep_dir Endpoint Direction
39659 + * @param mps Max Packet Size
39660 + */
39661 +extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb,
39662 +                                        uint8_t devaddr, uint8_t ep_num,
39663 +                                        uint8_t ep_type, uint8_t ep_dir,
39664 +                                        uint16_t mps);
39665 +
39666 +/* Transfer flags */
39667 +#define URB_GIVEBACK_ASAP 0x1
39668 +#define URB_SEND_ZERO_PACKET 0x2
39669 +
39670 +/**
39671 + * Sets dwc_otg_hcd_urb parameters.
39672 + *
39673 + * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function.
39674 + * @param urb_handle Unique handle for request, this will be passed back
39675 + * to function driver in completion callback.
39676 + * @param buf The buffer for the data
39677 + * @param dma The DMA buffer for the data
39678 + * @param buflen Transfer length
39679 + * @param sp Buffer for setup data
39680 + * @param sp_dma DMA address of setup data buffer
39681 + * @param flags Transfer flags
39682 + * @param interval Polling interval for interrupt or isochronous transfers.
39683 + */
39684 +extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb,
39685 +                                      void *urb_handle, void *buf,
39686 +                                      dwc_dma_t dma, uint32_t buflen, void *sp,
39687 +                                      dwc_dma_t sp_dma, uint32_t flags,
39688 +                                      uint16_t interval);
39689 +
39690 +/** Gets status from dwc_otg_hcd_urb
39691 + *
39692 + * @param dwc_otg_urb DWC_OTG URB
39693 + */
39694 +extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb);
39695 +
39696 +/** Gets actual length from dwc_otg_hcd_urb
39697 + *
39698 + * @param dwc_otg_urb DWC_OTG URB
39699 + */
39700 +extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *
39701 +                                                 dwc_otg_urb);
39702 +
39703 +/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs
39704 + *
39705 + * @param dwc_otg_urb DWC_OTG URB
39706 + */
39707 +extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *
39708 +                                               dwc_otg_urb);
39709 +
39710 +/** Set ISOC descriptor offset and length
39711 + *
39712 + * @param dwc_otg_urb DWC_OTG URB
39713 + * @param desc_num ISOC descriptor number
39714 + * @param offset Offset from beginig of buffer.
39715 + * @param length Transaction length
39716 + */
39717 +extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
39718 +                                               int desc_num, uint32_t offset,
39719 +                                               uint32_t length);
39720 +
39721 +/** Get status of ISOC descriptor, specified by desc_num
39722 + *
39723 + * @param dwc_otg_urb DWC_OTG URB
39724 + * @param desc_num ISOC descriptor number 
39725 + */
39726 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *
39727 +                                                   dwc_otg_urb, int desc_num);
39728 +
39729 +/** Get actual length of ISOC descriptor, specified by desc_num
39730 + *
39731 + * @param dwc_otg_urb DWC_OTG URB
39732 + * @param desc_num ISOC descriptor number
39733 + */
39734 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
39735 +                                                          dwc_otg_urb,
39736 +                                                          int desc_num);
39737 +
39738 +/** Queue URB. After transfer is completes, the complete callback will be called with the URB status
39739 + *
39740 + * @param dwc_otg_hcd The HCD
39741 + * @param dwc_otg_urb DWC_OTG URB
39742 + * @param ep_handle Out parameter for returning endpoint handle
39743 + * @param atomic_alloc Flag to do atomic allocation if needed
39744 + *
39745 + * Returns -DWC_E_NO_DEVICE if no device is connected.
39746 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
39747 + * Returns 0 on success.
39748 + */
39749 +extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd,
39750 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb,
39751 +                                  void **ep_handle, int atomic_alloc);
39752 +
39753 +/** De-queue the specified URB
39754 + *
39755 + * @param dwc_otg_hcd The HCD
39756 + * @param dwc_otg_urb DWC_OTG URB
39757 + */
39758 +extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd,
39759 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb);
39760 +
39761 +/** Frees resources in the DWC_otg controller related to a given endpoint.
39762 + * Any URBs for the endpoint must already be dequeued.
39763 + *
39764 + * @param hcd The HCD
39765 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39766 + * @param retry Number of retries if there are queued transfers.
39767 + *
39768 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39769 + * Returns 0 on success
39770 + */
39771 +extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
39772 +                                       int retry);
39773 +
39774 +/* Resets the data toggle in qh structure. This function can be called from
39775 + * usb_clear_halt routine.
39776 + *
39777 + * @param hcd The HCD
39778 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39779 + *
39780 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39781 + * Returns 0 on success
39782 + */
39783 +extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle);
39784 +
39785 +/** Returns 1 if status of specified port is changed and 0 otherwise.
39786 + *
39787 + * @param hcd The HCD
39788 + * @param port Port number
39789 + */
39790 +extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port);
39791 +
39792 +/** Call this function to check if bandwidth was allocated for specified endpoint.
39793 + * Only for ISOC and INTERRUPT endpoints.
39794 + *
39795 + * @param hcd The HCD
39796 + * @param ep_handle Endpoint handle
39797 + */
39798 +extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd,
39799 +                                             void *ep_handle);
39800 +
39801 +/** Call this function to check if bandwidth was freed for specified endpoint.
39802 + *
39803 + * @param hcd The HCD
39804 + * @param ep_handle Endpoint handle
39805 + */
39806 +extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle);
39807 +
39808 +/** Returns bandwidth allocated for specified endpoint in microseconds.
39809 + * Only for ISOC and INTERRUPT endpoints.
39810 + *
39811 + * @param hcd The HCD
39812 + * @param ep_handle Endpoint handle
39813 + */
39814 +extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd,
39815 +                                           void *ep_handle);
39816 +
39817 +/** @} */
39818 +
39819 +#endif /* __DWC_HCD_IF_H__ */
39820 +#endif /* DWC_DEVICE_ONLY */
39821 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
39822 new file mode 100644
39823 index 0000000..63c1b55
39824 --- /dev/null
39825 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
39826 @@ -0,0 +1,2106 @@
39827 +/* ==========================================================================
39828 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
39829 + * $Revision: #89 $
39830 + * $Date: 2011/10/20 $
39831 + * $Change: 1869487 $
39832 + *
39833 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39834 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39835 + * otherwise expressly agreed to in writing between Synopsys and you.
39836 + *
39837 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39838 + * any End User Software License Agreement or Agreement for Licensed Product
39839 + * with Synopsys or any supplement thereto. You are permitted to use and
39840 + * redistribute this Software in source and binary forms, with or without
39841 + * modification, provided that redistributions of source code must retain this
39842 + * notice. You may not view, use, disclose, copy or distribute this file or
39843 + * any information contained herein except pursuant to this license grant from
39844 + * Synopsys. If you do not agree with this notice, including the disclaimer
39845 + * below, then you are not authorized to use the Software.
39846 + *
39847 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39848 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39849 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39850 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39851 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39852 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39853 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39854 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39855 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39856 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39857 + * DAMAGE.
39858 + * ========================================================================== */
39859 +#ifndef DWC_DEVICE_ONLY
39860 +
39861 +#include "dwc_otg_hcd.h"
39862 +#include "dwc_otg_regs.h"
39863 +
39864 +extern bool microframe_schedule;
39865 +
39866 +/** @file
39867 + * This file contains the implementation of the HCD Interrupt handlers.
39868 + */
39869 +
39870 +/** This function handles interrupts for the HCD. */
39871 +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39872 +{
39873 +       int retval = 0;
39874 +
39875 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
39876 +       gintsts_data_t gintsts;
39877 +#ifdef DEBUG
39878 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
39879 +
39880 +        //GRAYG: debugging
39881 +        if (NULL == global_regs) {
39882 +                DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
39883 +                            "core_if=%p\n",
39884 +                            dwc_otg_hcd, global_regs);
39885 +                return retval;
39886 +        }
39887 +#endif
39888 +
39889 +       /* Exit from ISR if core is hibernated */
39890 +       if (core_if->hibernation_suspend == 1) {
39891 +               return retval;
39892 +       }
39893 +       DWC_SPINLOCK(dwc_otg_hcd->lock);
39894 +       /* Check if HOST Mode */
39895 +       if (dwc_otg_is_host_mode(core_if)) {
39896 +               gintsts.d32 = dwc_otg_read_core_intr(core_if);
39897 +               if (!gintsts.d32) {
39898 +                       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39899 +                       return 0;
39900 +               }
39901 +#ifdef DEBUG
39902 +               /* Don't print debug message in the interrupt handler on SOF */
39903 +#ifndef DEBUG_SOF
39904 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39905 +#endif
39906 +                       DWC_DEBUGPL(DBG_HCDI, "\n");
39907 +#endif
39908 +
39909 +#ifdef DEBUG
39910 +#ifndef DEBUG_SOF
39911 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39912 +#endif
39913 +                       DWC_DEBUGPL(DBG_HCDI,
39914 +                                   "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
39915 +                                   gintsts.d32, core_if);
39916 +#endif
39917 +
39918 +               if (gintsts.b.sofintr) {
39919 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
39920 +               }
39921 +               if (gintsts.b.rxstsqlvl) {
39922 +                       retval |=
39923 +                           dwc_otg_hcd_handle_rx_status_q_level_intr
39924 +                           (dwc_otg_hcd);
39925 +               }
39926 +               if (gintsts.b.nptxfempty) {
39927 +                       retval |=
39928 +                           dwc_otg_hcd_handle_np_tx_fifo_empty_intr
39929 +                           (dwc_otg_hcd);
39930 +               }
39931 +               if (gintsts.b.i2cintr) {
39932 +                       /** @todo Implement i2cintr handler. */
39933 +               }
39934 +               if (gintsts.b.portintr) {
39935 +                       retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
39936 +               }
39937 +               if (gintsts.b.hcintr) {
39938 +                       retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
39939 +               }
39940 +               if (gintsts.b.ptxfempty) {
39941 +                       retval |=
39942 +                           dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
39943 +                           (dwc_otg_hcd);
39944 +               }
39945 +#ifdef DEBUG
39946 +#ifndef DEBUG_SOF
39947 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39948 +#endif
39949 +               {
39950 +                       DWC_DEBUGPL(DBG_HCDI,
39951 +                                   "DWC OTG HCD Finished Servicing Interrupts\n");
39952 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
39953 +                                   DWC_READ_REG32(&global_regs->gintsts));
39954 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
39955 +                                   DWC_READ_REG32(&global_regs->gintmsk));
39956 +               }
39957 +#endif
39958 +
39959 +#ifdef DEBUG
39960 +#ifndef DEBUG_SOF
39961 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39962 +#endif
39963 +                       DWC_DEBUGPL(DBG_HCDI, "\n");
39964 +#endif
39965 +
39966 +       }
39967 +       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39968 +       return retval;
39969 +}
39970 +
39971 +#ifdef DWC_TRACK_MISSED_SOFS
39972 +#warning Compiling code to track missed SOFs
39973 +#define FRAME_NUM_ARRAY_SIZE 1000
39974 +/**
39975 + * This function is for debug only.
39976 + */
39977 +static inline void track_missed_sofs(uint16_t curr_frame_number)
39978 +{
39979 +       static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
39980 +       static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
39981 +       static int frame_num_idx = 0;
39982 +       static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
39983 +       static int dumped_frame_num_array = 0;
39984 +
39985 +       if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
39986 +               if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
39987 +                   curr_frame_number) {
39988 +                       frame_num_array[frame_num_idx] = curr_frame_number;
39989 +                       last_frame_num_array[frame_num_idx++] = last_frame_num;
39990 +               }
39991 +       } else if (!dumped_frame_num_array) {
39992 +               int i;
39993 +               DWC_PRINTF("Frame     Last Frame\n");
39994 +               DWC_PRINTF("-----     ----------\n");
39995 +               for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
39996 +                       DWC_PRINTF("0x%04x    0x%04x\n",
39997 +                                  frame_num_array[i], last_frame_num_array[i]);
39998 +               }
39999 +               dumped_frame_num_array = 1;
40000 +       }
40001 +       last_frame_num = curr_frame_number;
40002 +}
40003 +#endif
40004 +
40005 +/**
40006 + * Handles the start-of-frame interrupt in host mode. Non-periodic
40007 + * transactions may be queued to the DWC_otg controller for the current
40008 + * (micro)frame. Periodic transactions may be queued to the controller for the
40009 + * next (micro)frame.
40010 + */
40011 +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
40012 +{
40013 +       hfnum_data_t hfnum;
40014 +       dwc_list_link_t *qh_entry;
40015 +       dwc_otg_qh_t *qh;
40016 +       dwc_otg_transaction_type_e tr_type;
40017 +       gintsts_data_t gintsts = {.d32 = 0 };
40018 +
40019 +       hfnum.d32 =
40020 +           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
40021 +
40022 +#ifdef DEBUG_SOF
40023 +       DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
40024 +#endif
40025 +       hcd->frame_number = hfnum.b.frnum;
40026 +
40027 +#ifdef DEBUG
40028 +       hcd->frrem_accum += hfnum.b.frrem;
40029 +       hcd->frrem_samples++;
40030 +#endif
40031 +
40032 +#ifdef DWC_TRACK_MISSED_SOFS
40033 +       track_missed_sofs(hcd->frame_number);
40034 +#endif
40035 +       /* Determine whether any periodic QHs should be executed. */
40036 +       qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
40037 +       while (qh_entry != &hcd->periodic_sched_inactive) {
40038 +               qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
40039 +               qh_entry = qh_entry->next;
40040 +               if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
40041 +                       /*
40042 +                        * Move QH to the ready list to be executed next
40043 +                        * (micro)frame.
40044 +                        */
40045 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
40046 +                                          &qh->qh_list_entry);
40047 +               }
40048 +       }
40049 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
40050 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
40051 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
40052 +       }
40053 +
40054 +       /* Clear interrupt */
40055 +       gintsts.b.sofintr = 1;
40056 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
40057 +
40058 +       return 1;
40059 +}
40060 +
40061 +/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at
40062 + * least one packet in the Rx FIFO.  The packets are moved from the FIFO to
40063 + * memory if the DWC_otg controller is operating in Slave mode. */
40064 +int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40065 +{
40066 +       host_grxsts_data_t grxsts;
40067 +       dwc_hc_t *hc = NULL;
40068 +
40069 +       DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
40070 +
40071 +       grxsts.d32 =
40072 +           DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
40073 +
40074 +       hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
40075 +       if (!hc) {
40076 +               DWC_ERROR("Unable to get corresponding channel\n");
40077 +               return 0;
40078 +       }
40079 +
40080 +       /* Packet Status */
40081 +       DWC_DEBUGPL(DBG_HCDV, "    Ch num = %d\n", grxsts.b.chnum);
40082 +       DWC_DEBUGPL(DBG_HCDV, "    Count = %d\n", grxsts.b.bcnt);
40083 +       DWC_DEBUGPL(DBG_HCDV, "    DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
40084 +                   hc->data_pid_start);
40085 +       DWC_DEBUGPL(DBG_HCDV, "    PStatus = %d\n", grxsts.b.pktsts);
40086 +
40087 +       switch (grxsts.b.pktsts) {
40088 +       case DWC_GRXSTS_PKTSTS_IN:
40089 +               /* Read the data into the host buffer. */
40090 +               if (grxsts.b.bcnt > 0) {
40091 +                       dwc_otg_read_packet(dwc_otg_hcd->core_if,
40092 +                                           hc->xfer_buff, grxsts.b.bcnt);
40093 +
40094 +                       /* Update the HC fields for the next packet received. */
40095 +                       hc->xfer_count += grxsts.b.bcnt;
40096 +                       hc->xfer_buff += grxsts.b.bcnt;
40097 +               }
40098 +
40099 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
40100 +       case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
40101 +       case DWC_GRXSTS_PKTSTS_CH_HALTED:
40102 +               /* Handled in interrupt, just ignore data */
40103 +               break;
40104 +       default:
40105 +               DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
40106 +                         grxsts.b.pktsts);
40107 +               break;
40108 +       }
40109 +
40110 +       return 1;
40111 +}
40112 +
40113 +/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
40114 + * data packets may be written to the FIFO for OUT transfers. More requests
40115 + * may be written to the non-periodic request queue for IN transfers. This
40116 + * interrupt is enabled only in Slave mode. */
40117 +int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40118 +{
40119 +       DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
40120 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
40121 +                                      DWC_OTG_TRANSACTION_NON_PERIODIC);
40122 +       return 1;
40123 +}
40124 +
40125 +/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data
40126 + * packets may be written to the FIFO for OUT transfers. More requests may be
40127 + * written to the periodic request queue for IN transfers. This interrupt is
40128 + * enabled only in Slave mode. */
40129 +int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40130 +{
40131 +       DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
40132 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
40133 +                                      DWC_OTG_TRANSACTION_PERIODIC);
40134 +       return 1;
40135 +}
40136 +
40137 +/** There are multiple conditions that can cause a port interrupt. This function
40138 + * determines which interrupt conditions have occurred and handles them
40139 + * appropriately. */
40140 +int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40141 +{
40142 +       int retval = 0;
40143 +       hprt0_data_t hprt0;
40144 +       hprt0_data_t hprt0_modify;
40145 +
40146 +       hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40147 +       hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40148 +
40149 +       /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
40150 +        * GINTSTS */
40151 +
40152 +       hprt0_modify.b.prtena = 0;
40153 +       hprt0_modify.b.prtconndet = 0;
40154 +       hprt0_modify.b.prtenchng = 0;
40155 +       hprt0_modify.b.prtovrcurrchng = 0;
40156 +
40157 +       /* Port Connect Detected
40158 +        * Set flag and clear if detected */
40159 +       if (dwc_otg_hcd->core_if->hibernation_suspend == 1) {
40160 +               // Dont modify port status if we are in hibernation state
40161 +               hprt0_modify.b.prtconndet = 1;
40162 +               hprt0_modify.b.prtenchng = 1;
40163 +               DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40164 +               hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40165 +               return retval;
40166 +       }
40167 +
40168 +       if (hprt0.b.prtconndet) {
40169 +               /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */
40170 +               if (dwc_otg_hcd->core_if->adp_enable &&         
40171 +                               dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {
40172 +                       DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");
40173 +                       DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);
40174 +                       dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40175 +                       /* TODO - check if this is required, as
40176 +                        * host initialization was already performed
40177 +                        * after initial ADP probing
40178 +                        */
40179 +                       /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40180 +                       dwc_otg_core_init(dwc_otg_hcd->core_if);
40181 +                       dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);
40182 +                       cil_hcd_start(dwc_otg_hcd->core_if);*/
40183 +               } else {
40184 +               
40185 +                       DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
40186 +                                   "Port Connect Detected--\n", hprt0.d32);
40187 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
40188 +                       dwc_otg_hcd->flags.b.port_connect_status = 1;
40189 +                       hprt0_modify.b.prtconndet = 1;
40190 +       
40191 +                       /* B-Device has connected, Delete the connection timer. */
40192 +                       DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
40193 +               }
40194 +               /* The Hub driver asserts a reset when it sees port connect
40195 +                * status change flag */
40196 +               retval |= 1;
40197 +       }
40198 +
40199 +       /* Port Enable Changed
40200 +        * Clear if detected - Set internal flag if disabled */
40201 +       if (hprt0.b.prtenchng) {
40202 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
40203 +                           "Port Enable Changed--\n", hprt0.d32);
40204 +               hprt0_modify.b.prtenchng = 1;
40205 +               if (hprt0.b.prtena == 1) {
40206 +                       hfir_data_t hfir;
40207 +                       int do_reset = 0;
40208 +                       dwc_otg_core_params_t *params =
40209 +                           dwc_otg_hcd->core_if->core_params;
40210 +                       dwc_otg_core_global_regs_t *global_regs =
40211 +                           dwc_otg_hcd->core_if->core_global_regs;
40212 +                       dwc_otg_host_if_t *host_if =
40213 +                           dwc_otg_hcd->core_if->host_if;
40214 +                           
40215 +                       /* Every time when port enables calculate
40216 +                        * HFIR.FrInterval
40217 +                        */
40218 +                       hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
40219 +                       hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if);
40220 +                       DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
40221 +
40222 +                       /* Check if we need to adjust the PHY clock speed for
40223 +                        * low power and adjust it */
40224 +                       if (params->host_support_fs_ls_low_power) {
40225 +                               gusbcfg_data_t usbcfg;
40226 +
40227 +                               usbcfg.d32 =
40228 +                                   DWC_READ_REG32(&global_regs->gusbcfg);
40229 +
40230 +                               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
40231 +                                   || hprt0.b.prtspd ==
40232 +                                   DWC_HPRT0_PRTSPD_FULL_SPEED) {
40233 +                                       /*
40234 +                                        * Low power
40235 +                                        */
40236 +                                       hcfg_data_t hcfg;
40237 +                                       if (usbcfg.b.phylpwrclksel == 0) {
40238 +                                               /* Set PHY low power clock select for FS/LS devices */
40239 +                                               usbcfg.b.phylpwrclksel = 1;
40240 +                                               DWC_WRITE_REG32
40241 +                                                   (&global_regs->gusbcfg,
40242 +                                                    usbcfg.d32);
40243 +                                               do_reset = 1;
40244 +                                       }
40245 +
40246 +                                       hcfg.d32 =
40247 +                                           DWC_READ_REG32
40248 +                                           (&host_if->host_global_regs->hcfg);
40249 +
40250 +                                       if (hprt0.b.prtspd ==
40251 +                                           DWC_HPRT0_PRTSPD_LOW_SPEED
40252 +                                           && params->host_ls_low_power_phy_clk
40253 +                                           ==
40254 +                                           DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
40255 +                                       {
40256 +                                               /* 6 MHZ */
40257 +                                               DWC_DEBUGPL(DBG_CIL,
40258 +                                                           "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
40259 +                                               if (hcfg.b.fslspclksel !=
40260 +                                                   DWC_HCFG_6_MHZ) {
40261 +                                                       hcfg.b.fslspclksel =
40262 +                                                           DWC_HCFG_6_MHZ;
40263 +                                                       DWC_WRITE_REG32
40264 +                                                           (&host_if->host_global_regs->hcfg,
40265 +                                                            hcfg.d32);
40266 +                                                       do_reset = 1;
40267 +                                               }
40268 +                                       } else {
40269 +                                               /* 48 MHZ */
40270 +                                               DWC_DEBUGPL(DBG_CIL,
40271 +                                                           "FS_PHY programming HCFG to 48 MHz ()\n");
40272 +                                               if (hcfg.b.fslspclksel !=
40273 +                                                   DWC_HCFG_48_MHZ) {
40274 +                                                       hcfg.b.fslspclksel =
40275 +                                                           DWC_HCFG_48_MHZ;
40276 +                                                       DWC_WRITE_REG32
40277 +                                                           (&host_if->host_global_regs->hcfg,
40278 +                                                            hcfg.d32);
40279 +                                                       do_reset = 1;
40280 +                                               }
40281 +                                       }
40282 +                               } else {
40283 +                                       /*
40284 +                                        * Not low power
40285 +                                        */
40286 +                                       if (usbcfg.b.phylpwrclksel == 1) {
40287 +                                               usbcfg.b.phylpwrclksel = 0;
40288 +                                               DWC_WRITE_REG32
40289 +                                                   (&global_regs->gusbcfg,
40290 +                                                    usbcfg.d32);
40291 +                                               do_reset = 1;
40292 +                                       }
40293 +                               }
40294 +
40295 +                               if (do_reset) {
40296 +                                       DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet);
40297 +                               }
40298 +                       }
40299 +
40300 +                       if (!do_reset) {
40301 +                               /* Port has been enabled set the reset change flag */
40302 +                               dwc_otg_hcd->flags.b.port_reset_change = 1;
40303 +                       }
40304 +               } else {
40305 +                       dwc_otg_hcd->flags.b.port_enable_change = 1;
40306 +               }
40307 +               retval |= 1;
40308 +       }
40309 +
40310 +       /** Overcurrent Change Interrupt */
40311 +       if (hprt0.b.prtovrcurrchng) {
40312 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
40313 +                           "Port Overcurrent Changed--\n", hprt0.d32);
40314 +               dwc_otg_hcd->flags.b.port_over_current_change = 1;
40315 +               hprt0_modify.b.prtovrcurrchng = 1;
40316 +               retval |= 1;
40317 +       }
40318 +
40319 +       /* Clear Port Interrupts */
40320 +       DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40321 +
40322 +       return retval;
40323 +}
40324 +
40325 +/** This interrupt indicates that one or more host channels has a pending
40326 + * interrupt. There are multiple conditions that can cause each host channel
40327 + * interrupt. This function determines which conditions have occurred for each
40328 + * host channel interrupt and handles them appropriately. */
40329 +int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40330 +{
40331 +       int i;
40332 +       int retval = 0;
40333 +       haint_data_t haint;
40334 +
40335 +       /* Clear appropriate bits in HCINTn to clear the interrupt bit in
40336 +        * GINTSTS */
40337 +
40338 +       haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
40339 +
40340 +       for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
40341 +               if (haint.b2.chint & (1 << i)) {
40342 +                       retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
40343 +               }
40344 +       }
40345 +
40346 +       return retval;
40347 +}
40348 +
40349 +/**
40350 + * Gets the actual length of a transfer after the transfer halts. _halt_status
40351 + * holds the reason for the halt.
40352 + *
40353 + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,
40354 + * *short_read is set to 1 upon return if less than the requested
40355 + * number of bytes were transferred. Otherwise, *short_read is set to 0 upon
40356 + * return. short_read may also be NULL on entry, in which case it remains
40357 + * unchanged.
40358 + */
40359 +static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
40360 +                                      dwc_otg_hc_regs_t * hc_regs,
40361 +                                      dwc_otg_qtd_t * qtd,
40362 +                                      dwc_otg_halt_status_e halt_status,
40363 +                                      int *short_read)
40364 +{
40365 +       hctsiz_data_t hctsiz;
40366 +       uint32_t length;
40367 +
40368 +       if (short_read != NULL) {
40369 +               *short_read = 0;
40370 +       }
40371 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40372 +
40373 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
40374 +               if (hc->ep_is_in) {
40375 +                       length = hc->xfer_len - hctsiz.b.xfersize;
40376 +                       if (short_read != NULL) {
40377 +                               *short_read = (hctsiz.b.xfersize != 0);
40378 +                       }
40379 +               } else if (hc->qh->do_split) {
40380 +                       length = qtd->ssplit_out_xfer_count;
40381 +               } else {
40382 +                       length = hc->xfer_len;
40383 +               }
40384 +       } else {
40385 +               /*
40386 +                * Must use the hctsiz.pktcnt field to determine how much data
40387 +                * has been transferred. This field reflects the number of
40388 +                * packets that have been transferred via the USB. This is
40389 +                * always an integral number of packets if the transfer was
40390 +                * halted before its normal completion. (Can't use the
40391 +                * hctsiz.xfersize field because that reflects the number of
40392 +                * bytes transferred via the AHB, not the USB).
40393 +                */
40394 +               length =
40395 +                   (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
40396 +       }
40397 +
40398 +       return length;
40399 +}
40400 +
40401 +/**
40402 + * Updates the state of the URB after a Transfer Complete interrupt on the
40403 + * host channel. Updates the actual_length field of the URB based on the
40404 + * number of bytes transferred via the host channel. Sets the URB status
40405 + * if the data transfer is finished.
40406 + *
40407 + * @return 1 if the data transfer specified by the URB is completely finished,
40408 + * 0 otherwise.
40409 + */
40410 +static int update_urb_state_xfer_comp(dwc_hc_t * hc,
40411 +                                     dwc_otg_hc_regs_t * hc_regs,
40412 +                                     dwc_otg_hcd_urb_t * urb,
40413 +                                     dwc_otg_qtd_t * qtd)
40414 +{
40415 +       int xfer_done = 0;
40416 +       int short_read = 0;
40417 +
40418 +       int xfer_length;
40419 +
40420 +       xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,
40421 +                                            DWC_OTG_HC_XFER_COMPLETE,
40422 +                                            &short_read);
40423 +
40424 +
40425 +       /* non DWORD-aligned buffer case handling. */
40426 +       if (hc->align_buff && xfer_length && hc->ep_is_in) {
40427 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
40428 +                          xfer_length);
40429 +       }
40430 +
40431 +       urb->actual_length += xfer_length;
40432 +
40433 +       if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
40434 +           (urb->flags & URB_SEND_ZERO_PACKET)
40435 +           && (urb->actual_length == urb->length)
40436 +           && !(urb->length % hc->max_packet)) {
40437 +               xfer_done = 0;
40438 +       } else if (short_read || urb->actual_length >= urb->length) {
40439 +               xfer_done = 1;
40440 +               urb->status = 0;
40441 +       }
40442 +       
40443 +#ifdef DEBUG
40444 +       {
40445 +               hctsiz_data_t hctsiz;
40446 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40447 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
40448 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
40449 +                           hc->hc_num);
40450 +               DWC_DEBUGPL(DBG_HCDV, "  hc->xfer_len %d\n", hc->xfer_len);
40451 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.xfersize %d\n",
40452 +                           hctsiz.b.xfersize);
40453 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
40454 +                           urb->length);
40455 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
40456 +                           urb->actual_length);
40457 +               DWC_DEBUGPL(DBG_HCDV, "  short_read %d, xfer_done %d\n",
40458 +                           short_read, xfer_done);
40459 +       }
40460 +#endif
40461 +
40462 +       return xfer_done;
40463 +}
40464 +
40465 +/*
40466 + * Save the starting data toggle for the next transfer. The data toggle is
40467 + * saved in the QH for non-control transfers and it's saved in the QTD for
40468 + * control transfers.
40469 + */
40470 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
40471 +                            dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
40472 +{
40473 +       hctsiz_data_t hctsiz;
40474 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40475 +
40476 +       if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
40477 +               dwc_otg_qh_t *qh = hc->qh;
40478 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40479 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
40480 +               } else {
40481 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA1;
40482 +               }
40483 +       } else {
40484 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40485 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
40486 +               } else {
40487 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
40488 +               }
40489 +       }
40490 +}
40491 +
40492 +/**
40493 + * Updates the state of an Isochronous URB when the transfer is stopped for
40494 + * any reason. The fields of the current entry in the frame descriptor array
40495 + * are set based on the transfer state and the input _halt_status. Completes
40496 + * the Isochronous URB if all the URB frames have been completed.
40497 + *
40498 + * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be
40499 + * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.
40500 + */
40501 +static dwc_otg_halt_status_e
40502 +update_isoc_urb_state(dwc_otg_hcd_t * hcd,
40503 +                     dwc_hc_t * hc,
40504 +                     dwc_otg_hc_regs_t * hc_regs,
40505 +                     dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40506 +{
40507 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40508 +       dwc_otg_halt_status_e ret_val = halt_status;
40509 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40510 +
40511 +       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
40512 +       switch (halt_status) {
40513 +       case DWC_OTG_HC_XFER_COMPLETE:
40514 +               frame_desc->status = 0;
40515 +               frame_desc->actual_length =
40516 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40517 +
40518 +               /* non DWORD-aligned buffer case handling. */
40519 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40520 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40521 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
40522 +               }
40523 +               
40524 +               break;
40525 +       case DWC_OTG_HC_XFER_FRAME_OVERRUN:
40526 +               urb->error_count++;
40527 +               if (hc->ep_is_in) {
40528 +                       frame_desc->status = -DWC_E_NO_STREAM_RES;
40529 +               } else {
40530 +                       frame_desc->status = -DWC_E_COMMUNICATION;
40531 +               }
40532 +               frame_desc->actual_length = 0;
40533 +               break;
40534 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
40535 +               urb->error_count++;
40536 +               frame_desc->status = -DWC_E_OVERFLOW;
40537 +               /* Don't need to update actual_length in this case. */
40538 +               break;
40539 +       case DWC_OTG_HC_XFER_XACT_ERR:
40540 +               urb->error_count++;
40541 +               frame_desc->status = -DWC_E_PROTOCOL;
40542 +               frame_desc->actual_length =
40543 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40544 +
40545 +               /* non DWORD-aligned buffer case handling. */
40546 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40547 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40548 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
40549 +               }
40550 +               /* Skip whole frame */
40551 +               if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&
40552 +                   hc->ep_is_in && hcd->core_if->dma_enable) {
40553 +                       qtd->complete_split = 0;
40554 +                       qtd->isoc_split_offset = 0;
40555 +               }
40556 +
40557 +               break;
40558 +       default:
40559 +               DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
40560 +               break;
40561 +       }
40562 +       if (++qtd->isoc_frame_index == urb->packet_count) {
40563 +               /*
40564 +                * urb->status is not used for isoc transfers.
40565 +                * The individual frame_desc statuses are used instead.
40566 +                */
40567 +               hcd->fops->complete(hcd, urb->priv, urb, 0);
40568 +               ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
40569 +       } else {
40570 +               ret_val = DWC_OTG_HC_XFER_COMPLETE;
40571 +       }
40572 +       return ret_val;
40573 +}
40574 +
40575 +/**
40576 + * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
40577 + * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
40578 + * still linked to the QH, the QH is added to the end of the inactive
40579 + * non-periodic schedule. For periodic QHs, removes the QH from the periodic
40580 + * schedule if no more QTDs are linked to the QH.
40581 + */
40582 +static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
40583 +{
40584 +       int continue_split = 0;
40585 +       dwc_otg_qtd_t *qtd;
40586 +
40587 +       DWC_DEBUGPL(DBG_HCDV, "  %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
40588 +
40589 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
40590 +
40591 +       if (qtd->complete_split) {
40592 +               continue_split = 1;
40593 +       } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
40594 +                  qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
40595 +               continue_split = 1;
40596 +       }
40597 +
40598 +       if (free_qtd) {
40599 +               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
40600 +               continue_split = 0;
40601 +       }
40602 +
40603 +       qh->channel = NULL;
40604 +       dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
40605 +}
40606 +
40607 +/**
40608 + * Releases a host channel for use by other transfers. Attempts to select and
40609 + * queue more transactions since at least one host channel is available.
40610 + *
40611 + * @param hcd The HCD state structure.
40612 + * @param hc The host channel to release.
40613 + * @param qtd The QTD associated with the host channel. This QTD may be freed
40614 + * if the transfer is complete or an error has occurred.
40615 + * @param halt_status Reason the channel is being released. This status
40616 + * determines the actions taken by this function.
40617 + */
40618 +static void release_channel(dwc_otg_hcd_t * hcd,
40619 +                           dwc_hc_t * hc,
40620 +                           dwc_otg_qtd_t * qtd,
40621 +                           dwc_otg_halt_status_e halt_status)
40622 +{
40623 +       dwc_otg_transaction_type_e tr_type;
40624 +       int free_qtd;
40625 +       dwc_irqflags_t flags;
40626 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
40627 +
40628 +       DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d, xfer_len %d\n",
40629 +                   __func__, hc->hc_num, halt_status, hc->xfer_len);
40630 +
40631 +       switch (halt_status) {
40632 +       case DWC_OTG_HC_XFER_URB_COMPLETE:
40633 +               free_qtd = 1;
40634 +               break;
40635 +       case DWC_OTG_HC_XFER_AHB_ERR:
40636 +       case DWC_OTG_HC_XFER_STALL:
40637 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
40638 +               free_qtd = 1;
40639 +               break;
40640 +       case DWC_OTG_HC_XFER_XACT_ERR:
40641 +               if (qtd->error_count >= 3) {
40642 +                       DWC_DEBUGPL(DBG_HCDV,
40643 +                                   "  Complete URB with transaction error\n");
40644 +                       free_qtd = 1;
40645 +                       qtd->urb->status = -DWC_E_PROTOCOL;
40646 +                       hcd->fops->complete(hcd, qtd->urb->priv,
40647 +                                           qtd->urb, -DWC_E_PROTOCOL);
40648 +               } else {
40649 +                       free_qtd = 0;
40650 +               }
40651 +               break;
40652 +       case DWC_OTG_HC_XFER_URB_DEQUEUE:
40653 +               /*
40654 +                * The QTD has already been removed and the QH has been
40655 +                * deactivated. Don't want to do anything except release the
40656 +                * host channel and try to queue more transfers.
40657 +                */
40658 +               goto cleanup;
40659 +       case DWC_OTG_HC_XFER_NO_HALT_STATUS:
40660 +               free_qtd = 0;
40661 +               break;
40662 +       case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:
40663 +               DWC_DEBUGPL(DBG_HCDV,
40664 +                       "  Complete URB with I/O error\n");
40665 +               free_qtd = 1;
40666 +               qtd->urb->status = -DWC_E_IO;
40667 +               hcd->fops->complete(hcd, qtd->urb->priv,
40668 +                       qtd->urb, -DWC_E_IO);
40669 +               break;
40670 +       default:
40671 +               free_qtd = 0;
40672 +               break;
40673 +       }
40674 +
40675 +       deactivate_qh(hcd, hc->qh, free_qtd);
40676 +
40677 +cleanup:
40678 +       /*
40679 +        * Release the host channel for use by other transfers. The cleanup
40680 +        * function clears the channel interrupt enables and conditions, so
40681 +        * there's no need to clear the Channel Halted interrupt separately.
40682 +        */
40683 +       dwc_otg_hc_cleanup(hcd->core_if, hc);
40684 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
40685 +
40686 +       if (!microframe_schedule) {
40687 +               switch (hc->ep_type) {
40688 +               case DWC_OTG_EP_TYPE_CONTROL:
40689 +               case DWC_OTG_EP_TYPE_BULK:
40690 +                       hcd->non_periodic_channels--;
40691 +                       break;
40692 +
40693 +               default:
40694 +                       /*
40695 +                        * Don't release reservations for periodic channels here.
40696 +                        * That's done when a periodic transfer is descheduled (i.e.
40697 +                        * when the QH is removed from the periodic schedule).
40698 +                        */
40699 +                       break;
40700 +               }
40701 +       } else {
40702 +
40703 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
40704 +               hcd->available_host_channels++;
40705 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
40706 +       }
40707 +
40708 +       /* Try to queue more transfers now that there's a free channel. */
40709 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
40710 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
40711 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
40712 +       }
40713 +       DWC_SPINLOCK_FREE(channel_lock);
40714 +}
40715 +
40716 +/**
40717 + * Halts a host channel. If the channel cannot be halted immediately because
40718 + * the request queue is full, this function ensures that the FIFO empty
40719 + * interrupt for the appropriate queue is enabled so that the halt request can
40720 + * be queued when there is space in the request queue.
40721 + *
40722 + * This function may also be called in DMA mode. In that case, the channel is
40723 + * simply released since the core always halts the channel automatically in
40724 + * DMA mode.
40725 + */
40726 +static void halt_channel(dwc_otg_hcd_t * hcd,
40727 +                        dwc_hc_t * hc,
40728 +                        dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40729 +{
40730 +       if (hcd->core_if->dma_enable) {
40731 +               release_channel(hcd, hc, qtd, halt_status);
40732 +               return;
40733 +       }
40734 +
40735 +       /* Slave mode processing... */
40736 +       dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
40737 +
40738 +       if (hc->halt_on_queue) {
40739 +               gintmsk_data_t gintmsk = {.d32 = 0 };
40740 +               dwc_otg_core_global_regs_t *global_regs;
40741 +               global_regs = hcd->core_if->core_global_regs;
40742 +
40743 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
40744 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
40745 +                       /*
40746 +                        * Make sure the Non-periodic Tx FIFO empty interrupt
40747 +                        * is enabled so that the non-periodic schedule will
40748 +                        * be processed.
40749 +                        */
40750 +                       gintmsk.b.nptxfempty = 1;
40751 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40752 +               } else {
40753 +                       /*
40754 +                        * Move the QH from the periodic queued schedule to
40755 +                        * the periodic assigned schedule. This allows the
40756 +                        * halt to be queued when the periodic schedule is
40757 +                        * processed.
40758 +                        */
40759 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
40760 +                                          &hc->qh->qh_list_entry);
40761 +
40762 +                       /*
40763 +                        * Make sure the Periodic Tx FIFO Empty interrupt is
40764 +                        * enabled so that the periodic schedule will be
40765 +                        * processed.
40766 +                        */
40767 +                       gintmsk.b.ptxfempty = 1;
40768 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40769 +               }
40770 +       }
40771 +}
40772 +
40773 +/**
40774 + * Performs common cleanup for non-periodic transfers after a Transfer
40775 + * Complete interrupt. This function should be called after any endpoint type
40776 + * specific handling is finished to release the host channel.
40777 + */
40778 +static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
40779 +                                      dwc_hc_t * hc,
40780 +                                      dwc_otg_hc_regs_t * hc_regs,
40781 +                                      dwc_otg_qtd_t * qtd,
40782 +                                      dwc_otg_halt_status_e halt_status)
40783 +{
40784 +       hcint_data_t hcint;
40785 +
40786 +       qtd->error_count = 0;
40787 +
40788 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
40789 +       if (hcint.b.nyet) {
40790 +               /*
40791 +                * Got a NYET on the last transaction of the transfer. This
40792 +                * means that the endpoint should be in the PING state at the
40793 +                * beginning of the next transfer.
40794 +                */
40795 +               hc->qh->ping_state = 1;
40796 +               clear_hc_int(hc_regs, nyet);
40797 +       }
40798 +
40799 +       /*
40800 +        * Always halt and release the host channel to make it available for
40801 +        * more transfers. There may still be more phases for a control
40802 +        * transfer or more data packets for a bulk transfer at this point,
40803 +        * but the host channel is still halted. A channel will be reassigned
40804 +        * to the transfer when the non-periodic schedule is processed after
40805 +        * the channel is released. This allows transactions to be queued
40806 +        * properly via dwc_otg_hcd_queue_transactions, which also enables the
40807 +        * Tx FIFO Empty interrupt if necessary.
40808 +        */
40809 +       if (hc->ep_is_in) {
40810 +               /*
40811 +                * IN transfers in Slave mode require an explicit disable to
40812 +                * halt the channel. (In DMA mode, this call simply releases
40813 +                * the channel.)
40814 +                */
40815 +               halt_channel(hcd, hc, qtd, halt_status);
40816 +       } else {
40817 +               /*
40818 +                * The channel is automatically disabled by the core for OUT
40819 +                * transfers in Slave mode.
40820 +                */
40821 +               release_channel(hcd, hc, qtd, halt_status);
40822 +       }
40823 +}
40824 +
40825 +/**
40826 + * Performs common cleanup for periodic transfers after a Transfer Complete
40827 + * interrupt. This function should be called after any endpoint type specific
40828 + * handling is finished to release the host channel.
40829 + */
40830 +static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
40831 +                                  dwc_hc_t * hc,
40832 +                                  dwc_otg_hc_regs_t * hc_regs,
40833 +                                  dwc_otg_qtd_t * qtd,
40834 +                                  dwc_otg_halt_status_e halt_status)
40835 +{
40836 +       hctsiz_data_t hctsiz;
40837 +       qtd->error_count = 0;
40838 +
40839 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40840 +       if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
40841 +               /* Core halts channel in these cases. */
40842 +               release_channel(hcd, hc, qtd, halt_status);
40843 +       } else {
40844 +               /* Flush any outstanding requests from the Tx queue. */
40845 +               halt_channel(hcd, hc, qtd, halt_status);
40846 +       }
40847 +}
40848 +
40849 +static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
40850 +                                            dwc_hc_t * hc,
40851 +                                            dwc_otg_hc_regs_t * hc_regs,
40852 +                                            dwc_otg_qtd_t * qtd)
40853 +{
40854 +       uint32_t len;
40855 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40856 +       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
40857 +
40858 +       len = get_actual_xfer_length(hc, hc_regs, qtd,
40859 +                                    DWC_OTG_HC_XFER_COMPLETE, NULL);
40860 +
40861 +       if (!len) {
40862 +               qtd->complete_split = 0;
40863 +               qtd->isoc_split_offset = 0;
40864 +               return 0;
40865 +       }
40866 +       frame_desc->actual_length += len;
40867 +
40868 +       if (hc->align_buff && len)
40869 +               dwc_memcpy(qtd->urb->buf + frame_desc->offset +
40870 +                          qtd->isoc_split_offset, hc->qh->dw_align_buf, len);
40871 +       qtd->isoc_split_offset += len;
40872 +
40873 +       if (frame_desc->length == frame_desc->actual_length) {
40874 +               frame_desc->status = 0;
40875 +               qtd->isoc_frame_index++;
40876 +               qtd->complete_split = 0;
40877 +               qtd->isoc_split_offset = 0;
40878 +       }
40879 +
40880 +       if (qtd->isoc_frame_index == qtd->urb->packet_count) {
40881 +               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
40882 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
40883 +       } else {
40884 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
40885 +       }
40886 +
40887 +       return 1;               /* Indicates that channel released */
40888 +}
40889 +
40890 +/**
40891 + * Handles a host channel Transfer Complete interrupt. This handler may be
40892 + * called in either DMA mode or Slave mode.
40893 + */
40894 +static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
40895 +                                      dwc_hc_t * hc,
40896 +                                      dwc_otg_hc_regs_t * hc_regs,
40897 +                                      dwc_otg_qtd_t * qtd)
40898 +{
40899 +       int urb_xfer_done;
40900 +       dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
40901 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40902 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
40903 +
40904 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
40905 +                   "Transfer Complete--\n", hc->hc_num);
40906 +
40907 +       if (hcd->core_if->dma_desc_enable) {
40908 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
40909 +               if (pipe_type == UE_ISOCHRONOUS) {
40910 +                       /* Do not disable the interrupt, just clear it */
40911 +                       clear_hc_int(hc_regs, xfercomp);
40912 +                       return 1;
40913 +               }
40914 +               goto handle_xfercomp_done;
40915 +       }
40916 +
40917 +       /*
40918 +        * Handle xfer complete on CSPLIT.
40919 +        */
40920 +
40921 +       if (hc->qh->do_split) {
40922 +               if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in
40923 +                   && hcd->core_if->dma_enable) {
40924 +                       if (qtd->complete_split
40925 +                           && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs,
40926 +                                                            qtd))
40927 +                               goto handle_xfercomp_done;
40928 +               } else {
40929 +                       qtd->complete_split = 0;
40930 +               }
40931 +       }
40932 +
40933 +       /* Update the QTD and URB states. */
40934 +       switch (pipe_type) {
40935 +       case UE_CONTROL:
40936 +               switch (qtd->control_phase) {
40937 +               case DWC_OTG_CONTROL_SETUP:
40938 +                       if (urb->length > 0) {
40939 +                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
40940 +                       } else {
40941 +                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
40942 +                       }
40943 +                       DWC_DEBUGPL(DBG_HCDV,
40944 +                                   "  Control setup transaction done\n");
40945 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
40946 +                       break;
40947 +               case DWC_OTG_CONTROL_DATA:{
40948 +                               urb_xfer_done =
40949 +                                   update_urb_state_xfer_comp(hc, hc_regs, urb,
40950 +                                                              qtd);
40951 +                               if (urb_xfer_done) {
40952 +                                       qtd->control_phase =
40953 +                                           DWC_OTG_CONTROL_STATUS;
40954 +                                       DWC_DEBUGPL(DBG_HCDV,
40955 +                                                   "  Control data transfer done\n");
40956 +                               } else {
40957 +                                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40958 +                               }
40959 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
40960 +                               break;
40961 +                       }
40962 +               case DWC_OTG_CONTROL_STATUS:
40963 +                       DWC_DEBUGPL(DBG_HCDV, "  Control transfer complete\n");
40964 +                       if (urb->status == -DWC_E_IN_PROGRESS) {
40965 +                               urb->status = 0;
40966 +                       }
40967 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40968 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40969 +                       break;
40970 +               }
40971 +
40972 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40973 +               break;
40974 +       case UE_BULK:
40975 +               DWC_DEBUGPL(DBG_HCDV, "  Bulk transfer complete\n");
40976 +               urb_xfer_done =
40977 +                   update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40978 +               if (urb_xfer_done) {
40979 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40980 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40981 +               } else {
40982 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
40983 +               }
40984 +
40985 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40986 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40987 +               break;
40988 +       case UE_INTERRUPT:
40989 +               DWC_DEBUGPL(DBG_HCDV, "  Interrupt transfer complete\n");
40990 +               urb_xfer_done =
40991 +                       update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40992 +
40993 +               /*
40994 +                * Interrupt URB is done on the first transfer complete
40995 +                * interrupt.
40996 +                */
40997 +               if (urb_xfer_done) {
40998 +                               hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40999 +                               halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
41000 +               } else {
41001 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
41002 +               }
41003 +
41004 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41005 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
41006 +               break;
41007 +       case UE_ISOCHRONOUS:
41008 +               DWC_DEBUGPL(DBG_HCDV, "  Isochronous transfer complete\n");
41009 +               if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
41010 +                       halt_status =
41011 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41012 +                                                 DWC_OTG_HC_XFER_COMPLETE);
41013 +               }
41014 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
41015 +               break;
41016 +       }
41017 +
41018 +handle_xfercomp_done:
41019 +       disable_hc_int(hc_regs, xfercompl);
41020 +
41021 +       return 1;
41022 +}
41023 +
41024 +/**
41025 + * Handles a host channel STALL interrupt. This handler may be called in
41026 + * either DMA mode or Slave mode.
41027 + */
41028 +static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
41029 +                                   dwc_hc_t * hc,
41030 +                                   dwc_otg_hc_regs_t * hc_regs,
41031 +                                   dwc_otg_qtd_t * qtd)
41032 +{
41033 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
41034 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
41035 +
41036 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
41037 +                   "STALL Received--\n", hc->hc_num);
41038 +
41039 +       if (hcd->core_if->dma_desc_enable) {
41040 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
41041 +               goto handle_stall_done;
41042 +       }
41043 +
41044 +       if (pipe_type == UE_CONTROL) {
41045 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
41046 +       }
41047 +
41048 +       if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
41049 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
41050 +               /*
41051 +                * USB protocol requires resetting the data toggle for bulk
41052 +                * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
41053 +                * setup command is issued to the endpoint. Anticipate the
41054 +                * CLEAR_FEATURE command since a STALL has occurred and reset
41055 +                * the data toggle now.
41056 +                */
41057 +               hc->qh->data_toggle = 0;
41058 +       }
41059 +
41060 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
41061 +
41062 +handle_stall_done:
41063 +       disable_hc_int(hc_regs, stall);
41064 +
41065 +       return 1;
41066 +}
41067 +
41068 +/*
41069 + * Updates the state of the URB when a transfer has been stopped due to an
41070 + * abnormal condition before the transfer completes. Modifies the
41071 + * actual_length field of the URB to reflect the number of bytes that have
41072 + * actually been transferred via the host channel.
41073 + */
41074 +static void update_urb_state_xfer_intr(dwc_hc_t * hc,
41075 +                                      dwc_otg_hc_regs_t * hc_regs,
41076 +                                      dwc_otg_hcd_urb_t * urb,
41077 +                                      dwc_otg_qtd_t * qtd,
41078 +                                      dwc_otg_halt_status_e halt_status)
41079 +{
41080 +       uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
41081 +                                                           halt_status, NULL);
41082 +       /* non DWORD-aligned buffer case handling. */
41083 +       if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
41084 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
41085 +                          bytes_transferred);
41086 +       }
41087 +
41088 +       urb->actual_length += bytes_transferred;
41089 +
41090 +#ifdef DEBUG
41091 +       {
41092 +               hctsiz_data_t hctsiz;
41093 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41094 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
41095 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
41096 +                           hc->hc_num);
41097 +               DWC_DEBUGPL(DBG_HCDV, "  hc->start_pkt_count %d\n",
41098 +                           hc->start_pkt_count);
41099 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
41100 +               DWC_DEBUGPL(DBG_HCDV, "  hc->max_packet %d\n", hc->max_packet);
41101 +               DWC_DEBUGPL(DBG_HCDV, "  bytes_transferred %d\n",
41102 +                           bytes_transferred);
41103 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
41104 +                           urb->actual_length);
41105 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
41106 +                           urb->length);
41107 +       }
41108 +#endif
41109 +}
41110 +
41111 +/**
41112 + * Handles a host channel NAK interrupt. This handler may be called in either
41113 + * DMA mode or Slave mode.
41114 + */
41115 +static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
41116 +                                 dwc_hc_t * hc,
41117 +                                 dwc_otg_hc_regs_t * hc_regs,
41118 +                                 dwc_otg_qtd_t * qtd)
41119 +{
41120 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41121 +                   "NAK Received--\n", hc->hc_num);
41122 +
41123 +       /*
41124 +        * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
41125 +        * interrupt.  Re-start the SSPLIT transfer.
41126 +        */
41127 +       if (hc->do_split) {
41128 +               if (hc->complete_split) {
41129 +                       qtd->error_count = 0;
41130 +               }
41131 +               qtd->complete_split = 0;
41132 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41133 +               goto handle_nak_done;
41134 +       }
41135 +
41136 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41137 +       case UE_CONTROL:
41138 +       case UE_BULK:
41139 +               if (hcd->core_if->dma_enable && hc->ep_is_in) {
41140 +                       /*
41141 +                        * NAK interrupts are enabled on bulk/control IN
41142 +                        * transfers in DMA mode for the sole purpose of
41143 +                        * resetting the error count after a transaction error
41144 +                        * occurs. The core will continue transferring data.
41145 +                        */
41146 +                       qtd->error_count = 0;
41147 +                       goto handle_nak_done;
41148 +               }
41149 +
41150 +               /*
41151 +                * NAK interrupts normally occur during OUT transfers in DMA
41152 +                * or Slave mode. For IN transfers, more requests will be
41153 +                * queued as request queue space is available.
41154 +                */
41155 +               qtd->error_count = 0;
41156 +
41157 +               if (!hc->qh->ping_state) {
41158 +                       update_urb_state_xfer_intr(hc, hc_regs,
41159 +                                                  qtd->urb, qtd,
41160 +                                                  DWC_OTG_HC_XFER_NAK);
41161 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41162 +
41163 +                       if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
41164 +                               hc->qh->ping_state = 1;
41165 +               }
41166 +
41167 +               /*
41168 +                * Halt the channel so the transfer can be re-started from
41169 +                * the appropriate point or the PING protocol will
41170 +                * start/continue.
41171 +                */
41172 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41173 +               break;
41174 +       case UE_INTERRUPT:
41175 +               qtd->error_count = 0;
41176 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41177 +               break;
41178 +       case UE_ISOCHRONOUS:
41179 +               /* Should never get called for isochronous transfers. */
41180 +               DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
41181 +               break;
41182 +       }
41183 +
41184 +handle_nak_done:
41185 +       disable_hc_int(hc_regs, nak);
41186 +
41187 +       return 1;
41188 +}
41189 +
41190 +/**
41191 + * Handles a host channel ACK interrupt. This interrupt is enabled when
41192 + * performing the PING protocol in Slave mode, when errors occur during
41193 + * either Slave mode or DMA mode, and during Start Split transactions.
41194 + */
41195 +static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
41196 +                                 dwc_hc_t * hc,
41197 +                                 dwc_otg_hc_regs_t * hc_regs,
41198 +                                 dwc_otg_qtd_t * qtd)
41199 +{
41200 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41201 +                   "ACK Received--\n", hc->hc_num);
41202 +
41203 +       if (hc->do_split) {
41204 +               /*
41205 +                * Handle ACK on SSPLIT.
41206 +                * ACK should not occur in CSPLIT.
41207 +                */
41208 +               if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
41209 +                       qtd->ssplit_out_xfer_count = hc->xfer_len;
41210 +               }
41211 +               if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
41212 +                       /* Don't need complete for isochronous out transfers. */
41213 +                       qtd->complete_split = 1;
41214 +               }
41215 +
41216 +               /* ISOC OUT */
41217 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41218 +                       switch (hc->xact_pos) {
41219 +                       case DWC_HCSPLIT_XACTPOS_ALL:
41220 +                               break;
41221 +                       case DWC_HCSPLIT_XACTPOS_END:
41222 +                               qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
41223 +                               qtd->isoc_split_offset = 0;
41224 +                               break;
41225 +                       case DWC_HCSPLIT_XACTPOS_BEGIN:
41226 +                       case DWC_HCSPLIT_XACTPOS_MID:
41227 +                               /*
41228 +                                * For BEGIN or MID, calculate the length for
41229 +                                * the next microframe to determine the correct
41230 +                                * SSPLIT token, either MID or END.
41231 +                                */
41232 +                               {
41233 +                                       struct dwc_otg_hcd_iso_packet_desc
41234 +                                       *frame_desc;
41235 +
41236 +                                       frame_desc =
41237 +                                           &qtd->urb->
41238 +                                           iso_descs[qtd->isoc_frame_index];
41239 +                                       qtd->isoc_split_offset += 188;
41240 +
41241 +                                       if ((frame_desc->length -
41242 +                                            qtd->isoc_split_offset) <= 188) {
41243 +                                               qtd->isoc_split_pos =
41244 +                                                   DWC_HCSPLIT_XACTPOS_END;
41245 +                                       } else {
41246 +                                               qtd->isoc_split_pos =
41247 +                                                   DWC_HCSPLIT_XACTPOS_MID;
41248 +                                       }
41249 +
41250 +                               }
41251 +                               break;
41252 +                       }
41253 +               } else {
41254 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41255 +               }
41256 +       } else {
41257 +               qtd->error_count = 0;
41258 +
41259 +               if (hc->qh->ping_state) {
41260 +                       hc->qh->ping_state = 0;
41261 +                       /*
41262 +                        * Halt the channel so the transfer can be re-started
41263 +                        * from the appropriate point. This only happens in
41264 +                        * Slave mode. In DMA mode, the ping_state is cleared
41265 +                        * when the transfer is started because the core
41266 +                        * automatically executes the PING, then the transfer.
41267 +                        */
41268 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41269 +               }
41270 +       }
41271 +
41272 +       /*
41273 +        * If the ACK occurred when _not_ in the PING state, let the channel
41274 +        * continue transferring data after clearing the error count.
41275 +        */
41276 +
41277 +       disable_hc_int(hc_regs, ack);
41278 +
41279 +       return 1;
41280 +}
41281 +
41282 +/**
41283 + * Handles a host channel NYET interrupt. This interrupt should only occur on
41284 + * Bulk and Control OUT endpoints and for complete split transactions. If a
41285 + * NYET occurs at the same time as a Transfer Complete interrupt, it is
41286 + * handled in the xfercomp interrupt handler, not here. This handler may be
41287 + * called in either DMA mode or Slave mode.
41288 + */
41289 +static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
41290 +                                  dwc_hc_t * hc,
41291 +                                  dwc_otg_hc_regs_t * hc_regs,
41292 +                                  dwc_otg_qtd_t * qtd)
41293 +{
41294 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41295 +                   "NYET Received--\n", hc->hc_num);
41296 +
41297 +       /*
41298 +        * NYET on CSPLIT
41299 +        * re-do the CSPLIT immediately on non-periodic
41300 +        */
41301 +       if (hc->do_split && hc->complete_split) {
41302 +               if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
41303 +                   && hcd->core_if->dma_enable) {
41304 +                       qtd->complete_split = 0;
41305 +                       qtd->isoc_split_offset = 0;
41306 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
41307 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
41308 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);    
41309 +                       }
41310 +                       else
41311 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);  
41312 +                       goto handle_nyet_done;
41313 +               }
41314 +               
41315 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41316 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41317 +                       int frnum = dwc_otg_hcd_get_frame_number(hcd);
41318 +
41319 +                       if (dwc_full_frame_num(frnum) !=
41320 +                           dwc_full_frame_num(hc->qh->sched_frame)) {
41321 +                               /*
41322 +                                * No longer in the same full speed frame.
41323 +                                * Treat this as a transaction error.
41324 +                                */
41325 +#if 0
41326 +                               /** @todo Fix system performance so this can
41327 +                                * be treated as an error. Right now complete
41328 +                                * splits cannot be scheduled precisely enough
41329 +                                * due to other system activity, so this error
41330 +                                * occurs regularly in Slave mode.
41331 +                                */
41332 +                               qtd->error_count++;
41333 +#endif
41334 +                               qtd->complete_split = 0;
41335 +                               halt_channel(hcd, hc, qtd,
41336 +                                            DWC_OTG_HC_XFER_XACT_ERR);
41337 +                               /** @todo add support for isoc release */
41338 +                               goto handle_nyet_done;
41339 +                       }
41340 +               }
41341 +
41342 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41343 +               goto handle_nyet_done;
41344 +       }
41345 +
41346 +       hc->qh->ping_state = 1;
41347 +       qtd->error_count = 0;
41348 +
41349 +       update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
41350 +                                  DWC_OTG_HC_XFER_NYET);
41351 +       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41352 +
41353 +       /*
41354 +        * Halt the channel and re-start the transfer so the PING
41355 +        * protocol will start.
41356 +        */
41357 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41358 +
41359 +handle_nyet_done:
41360 +       disable_hc_int(hc_regs, nyet);
41361 +       return 1;
41362 +}
41363 +
41364 +/**
41365 + * Handles a host channel babble interrupt. This handler may be called in
41366 + * either DMA mode or Slave mode.
41367 + */
41368 +static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
41369 +                                    dwc_hc_t * hc,
41370 +                                    dwc_otg_hc_regs_t * hc_regs,
41371 +                                    dwc_otg_qtd_t * qtd)
41372 +{
41373 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41374 +                   "Babble Error--\n", hc->hc_num);
41375 +
41376 +       if (hcd->core_if->dma_desc_enable) {
41377 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41378 +                                              DWC_OTG_HC_XFER_BABBLE_ERR);
41379 +               goto handle_babble_done;
41380 +       }
41381 +
41382 +       if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
41383 +               hcd->fops->complete(hcd, qtd->urb->priv,
41384 +                                   qtd->urb, -DWC_E_OVERFLOW);
41385 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
41386 +       } else {
41387 +               dwc_otg_halt_status_e halt_status;
41388 +               halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41389 +                                                   DWC_OTG_HC_XFER_BABBLE_ERR);
41390 +               halt_channel(hcd, hc, qtd, halt_status);
41391 +       }
41392 +
41393 +handle_babble_done:
41394 +       disable_hc_int(hc_regs, bblerr);
41395 +       return 1;
41396 +}
41397 +
41398 +/**
41399 + * Handles a host channel AHB error interrupt. This handler is only called in
41400 + * DMA mode.
41401 + */
41402 +static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
41403 +                                    dwc_hc_t * hc,
41404 +                                    dwc_otg_hc_regs_t * hc_regs,
41405 +                                    dwc_otg_qtd_t * qtd)
41406 +{
41407 +       hcchar_data_t hcchar;
41408 +       hcsplt_data_t hcsplt;
41409 +       hctsiz_data_t hctsiz;
41410 +       uint32_t hcdma;
41411 +       char *pipetype, *speed;
41412 +
41413 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
41414 +
41415 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41416 +                   "AHB Error--\n", hc->hc_num);
41417 +
41418 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41419 +       hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41420 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41421 +       hcdma = DWC_READ_REG32(&hc_regs->hcdma);
41422 +
41423 +       DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
41424 +       DWC_ERROR("  hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
41425 +       DWC_ERROR("  hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
41426 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
41427 +       DWC_ERROR("  Device address: %d\n",
41428 +                 dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
41429 +       DWC_ERROR("  Endpoint: %d, %s\n",
41430 +                 dwc_otg_hcd_get_ep_num(&urb->pipe_info),
41431 +                 (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
41432 +
41433 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
41434 +       case UE_CONTROL:
41435 +               pipetype = "CONTROL";
41436 +               break;
41437 +       case UE_BULK:
41438 +               pipetype = "BULK";
41439 +               break;
41440 +       case UE_INTERRUPT:
41441 +               pipetype = "INTERRUPT";
41442 +               break;
41443 +       case UE_ISOCHRONOUS:
41444 +               pipetype = "ISOCHRONOUS";
41445 +               break;
41446 +       default:
41447 +               pipetype = "UNKNOWN";
41448 +               break;
41449 +       }
41450 +
41451 +       DWC_ERROR("  Endpoint type: %s\n", pipetype);
41452 +
41453 +       switch (hc->speed) {
41454 +       case DWC_OTG_EP_SPEED_HIGH:
41455 +               speed = "HIGH";
41456 +               break;
41457 +       case DWC_OTG_EP_SPEED_FULL:
41458 +               speed = "FULL";
41459 +               break;
41460 +       case DWC_OTG_EP_SPEED_LOW:
41461 +               speed = "LOW";
41462 +               break;
41463 +       default:
41464 +               speed = "UNKNOWN";
41465 +               break;
41466 +       };
41467 +
41468 +       DWC_ERROR("  Speed: %s\n", speed);
41469 +
41470 +       DWC_ERROR("  Max packet size: %d\n",
41471 +                 dwc_otg_hcd_get_mps(&urb->pipe_info));
41472 +       DWC_ERROR("  Data buffer length: %d\n", urb->length);
41473 +       DWC_ERROR("  Transfer buffer: %p, Transfer DMA: %p\n",
41474 +                 urb->buf, (void *)urb->dma);
41475 +       DWC_ERROR("  Setup buffer: %p, Setup DMA: %p\n",
41476 +                 urb->setup_packet, (void *)urb->setup_dma);
41477 +       DWC_ERROR("  Interval: %d\n", urb->interval);
41478 +
41479 +       /* Core haltes the channel for Descriptor DMA mode */
41480 +       if (hcd->core_if->dma_desc_enable) {
41481 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41482 +                                              DWC_OTG_HC_XFER_AHB_ERR);
41483 +               goto handle_ahberr_done;
41484 +       }
41485 +
41486 +       hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
41487 +
41488 +       /*
41489 +        * Force a channel halt. Don't call halt_channel because that won't
41490 +        * write to the HCCHARn register in DMA mode to force the halt.
41491 +        */
41492 +       dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
41493 +handle_ahberr_done:
41494 +       disable_hc_int(hc_regs, ahberr);
41495 +       return 1;
41496 +}
41497 +
41498 +/**
41499 + * Handles a host channel transaction error interrupt. This handler may be
41500 + * called in either DMA mode or Slave mode.
41501 + */
41502 +static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
41503 +                                     dwc_hc_t * hc,
41504 +                                     dwc_otg_hc_regs_t * hc_regs,
41505 +                                     dwc_otg_qtd_t * qtd)
41506 +{
41507 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41508 +                   "Transaction Error--\n", hc->hc_num);
41509 +
41510 +       if (hcd->core_if->dma_desc_enable) {
41511 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41512 +                                              DWC_OTG_HC_XFER_XACT_ERR);
41513 +               goto handle_xacterr_done;
41514 +       }
41515 +
41516 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41517 +       case UE_CONTROL:
41518 +       case UE_BULK:
41519 +               qtd->error_count++;
41520 +               if (!hc->qh->ping_state) {
41521 +
41522 +                       update_urb_state_xfer_intr(hc, hc_regs,
41523 +                                                  qtd->urb, qtd,
41524 +                                                  DWC_OTG_HC_XFER_XACT_ERR);
41525 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41526 +                       if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
41527 +                               hc->qh->ping_state = 1;
41528 +                       }
41529 +               }
41530 +
41531 +               /*
41532 +                * Halt the channel so the transfer can be re-started from
41533 +                * the appropriate point or the PING protocol will start.
41534 +                */
41535 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41536 +               break;
41537 +       case UE_INTERRUPT:
41538 +               qtd->error_count++;
41539 +               if (hc->do_split && hc->complete_split) {
41540 +                       qtd->complete_split = 0;
41541 +               }
41542 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41543 +               break;
41544 +       case UE_ISOCHRONOUS:
41545 +               {
41546 +                       dwc_otg_halt_status_e halt_status;
41547 +                       halt_status =
41548 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41549 +                                                 DWC_OTG_HC_XFER_XACT_ERR);
41550 +
41551 +                       halt_channel(hcd, hc, qtd, halt_status);
41552 +               }
41553 +               break;
41554 +       }
41555 +handle_xacterr_done:
41556 +       disable_hc_int(hc_regs, xacterr);
41557 +
41558 +       return 1;
41559 +}
41560 +
41561 +/**
41562 + * Handles a host channel frame overrun interrupt. This handler may be called
41563 + * in either DMA mode or Slave mode.
41564 + */
41565 +static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
41566 +                                      dwc_hc_t * hc,
41567 +                                      dwc_otg_hc_regs_t * hc_regs,
41568 +                                      dwc_otg_qtd_t * qtd)
41569 +{
41570 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41571 +                   "Frame Overrun--\n", hc->hc_num);
41572 +
41573 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41574 +       case UE_CONTROL:
41575 +       case UE_BULK:
41576 +               break;
41577 +       case UE_INTERRUPT:
41578 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
41579 +               break;
41580 +       case UE_ISOCHRONOUS:
41581 +               {
41582 +                       dwc_otg_halt_status_e halt_status;
41583 +                       halt_status =
41584 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41585 +                                                 DWC_OTG_HC_XFER_FRAME_OVERRUN);
41586 +
41587 +                       halt_channel(hcd, hc, qtd, halt_status);
41588 +               }
41589 +               break;
41590 +       }
41591 +
41592 +       disable_hc_int(hc_regs, frmovrun);
41593 +
41594 +       return 1;
41595 +}
41596 +
41597 +/**
41598 + * Handles a host channel data toggle error interrupt. This handler may be
41599 + * called in either DMA mode or Slave mode.
41600 + */
41601 +static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
41602 +                                        dwc_hc_t * hc,
41603 +                                        dwc_otg_hc_regs_t * hc_regs,
41604 +                                        dwc_otg_qtd_t * qtd)
41605 +{
41606 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41607 +                   "Data Toggle Error--\n", hc->hc_num);
41608 +
41609 +       if (hc->ep_is_in) {
41610 +               qtd->error_count = 0;
41611 +       } else {
41612 +               DWC_ERROR("Data Toggle Error on OUT transfer,"
41613 +                         "channel %d\n", hc->hc_num);
41614 +       }
41615 +
41616 +       disable_hc_int(hc_regs, datatglerr);
41617 +
41618 +       return 1;
41619 +}
41620 +
41621 +#ifdef DEBUG
41622 +/**
41623 + * This function is for debug only. It checks that a valid halt status is set
41624 + * and that HCCHARn.chdis is clear. If there's a problem, corrective action is
41625 + * taken and a warning is issued.
41626 + * @return 1 if halt status is ok, 0 otherwise.
41627 + */
41628 +static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
41629 +                                dwc_hc_t * hc,
41630 +                                dwc_otg_hc_regs_t * hc_regs,
41631 +                                dwc_otg_qtd_t * qtd)
41632 +{
41633 +       hcchar_data_t hcchar;
41634 +       hctsiz_data_t hctsiz;
41635 +       hcint_data_t hcint;
41636 +       hcintmsk_data_t hcintmsk;
41637 +       hcsplt_data_t hcsplt;
41638 +
41639 +       if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
41640 +               /*
41641 +                * This code is here only as a check. This condition should
41642 +                * never happen. Ignore the halt if it does occur.
41643 +                */
41644 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41645 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41646 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41647 +               hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41648 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41649 +               DWC_WARN
41650 +                   ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
41651 +                    "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
41652 +                    "hcint 0x%08x, hcintmsk 0x%08x, "
41653 +                    "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
41654 +                    hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
41655 +                    hcintmsk.d32, hcsplt.d32, qtd->complete_split);
41656 +
41657 +               DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
41658 +                        __func__, hc->hc_num);
41659 +               DWC_WARN("\n");
41660 +               clear_hc_int(hc_regs, chhltd);
41661 +               return 0;
41662 +       }
41663 +
41664 +       /*
41665 +        * This code is here only as a check. hcchar.chdis should
41666 +        * never be set when the halt interrupt occurs. Halt the
41667 +        * channel again if it does occur.
41668 +        */
41669 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41670 +       if (hcchar.b.chdis) {
41671 +               DWC_WARN("%s: hcchar.chdis set unexpectedly, "
41672 +                        "hcchar 0x%08x, trying to halt again\n",
41673 +                        __func__, hcchar.d32);
41674 +               clear_hc_int(hc_regs, chhltd);
41675 +               hc->halt_pending = 0;
41676 +               halt_channel(hcd, hc, qtd, hc->halt_status);
41677 +               return 0;
41678 +       }
41679 +
41680 +       return 1;
41681 +}
41682 +#endif
41683 +
41684 +/**
41685 + * Handles a host Channel Halted interrupt in DMA mode. This handler
41686 + * determines the reason the channel halted and proceeds accordingly.
41687 + */
41688 +static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
41689 +                                     dwc_hc_t * hc,
41690 +                                     dwc_otg_hc_regs_t * hc_regs,
41691 +                                     dwc_otg_qtd_t * qtd)
41692 +{
41693 +       hcint_data_t hcint;
41694 +       hcintmsk_data_t hcintmsk;
41695 +       int out_nak_enh = 0;
41696 +
41697 +       /* For core with OUT NAK enhancement, the flow for high-
41698 +        * speed CONTROL/BULK OUT is handled a little differently.
41699 +        */
41700 +       if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
41701 +               if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
41702 +                   (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
41703 +                    hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
41704 +                       out_nak_enh = 1;
41705 +               }
41706 +       }
41707 +
41708 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
41709 +           (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR
41710 +            && !hcd->core_if->dma_desc_enable)) {
41711 +               /*
41712 +                * Just release the channel. A dequeue can happen on a
41713 +                * transfer timeout. In the case of an AHB Error, the channel
41714 +                * was forced to halt because there's no way to gracefully
41715 +                * recover.
41716 +                */
41717 +               if (hcd->core_if->dma_desc_enable)
41718 +                       dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41719 +                                                      hc->halt_status);
41720 +               else
41721 +                       release_channel(hcd, hc, qtd, hc->halt_status);
41722 +               return;
41723 +       }
41724 +
41725 +       /* Read the HCINTn register to determine the cause for the halt. */
41726 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41727 +       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41728 +
41729 +       if (hcint.b.xfercomp) {
41730 +               /** @todo This is here because of a possible hardware bug.  Spec
41731 +                * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
41732 +                * interrupt w/ACK bit set should occur, but I only see the
41733 +                * XFERCOMP bit, even with it masked out.  This is a workaround
41734 +                * for that behavior.  Should fix this when hardware is fixed.
41735 +                */
41736 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41737 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41738 +               }
41739 +               handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
41740 +       } else if (hcint.b.stall) {
41741 +               handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
41742 +       } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
41743 +               if (out_nak_enh) {
41744 +                       if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
41745 +                               DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");
41746 +                               qtd->error_count = 0;
41747 +                       } else {
41748 +                               DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");
41749 +                       }
41750 +               }
41751 +
41752 +               /*
41753 +                * Must handle xacterr before nak or ack. Could get a xacterr
41754 +                * at the same time as either of these on a BULK/CONTROL OUT
41755 +                * that started with a PING. The xacterr takes precedence.
41756 +                */
41757 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41758 +       } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
41759 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41760 +       } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {
41761 +               handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
41762 +       } else if (hcint.b.bblerr) {
41763 +               handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
41764 +       } else if (hcint.b.frmovrun) {
41765 +               handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
41766 +       } else if (!out_nak_enh) {
41767 +               if (hcint.b.nyet) {
41768 +                       /*
41769 +                        * Must handle nyet before nak or ack. Could get a nyet at the
41770 +                        * same time as either of those on a BULK/CONTROL OUT that
41771 +                        * started with a PING. The nyet takes precedence.
41772 +                        */
41773 +                       handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
41774 +               } else if (hcint.b.nak && !hcintmsk.b.nak) {
41775 +                       /*
41776 +                        * If nak is not masked, it's because a non-split IN transfer
41777 +                        * is in an error state. In that case, the nak is handled by
41778 +                        * the nak interrupt handler, not here. Handle nak here for
41779 +                        * BULK/CONTROL OUT transfers, which halt on a NAK to allow
41780 +                        * rewinding the buffer pointer.
41781 +                        */
41782 +                       handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
41783 +               } else if (hcint.b.ack && !hcintmsk.b.ack) {
41784 +                       /*
41785 +                        * If ack is not masked, it's because a non-split IN transfer
41786 +                        * is in an error state. In that case, the ack is handled by
41787 +                        * the ack interrupt handler, not here. Handle ack here for
41788 +                        * split transfers. Start splits halt on ACK.
41789 +                        */
41790 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41791 +               } else {
41792 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41793 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41794 +                               /*
41795 +                                * A periodic transfer halted with no other channel
41796 +                                * interrupts set. Assume it was halted by the core
41797 +                                * because it could not be completed in its scheduled
41798 +                                * (micro)frame.
41799 +                                */
41800 +#ifdef DEBUG
41801 +                               DWC_PRINTF
41802 +                                   ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
41803 +                                    __func__, hc->hc_num);
41804 +#endif
41805 +                               halt_channel(hcd, hc, qtd,
41806 +                                            DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
41807 +                       } else {
41808 +                               DWC_ERROR
41809 +                                   ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
41810 +                                    "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
41811 +                                    __func__, hc->hc_num, hcint.d32,
41812 +                                    DWC_READ_REG32(&hcd->
41813 +                                                   core_if->core_global_regs->
41814 +                                                   gintsts));
41815 +                       }
41816 +
41817 +               }
41818 +       } else {
41819 +               DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
41820 +                          hcint.d32);
41821 +       }
41822 +}
41823 +
41824 +/**
41825 + * Handles a host channel Channel Halted interrupt.
41826 + *
41827 + * In slave mode, this handler is called only when the driver specifically
41828 + * requests a halt. This occurs during handling other host channel interrupts
41829 + * (e.g. nak, xacterr, stall, nyet, etc.).
41830 + *
41831 + * In DMA mode, this is the interrupt that occurs when the core has finished
41832 + * processing a transfer on a channel. Other host channel interrupts (except
41833 + * ahberr) are disabled in DMA mode.
41834 + */
41835 +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
41836 +                                    dwc_hc_t * hc,
41837 +                                    dwc_otg_hc_regs_t * hc_regs,
41838 +                                    dwc_otg_qtd_t * qtd)
41839 +{
41840 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41841 +                   "Channel Halted--\n", hc->hc_num);
41842 +
41843 +       if (hcd->core_if->dma_enable) {
41844 +               handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
41845 +       } else {
41846 +#ifdef DEBUG
41847 +               if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
41848 +                       return 1;
41849 +               }
41850 +#endif
41851 +               release_channel(hcd, hc, qtd, hc->halt_status);
41852 +       }
41853 +
41854 +       return 1;
41855 +}
41856 +
41857 +/** Handles interrupt for a specific Host Channel */
41858 +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
41859 +{
41860 +       int retval = 0;
41861 +       hcint_data_t hcint;
41862 +       hcintmsk_data_t hcintmsk;
41863 +       dwc_hc_t *hc;
41864 +       dwc_otg_hc_regs_t *hc_regs;
41865 +       dwc_otg_qtd_t *qtd;
41866 +
41867 +       DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
41868 +
41869 +       hc = dwc_otg_hcd->hc_ptr_array[num];
41870 +       hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
41871 +       qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
41872 +
41873 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41874 +       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41875 +       DWC_DEBUGPL(DBG_HCDV,
41876 +                   "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
41877 +                   hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
41878 +       hcint.d32 = hcint.d32 & hcintmsk.d32;
41879 +
41880 +       if (!dwc_otg_hcd->core_if->dma_enable) {
41881 +               if (hcint.b.chhltd && hcint.d32 != 0x2) {
41882 +                       hcint.b.chhltd = 0;
41883 +               }
41884 +       }
41885 +
41886 +       if (hcint.b.xfercomp) {
41887 +               retval |=
41888 +                   handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41889 +               /*
41890 +                * If NYET occurred at same time as Xfer Complete, the NYET is
41891 +                * handled by the Xfer Complete interrupt handler. Don't want
41892 +                * to call the NYET interrupt handler in this case.
41893 +                */
41894 +               hcint.b.nyet = 0;
41895 +       }
41896 +       if (hcint.b.chhltd) {
41897 +               retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41898 +       }
41899 +       if (hcint.b.ahberr) {
41900 +               retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41901 +       }
41902 +       if (hcint.b.stall) {
41903 +               retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41904 +       }
41905 +       if (hcint.b.nak) {
41906 +               retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41907 +       }
41908 +       if (hcint.b.ack) {
41909 +               retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41910 +       }
41911 +       if (hcint.b.nyet) {
41912 +               retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41913 +       }
41914 +       if (hcint.b.xacterr) {
41915 +               retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41916 +       }
41917 +       if (hcint.b.bblerr) {
41918 +               retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41919 +       }
41920 +       if (hcint.b.frmovrun) {
41921 +               retval |=
41922 +                   handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41923 +       }
41924 +       if (hcint.b.datatglerr) {
41925 +               retval |=
41926 +                   handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41927 +       }
41928 +
41929 +       return retval;
41930 +}
41931 +
41932 +#endif /* DWC_DEVICE_ONLY */
41933 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
41934 new file mode 100644
41935 index 0000000..4a985a6
41936 --- /dev/null
41937 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
41938 @@ -0,0 +1,893 @@
41939 +/* ==========================================================================
41940 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
41941 + * $Revision: #20 $
41942 + * $Date: 2011/10/26 $
41943 + * $Change: 1872981 $
41944 + *
41945 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
41946 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
41947 + * otherwise expressly agreed to in writing between Synopsys and you.
41948 + *
41949 + * The Software IS NOT an item of Licensed Software or Licensed Product under
41950 + * any End User Software License Agreement or Agreement for Licensed Product
41951 + * with Synopsys or any supplement thereto. You are permitted to use and
41952 + * redistribute this Software in source and binary forms, with or without
41953 + * modification, provided that redistributions of source code must retain this
41954 + * notice. You may not view, use, disclose, copy or distribute this file or
41955 + * any information contained herein except pursuant to this license grant from
41956 + * Synopsys. If you do not agree with this notice, including the disclaimer
41957 + * below, then you are not authorized to use the Software.
41958 + *
41959 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
41960 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41961 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41962 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
41963 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41964 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41965 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41966 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41967 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41968 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
41969 + * DAMAGE.
41970 + * ========================================================================== */
41971 +#ifndef DWC_DEVICE_ONLY
41972 +
41973 +/**
41974 + * @file
41975 + *
41976 + * This file contains the implementation of the HCD. In Linux, the HCD
41977 + * implements the hc_driver API.
41978 + */
41979 +#include <linux/kernel.h>
41980 +#include <linux/module.h>
41981 +#include <linux/moduleparam.h>
41982 +#include <linux/init.h>
41983 +#include <linux/device.h>
41984 +#include <linux/errno.h>
41985 +#include <linux/list.h>
41986 +#include <linux/interrupt.h>
41987 +#include <linux/string.h>
41988 +#include <linux/dma-mapping.h>
41989 +#include <linux/version.h>
41990 +#include <asm/io.h>
41991 +#include <linux/usb.h>
41992 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
41993 +#include <../drivers/usb/core/hcd.h>
41994 +#else
41995 +#include <linux/usb/hcd.h>
41996 +#endif
41997 +
41998 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
41999 +#define USB_URB_EP_LINKING 1
42000 +#else
42001 +#define USB_URB_EP_LINKING 0
42002 +#endif
42003 +
42004 +#include "dwc_otg_hcd_if.h"
42005 +#include "dwc_otg_dbg.h"
42006 +#include "dwc_otg_driver.h"
42007 +#include "dwc_otg_hcd.h"
42008 +/**
42009 + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
42010 + * qualified with its direction (possible 32 endpoints per device).
42011 + */
42012 +#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
42013 +                                                    ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
42014 +
42015 +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
42016 +
42017 +/** @name Linux HC Driver API Functions */
42018 +/** @{ */
42019 +/* manage i/o requests, device state */
42020 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
42021 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42022 +                      struct usb_host_endpoint *ep,
42023 +#endif
42024 +                      struct urb *urb, gfp_t mem_flags);
42025 +
42026 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
42027 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42028 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
42029 +#endif
42030 +#else /* kernels at or post 2.6.30 */
42031 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd,
42032 +                               struct urb *urb, int status);
42033 +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */
42034 +
42035 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
42036 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42037 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
42038 +#endif
42039 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
42040 +extern int hcd_start(struct usb_hcd *hcd);
42041 +extern void hcd_stop(struct usb_hcd *hcd);
42042 +static int get_frame_number(struct usb_hcd *hcd);
42043 +extern int hub_status_data(struct usb_hcd *hcd, char *buf);
42044 +extern int hub_control(struct usb_hcd *hcd,
42045 +                      u16 typeReq,
42046 +                      u16 wValue, u16 wIndex, char *buf, u16 wLength);
42047 +
42048 +struct wrapper_priv_data {
42049 +       dwc_otg_hcd_t *dwc_otg_hcd;
42050 +};
42051 +
42052 +/** @} */
42053 +
42054 +static struct hc_driver dwc_otg_hc_driver = {
42055 +
42056 +       .description = dwc_otg_hcd_name,
42057 +       .product_desc = "DWC OTG Controller",
42058 +       .hcd_priv_size = sizeof(struct wrapper_priv_data),
42059 +
42060 +       .irq = dwc_otg_hcd_irq,
42061 +
42062 +       .flags = HCD_MEMORY | HCD_USB2,
42063 +
42064 +       //.reset =              
42065 +       .start = hcd_start,
42066 +       //.suspend =            
42067 +       //.resume =             
42068 +       .stop = hcd_stop,
42069 +
42070 +       .urb_enqueue = dwc_otg_urb_enqueue,
42071 +       .urb_dequeue = dwc_otg_urb_dequeue,
42072 +       .endpoint_disable = endpoint_disable,
42073 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42074 +       .endpoint_reset = endpoint_reset,
42075 +#endif
42076 +       .get_frame_number = get_frame_number,
42077 +
42078 +       .hub_status_data = hub_status_data,
42079 +       .hub_control = hub_control,
42080 +       //.bus_suspend =                
42081 +       //.bus_resume =         
42082 +};
42083 +
42084 +/** Gets the dwc_otg_hcd from a struct usb_hcd */
42085 +static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
42086 +{
42087 +       struct wrapper_priv_data *p;
42088 +       p = (struct wrapper_priv_data *)(hcd->hcd_priv);
42089 +       return p->dwc_otg_hcd;
42090 +}
42091 +
42092 +/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
42093 +static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
42094 +{
42095 +       return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
42096 +}
42097 +
42098 +/** Gets the usb_host_endpoint associated with an URB. */
42099 +inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
42100 +{
42101 +       struct usb_device *dev = urb->dev;
42102 +       int ep_num = usb_pipeendpoint(urb->pipe);
42103 +
42104 +       if (usb_pipein(urb->pipe))
42105 +               return dev->ep_in[ep_num];
42106 +       else
42107 +               return dev->ep_out[ep_num];
42108 +}
42109 +
42110 +static int _disconnect(dwc_otg_hcd_t * hcd)
42111 +{
42112 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42113 +
42114 +       usb_hcd->self.is_b_host = 0;
42115 +       return 0;
42116 +}
42117 +
42118 +static int _start(dwc_otg_hcd_t * hcd)
42119 +{
42120 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42121 +
42122 +       usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
42123 +       hcd_start(usb_hcd);
42124 +
42125 +       return 0;
42126 +}
42127 +
42128 +static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
42129 +                    uint32_t * port_addr)
42130 +{
42131 +   struct urb *urb = (struct urb *)urb_handle;
42132 +   struct usb_bus *bus;
42133 +#if 1 //GRAYG - temporary
42134 +   if (NULL == urb_handle)
42135 +      DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG
42136 +   if (NULL == urb->dev)
42137 +      DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG
42138 +   if (NULL == port_addr)
42139 +      DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG
42140 +#endif
42141 +   if (urb->dev->tt) {
42142 +        if (NULL == urb->dev->tt->hub) {
42143 +                DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n",
42144 +                           __func__); //GRAYG
42145 +                //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG
42146 +                *hub_addr = 0; //GRAYG
42147 +                // we probably shouldn't have a transaction translator if
42148 +                // there's no associated hub?
42149 +        } else {
42150 +               bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
42151 +               if (urb->dev->tt->hub == bus->root_hub)
42152 +                       *hub_addr = 0;
42153 +               else
42154 +                       *hub_addr = urb->dev->tt->hub->devnum;
42155 +       }
42156 +       *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
42157 +   } else {
42158 +        *hub_addr = 0;
42159 +       *port_addr = urb->dev->ttport;
42160 +   }
42161 +   return 0;
42162 +}
42163 +
42164 +static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
42165 +{
42166 +       struct urb *urb = (struct urb *)urb_handle;
42167 +       return urb->dev->speed;
42168 +}
42169 +
42170 +static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
42171 +{
42172 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42173 +       return usb_hcd->self.b_hnp_enable;
42174 +}
42175 +
42176 +static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42177 +                                  struct urb *urb)
42178 +{
42179 +       hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
42180 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42181 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
42182 +       } else {
42183 +               hcd_to_bus(hcd)->bandwidth_int_reqs++;
42184 +       }
42185 +}
42186 +
42187 +static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42188 +                              struct urb *urb)
42189 +{
42190 +       hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
42191 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42192 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
42193 +       } else {
42194 +               hcd_to_bus(hcd)->bandwidth_int_reqs--;
42195 +       }
42196 +}
42197 +
42198 +/**
42199 + * Sets the final status of an URB and returns it to the device driver. Any
42200 + * required cleanup of the URB is performed.
42201 + */
42202 +static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
42203 +                    dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
42204 +{
42205 +       struct urb *urb = (struct urb *)urb_handle;
42206 +
42207 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42208 +               DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
42209 +                          __func__, urb, usb_pipedevice(urb->pipe),
42210 +                          usb_pipeendpoint(urb->pipe),
42211 +                          usb_pipein(urb->pipe) ? "IN" : "OUT", status);
42212 +               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42213 +                       int i;
42214 +                       for (i = 0; i < urb->number_of_packets; i++) {
42215 +                               DWC_PRINTF("  ISO Desc %d status: %d\n",
42216 +                                          i, urb->iso_frame_desc[i].status);
42217 +                       }
42218 +               }
42219 +       }
42220 +
42221 +       urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
42222 +       /* Convert status value. */
42223 +       switch (status) {
42224 +       case -DWC_E_PROTOCOL:
42225 +               status = -EPROTO;
42226 +               break;
42227 +       case -DWC_E_IN_PROGRESS:
42228 +               status = -EINPROGRESS;
42229 +               break;
42230 +       case -DWC_E_PIPE:
42231 +               status = -EPIPE;
42232 +               break;
42233 +       case -DWC_E_IO:
42234 +               status = -EIO;
42235 +               break;
42236 +       case -DWC_E_TIMEOUT:
42237 +               status = -ETIMEDOUT;
42238 +               break;
42239 +       case -DWC_E_OVERFLOW:
42240 +               status = -EOVERFLOW;
42241 +               break;
42242 +       default:
42243 +               if (status) {
42244 +                       DWC_PRINTF("Uknown urb status %d\n", status);
42245 +
42246 +               }
42247 +       }
42248 +
42249 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42250 +               int i;
42251 +
42252 +               urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
42253 +               for (i = 0; i < urb->number_of_packets; ++i) {
42254 +                       urb->iso_frame_desc[i].actual_length =
42255 +                           dwc_otg_hcd_urb_get_iso_desc_actual_length
42256 +                           (dwc_otg_urb, i);
42257 +                       urb->iso_frame_desc[i].status =
42258 +                           dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i);
42259 +               }
42260 +       }
42261 +
42262 +       urb->status = status;
42263 +       urb->hcpriv = NULL;
42264 +       if (!status) {
42265 +               if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
42266 +                   (urb->actual_length < urb->transfer_buffer_length)) {
42267 +                       urb->status = -EREMOTEIO;
42268 +               }
42269 +       }
42270 +
42271 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
42272 +           (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42273 +               struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
42274 +               if (ep) {
42275 +                       free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
42276 +                                          dwc_otg_hcd_get_ep_bandwidth(hcd,
42277 +                                                                       ep->hcpriv),
42278 +                                          urb);
42279 +               }
42280 +       }
42281 +
42282 +       DWC_FREE(dwc_otg_urb);
42283 +
42284 +#if USB_URB_EP_LINKING
42285 +        usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
42286 +#endif
42287 +       DWC_SPINUNLOCK(hcd->lock);
42288 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42289 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
42290 +#else
42291 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
42292 +#endif
42293 +       DWC_SPINLOCK(hcd->lock);
42294 +
42295 +       return 0;
42296 +}
42297 +
42298 +static struct dwc_otg_hcd_function_ops hcd_fops = {
42299 +       .start = _start,
42300 +       .disconnect = _disconnect,
42301 +       .hub_info = _hub_info,
42302 +       .speed = _speed,
42303 +       .complete = _complete,
42304 +       .get_b_hnp_enable = _get_b_hnp_enable,
42305 +};
42306 +
42307 +/**
42308 + * Initializes the HCD. This function allocates memory for and initializes the
42309 + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
42310 + * USB bus with the core and calls the hc_driver->start() function. It returns
42311 + * a negative error on failure.
42312 + */
42313 +int hcd_init(dwc_bus_dev_t *_dev)
42314 +{
42315 +       struct usb_hcd *hcd = NULL;
42316 +       dwc_otg_hcd_t *dwc_otg_hcd = NULL;
42317 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42318 +       int retval = 0;
42319 +        u64 dmamask;
42320 +
42321 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
42322 +
42323 +       /* Set device flags indicating whether the HCD supports DMA. */
42324 +       if (dwc_otg_is_dma_enable(otg_dev->core_if))
42325 +                dmamask = DMA_BIT_MASK(32);
42326 +        else
42327 +                dmamask = 0;
42328 +              
42329 +#if    defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
42330 +        dma_set_mask(&_dev->dev, dmamask);
42331 +        dma_set_coherent_mask(&_dev->dev, dmamask);
42332 +#elif  defined(PCI_INTERFACE)
42333 +        pci_set_dma_mask(_dev, dmamask);
42334 +        pci_set_consistent_dma_mask(_dev, dmamask);
42335 +#endif
42336 +
42337 +       /*
42338 +        * Allocate memory for the base HCD plus the DWC OTG HCD.
42339 +        * Initialize the base HCD.
42340 +        */
42341 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
42342 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);
42343 +#else
42344 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev));
42345 +       hcd->has_tt = 1;
42346 +//      hcd->uses_new_polling = 1;
42347 +//      hcd->poll_rh = 0;
42348 +#endif
42349 +       if (!hcd) {
42350 +               retval = -ENOMEM;
42351 +               goto error1;
42352 +       }
42353 +
42354 +       hcd->regs = otg_dev->os_dep.base;
42355 +
42356 +       /* Initialize the DWC OTG HCD. */
42357 +       dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
42358 +       if (!dwc_otg_hcd) {
42359 +               goto error2;
42360 +       }
42361 +       ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
42362 +           dwc_otg_hcd;
42363 +       otg_dev->hcd = dwc_otg_hcd;
42364 +
42365 +       if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
42366 +               goto error2;
42367 +       }
42368 +
42369 +       otg_dev->hcd->otg_dev = otg_dev;
42370 +       hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
42371 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
42372 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later
42373 +       hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);
42374 +#endif
42375 +       /* Don't support SG list at this point */
42376 +       hcd->self.sg_tablesize = 0;
42377 +#endif
42378 +       /*
42379 +        * Finish generic HCD initialization and start the HCD. This function
42380 +        * allocates the DMA buffer pool, registers the USB bus, requests the
42381 +        * IRQ line, and calls hcd_start method.
42382 +        */
42383 +#ifdef PLATFORM_INTERFACE
42384 +        retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED);
42385 +#else
42386 +        retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);     
42387 +#endif
42388 +       if (retval < 0) {
42389 +               goto error2;
42390 +       }
42391 +
42392 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
42393 +       return 0;
42394 +
42395 +error2:
42396 +       usb_put_hcd(hcd);
42397 +error1:
42398 +       return retval;
42399 +}
42400 +
42401 +/**
42402 + * Removes the HCD.
42403 + * Frees memory and resources associated with the HCD and deregisters the bus.
42404 + */
42405 +void hcd_remove(dwc_bus_dev_t *_dev)
42406 +{
42407 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42408 +       dwc_otg_hcd_t *dwc_otg_hcd;
42409 +       struct usb_hcd *hcd;
42410 +
42411 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev);
42412 +
42413 +       if (!otg_dev) {
42414 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
42415 +               return;
42416 +       }
42417 +
42418 +       dwc_otg_hcd = otg_dev->hcd;
42419 +
42420 +       if (!dwc_otg_hcd) {
42421 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
42422 +               return;
42423 +       }
42424 +
42425 +       hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
42426 +
42427 +       if (!hcd) {
42428 +               DWC_DEBUGPL(DBG_ANY,
42429 +                           "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
42430 +                           __func__);
42431 +               return;
42432 +       }
42433 +       usb_remove_hcd(hcd);
42434 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
42435 +       dwc_otg_hcd_remove(dwc_otg_hcd);
42436 +       usb_put_hcd(hcd);
42437 +}
42438 +
42439 +/* =========================================================================
42440 + *  Linux HC Driver Functions
42441 + * ========================================================================= */
42442 +
42443 +/** Initializes the DWC_otg controller and its root hub and prepares it for host
42444 + * mode operation. Activates the root port. Returns 0 on success and a negative
42445 + * error code on failure. */
42446 +int hcd_start(struct usb_hcd *hcd)
42447 +{
42448 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42449 +       struct usb_bus *bus;
42450 +
42451 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
42452 +       bus = hcd_to_bus(hcd);
42453 +
42454 +       hcd->state = HC_STATE_RUNNING;
42455 +       if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
42456 +               return 0;
42457 +       }
42458 +
42459 +       /* Initialize and connect root hub if one is not already attached */
42460 +       if (bus->root_hub) {
42461 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
42462 +               /* Inform the HUB driver to resume. */
42463 +               usb_hcd_resume_root_hub(hcd);
42464 +       }
42465 +
42466 +       return 0;
42467 +}
42468 +
42469 +/**
42470 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
42471 + * stopped.
42472 + */
42473 +void hcd_stop(struct usb_hcd *hcd)
42474 +{
42475 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42476 +
42477 +       dwc_otg_hcd_stop(dwc_otg_hcd);
42478 +}
42479 +
42480 +/** Returns the current frame number. */
42481 +static int get_frame_number(struct usb_hcd *hcd)
42482 +{
42483 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42484 +
42485 +       return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
42486 +}
42487 +
42488 +#ifdef DEBUG
42489 +static void dump_urb_info(struct urb *urb, char *fn_name)
42490 +{
42491 +       DWC_PRINTF("%s, urb %p\n", fn_name, urb);
42492 +       DWC_PRINTF("  Device address: %d\n", usb_pipedevice(urb->pipe));
42493 +       DWC_PRINTF("  Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
42494 +                  (usb_pipein(urb->pipe) ? "IN" : "OUT"));
42495 +       DWC_PRINTF("  Endpoint type: %s\n", ( {
42496 +                                            char *pipetype;
42497 +                                            switch (usb_pipetype(urb->pipe)) {
42498 +case PIPE_CONTROL:
42499 +pipetype = "CONTROL"; break; case PIPE_BULK:
42500 +pipetype = "BULK"; break; case PIPE_INTERRUPT:
42501 +pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
42502 +pipetype = "ISOCHRONOUS"; break; default:
42503 +                                            pipetype = "UNKNOWN"; break;};
42504 +                                            pipetype;}
42505 +                  )) ;
42506 +       DWC_PRINTF("  Speed: %s\n", ( {
42507 +                                    char *speed; switch (urb->dev->speed) {
42508 +case USB_SPEED_HIGH:
42509 +speed = "HIGH"; break; case USB_SPEED_FULL:
42510 +speed = "FULL"; break; case USB_SPEED_LOW:
42511 +speed = "LOW"; break; default:
42512 +                                    speed = "UNKNOWN"; break;};
42513 +                                    speed;}
42514 +                  )) ;
42515 +       DWC_PRINTF("  Max packet size: %d\n",
42516 +                  usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
42517 +       DWC_PRINTF("  Data buffer length: %d\n", urb->transfer_buffer_length);
42518 +       DWC_PRINTF("  Transfer buffer: %p, Transfer DMA: %p\n",
42519 +                  urb->transfer_buffer, (void *)urb->transfer_dma);
42520 +       DWC_PRINTF("  Setup buffer: %p, Setup DMA: %p\n",
42521 +                  urb->setup_packet, (void *)urb->setup_dma);
42522 +       DWC_PRINTF("  Interval: %d\n", urb->interval);
42523 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42524 +               int i;
42525 +               for (i = 0; i < urb->number_of_packets; i++) {
42526 +                       DWC_PRINTF("  ISO Desc %d:\n", i);
42527 +                       DWC_PRINTF("    offset: %d, length %d\n",
42528 +                                  urb->iso_frame_desc[i].offset,
42529 +                                  urb->iso_frame_desc[i].length);
42530 +               }
42531 +       }
42532 +}
42533 +#endif
42534 +
42535 +/** Starts processing a USB transfer request specified by a USB Request Block
42536 + * (URB). mem_flags indicates the type of memory allocation to use while
42537 + * processing this URB. */
42538 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
42539 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42540 +                      struct usb_host_endpoint *ep,
42541 +#endif
42542 +                      struct urb *urb, gfp_t mem_flags)
42543 +{
42544 +       int retval = 0;
42545 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
42546 +       struct usb_host_endpoint *ep = urb->ep;
42547 +#endif
42548 +#if USB_URB_EP_LINKING
42549 +       dwc_irqflags_t irqflags;
42550 +#endif
42551 +        void **ref_ep_hcpriv = &ep->hcpriv;
42552 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42553 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
42554 +       int i;
42555 +       int alloc_bandwidth = 0;
42556 +       uint8_t ep_type = 0;
42557 +       uint32_t flags = 0;
42558 +       void *buf;
42559 +
42560 +#ifdef DEBUG
42561 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42562 +               dump_urb_info(urb, "dwc_otg_urb_enqueue");
42563 +       }
42564 +#endif
42565 +
42566 +       if (!urb->transfer_buffer && urb->transfer_buffer_length)
42567 +               return -EINVAL;
42568 +
42569 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
42570 +           || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42571 +               if (!dwc_otg_hcd_is_bandwidth_allocated
42572 +                   (dwc_otg_hcd, ref_ep_hcpriv)) {
42573 +                       alloc_bandwidth = 1;
42574 +               }
42575 +       }
42576 +
42577 +       switch (usb_pipetype(urb->pipe)) {
42578 +       case PIPE_CONTROL:
42579 +               ep_type = USB_ENDPOINT_XFER_CONTROL;
42580 +               break;
42581 +       case PIPE_ISOCHRONOUS:
42582 +               ep_type = USB_ENDPOINT_XFER_ISOC;
42583 +               break;
42584 +       case PIPE_BULK:
42585 +               ep_type = USB_ENDPOINT_XFER_BULK;
42586 +               break;
42587 +       case PIPE_INTERRUPT:
42588 +               ep_type = USB_ENDPOINT_XFER_INT;
42589 +               break;
42590 +       default:
42591 +                DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe));
42592 +       }
42593 +
42594 +        /* # of packets is often 0 - do we really need to call this then? */
42595 +       dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
42596 +                                           urb->number_of_packets,
42597 +                                           mem_flags == GFP_ATOMIC ? 1 : 0);
42598 +
42599 +       if(dwc_otg_urb == NULL)
42600 +               return -ENOMEM;
42601 +
42602 +        urb->hcpriv = dwc_otg_urb;
42603 +        if (!dwc_otg_urb && urb->number_of_packets)
42604 +                return -ENOMEM;
42605 +        
42606 +       dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
42607 +                                    usb_pipeendpoint(urb->pipe), ep_type,
42608 +                                    usb_pipein(urb->pipe),
42609 +                                    usb_maxpacket(urb->dev, urb->pipe,
42610 +                                                  !(usb_pipein(urb->pipe))));
42611 +
42612 +       buf = urb->transfer_buffer;
42613 +       if (hcd->self.uses_dma) {
42614 +               /*
42615 +                * Calculate virtual address from physical address,
42616 +                * because some class driver may not fill transfer_buffer.
42617 +                * In Buffer DMA mode virual address is used,
42618 +                * when handling non DWORD aligned buffers.
42619 +                */
42620 +               //buf = phys_to_virt(urb->transfer_dma);
42621 +                // DMA addresses are bus addresses not physical addresses!
42622 +                buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma);
42623 +       }
42624 +
42625 +       if (!(urb->transfer_flags & URB_NO_INTERRUPT))
42626 +               flags |= URB_GIVEBACK_ASAP;
42627 +       if (urb->transfer_flags & URB_ZERO_PACKET)
42628 +               flags |= URB_SEND_ZERO_PACKET;
42629 +
42630 +       dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
42631 +                                  urb->transfer_dma,
42632 +                                  urb->transfer_buffer_length,
42633 +                                  urb->setup_packet,
42634 +                                  urb->setup_dma, flags, urb->interval);
42635 +
42636 +       for (i = 0; i < urb->number_of_packets; ++i) {
42637 +               dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
42638 +                                                   urb->
42639 +                                                   iso_frame_desc[i].offset,
42640 +                                                   urb->
42641 +                                                   iso_frame_desc[i].length);
42642 +       }
42643 +
42644 +#if USB_URB_EP_LINKING
42645 +        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42646 +       retval = usb_hcd_link_urb_to_ep(hcd, urb);
42647 +        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42648 +       if (0 == retval) 
42649 +#endif
42650 +        {
42651 +                retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
42652 +                                                 /*(dwc_otg_qh_t **)*/
42653 +                                                 ref_ep_hcpriv, 
42654 +                                                 mem_flags == GFP_ATOMIC ? 1 : 0);
42655 +                if (0 == retval) {
42656 +                        if (alloc_bandwidth) {
42657 +                                allocate_bus_bandwidth(hcd,
42658 +                                        dwc_otg_hcd_get_ep_bandwidth(
42659 +                                                dwc_otg_hcd, *ref_ep_hcpriv),
42660 +                                                       urb);
42661 +                        }
42662 +                } else {
42663 +#if USB_URB_EP_LINKING
42664 +                       dwc_irqflags_t irqflags;
42665 +                        DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
42666 +                        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42667 +                        usb_hcd_unlink_urb_from_ep(hcd, urb);
42668 +                        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42669 +#endif
42670 +                        if (retval == -DWC_E_NO_DEVICE) {
42671 +                                retval = -ENODEV;
42672 +                        }
42673 +                }
42674 +        }
42675 +       return retval;
42676 +}
42677 +
42678 +/** Aborts/cancels a USB transfer request. Always returns 0 to indicate
42679 + * success.  */
42680 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42681 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
42682 +#else
42683 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
42684 +#endif
42685 +{
42686 +       dwc_irqflags_t flags;
42687 +       dwc_otg_hcd_t *dwc_otg_hcd;
42688 +        int rc;
42689 +
42690 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
42691 +
42692 +       dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42693 +
42694 +#ifdef DEBUG
42695 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42696 +               dump_urb_info(urb, "dwc_otg_urb_dequeue");
42697 +       }
42698 +#endif
42699 +
42700 +       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42701 +       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
42702 +       if (0 == rc) {
42703 +               if(urb->hcpriv != NULL) {
42704 +                       dwc_otg_hcd_urb_dequeue(dwc_otg_hcd,
42705 +                                           (dwc_otg_hcd_urb_t *)urb->hcpriv);
42706 +
42707 +                       DWC_FREE(urb->hcpriv);
42708 +                       urb->hcpriv = NULL;
42709 +               }
42710 +        }
42711 +
42712 +        if (0 == rc) {
42713 +               /* Higher layer software sets URB status. */
42714 +#if USB_URB_EP_LINKING
42715 +                usb_hcd_unlink_urb_from_ep(hcd, urb);
42716 +#endif
42717 +               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42718 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42719 +                usb_hcd_giveback_urb(hcd, urb);
42720 +#else
42721 +                usb_hcd_giveback_urb(hcd, urb, status);
42722 +#endif
42723 +                if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42724 +                        DWC_PRINTF("Called usb_hcd_giveback_urb() \n");
42725 +                        DWC_PRINTF("  1urb->status = %d\n", urb->status);
42726 +                }
42727 +                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n");
42728 +        } else {
42729 +               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42730 +                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n",
42731 +                            rc);
42732 +        }
42733 +           
42734 +       return rc;
42735 +}
42736 +
42737 +/* Frees resources in the DWC_otg controller related to a given endpoint. Also
42738 + * clears state in the HCD related to the endpoint. Any URBs for the endpoint
42739 + * must already be dequeued. */
42740 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42741 +{
42742 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42743 +
42744 +       DWC_DEBUGPL(DBG_HCD,
42745 +                   "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
42746 +                   "endpoint=%d\n", ep->desc.bEndpointAddress,
42747 +                   dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
42748 +       dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
42749 +       ep->hcpriv = NULL;
42750 +}
42751 +
42752 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42753 +/* Resets endpoint specific parameter values, in current version used to reset 
42754 + * the data toggle(as a WA). This function can be called from usb_clear_halt routine */
42755 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42756 +{
42757 +       dwc_irqflags_t flags;
42758 +       struct usb_device *udev = NULL;
42759 +       int epnum = usb_endpoint_num(&ep->desc);
42760 +       int is_out = usb_endpoint_dir_out(&ep->desc);
42761 +       int is_control = usb_endpoint_xfer_control(&ep->desc);
42762 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42763 +        struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep);
42764 +
42765 +       if (dev)
42766 +               udev = to_usb_device(dev);
42767 +       else
42768 +               return;
42769 +
42770 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum);
42771 +
42772 +       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42773 +       usb_settoggle(udev, epnum, is_out, 0);
42774 +       if (is_control)
42775 +               usb_settoggle(udev, epnum, !is_out, 0);
42776 +
42777 +       if (ep->hcpriv) {
42778 +               dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv);
42779 +       }
42780 +       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42781 +}
42782 +#endif
42783 +
42784 +/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
42785 + * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
42786 + * interrupt.
42787 + *
42788 + * This function is called by the USB core when an interrupt occurs */
42789 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
42790 +{
42791 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42792 +       int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
42793 +       if (retval != 0) {
42794 +               S3C2410X_CLEAR_EINTPEND();
42795 +       }
42796 +       return IRQ_RETVAL(retval);
42797 +}
42798 +
42799 +/** Creates Status Change bitmap for the root hub and root port. The bitmap is
42800 + * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
42801 + * is the status change indicator for the single root port. Returns 1 if either
42802 + * change indicator is 1, otherwise returns 0. */
42803 +int hub_status_data(struct usb_hcd *hcd, char *buf)
42804 +{
42805 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42806 +
42807 +       buf[0] = 0;
42808 +       buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
42809 +
42810 +       return (buf[0] != 0);
42811 +}
42812 +
42813 +/** Handles hub class-specific requests. */
42814 +int hub_control(struct usb_hcd *hcd,
42815 +               u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
42816 +{
42817 +       int retval;
42818 +
42819 +       retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
42820 +                                        typeReq, wValue, wIndex, buf, wLength);
42821 +
42822 +       switch (retval) {
42823 +       case -DWC_E_INVALID:
42824 +               retval = -EINVAL;
42825 +               break;
42826 +       }
42827 +
42828 +       return retval;
42829 +}
42830 +
42831 +#endif /* DWC_DEVICE_ONLY */
42832 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
42833 new file mode 100644
42834 index 0000000..08c1669
42835 --- /dev/null
42836 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
42837 @@ -0,0 +1,922 @@
42838 +/* ==========================================================================
42839 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
42840 + * $Revision: #44 $
42841 + * $Date: 2011/10/26 $
42842 + * $Change: 1873028 $
42843 + *
42844 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
42845 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
42846 + * otherwise expressly agreed to in writing between Synopsys and you.
42847 + * 
42848 + * The Software IS NOT an item of Licensed Software or Licensed Product under
42849 + * any End User Software License Agreement or Agreement for Licensed Product
42850 + * with Synopsys or any supplement thereto. You are permitted to use and
42851 + * redistribute this Software in source and binary forms, with or without
42852 + * modification, provided that redistributions of source code must retain this
42853 + * notice. You may not view, use, disclose, copy or distribute this file or
42854 + * any information contained herein except pursuant to this license grant from
42855 + * Synopsys. If you do not agree with this notice, including the disclaimer
42856 + * below, then you are not authorized to use the Software.
42857 + * 
42858 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
42859 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42860 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42861 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
42862 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42863 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
42864 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
42865 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42866 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42867 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
42868 + * DAMAGE.
42869 + * ========================================================================== */
42870 +#ifndef DWC_DEVICE_ONLY
42871 +
42872 +/**
42873 + * @file
42874 + *
42875 + * This file contains the functions to manage Queue Heads and Queue
42876 + * Transfer Descriptors.
42877 + */
42878 +
42879 +#include "dwc_otg_hcd.h"
42880 +#include "dwc_otg_regs.h"
42881 +
42882 +extern bool microframe_schedule;
42883 +
42884 +/** 
42885 + * Free each QTD in the QH's QTD-list then free the QH.  QH should already be
42886 + * removed from a list.  QTD list should already be empty if called from URB
42887 + * Dequeue.
42888 + *
42889 + * @param hcd HCD instance.
42890 + * @param qh The QH to free.
42891 + */
42892 +void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
42893 +{
42894 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
42895 +
42896 +       /* Free each QTD in the QTD list */
42897 +       DWC_SPINLOCK(hcd->lock);
42898 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
42899 +               DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
42900 +               dwc_otg_hcd_qtd_free(qtd);
42901 +       }
42902 +
42903 +       if (hcd->core_if->dma_desc_enable) {
42904 +               dwc_otg_hcd_qh_free_ddma(hcd, qh);
42905 +       } else if (qh->dw_align_buf) {
42906 +               uint32_t buf_size;
42907 +               if (qh->ep_type == UE_ISOCHRONOUS) {
42908 +                       buf_size = 4096;
42909 +               } else {
42910 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
42911 +               }
42912 +               DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma);
42913 +       }
42914 +
42915 +       DWC_FREE(qh);
42916 +       DWC_SPINUNLOCK(hcd->lock);
42917 +       return;
42918 +}
42919 +
42920 +#define BitStuffTime(bytecount)  ((8 * 7* bytecount) / 6)
42921 +#define HS_HOST_DELAY          5       /* nanoseconds */
42922 +#define FS_LS_HOST_DELAY       1000    /* nanoseconds */
42923 +#define HUB_LS_SETUP           333     /* nanoseconds */
42924 +#define NS_TO_US(ns)           ((ns + 500) / 1000)
42925 +                               /* convert & round nanoseconds to microseconds */
42926 +
42927 +static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount)
42928 +{
42929 +       unsigned long retval;
42930 +
42931 +       switch (speed) {
42932 +       case USB_SPEED_HIGH:
42933 +               if (is_isoc) {
42934 +                       retval =
42935 +                           ((38 * 8 * 2083) +
42936 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42937 +                           HS_HOST_DELAY;
42938 +               } else {
42939 +                       retval =
42940 +                           ((55 * 8 * 2083) +
42941 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42942 +                           HS_HOST_DELAY;
42943 +               }
42944 +               break;
42945 +       case USB_SPEED_FULL:
42946 +               if (is_isoc) {
42947 +                       retval =
42948 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42949 +                       if (is_in) {
42950 +                               retval = 7268 + FS_LS_HOST_DELAY + retval;
42951 +                       } else {
42952 +                               retval = 6265 + FS_LS_HOST_DELAY + retval;
42953 +                       }
42954 +               } else {
42955 +                       retval =
42956 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42957 +                       retval = 9107 + FS_LS_HOST_DELAY + retval;
42958 +               }
42959 +               break;
42960 +       case USB_SPEED_LOW:
42961 +               if (is_in) {
42962 +                       retval =
42963 +                           (67667 * (31 + 10 * BitStuffTime(bytecount))) /
42964 +                           1000;
42965 +                       retval =
42966 +                           64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42967 +                           retval;
42968 +               } else {
42969 +                       retval =
42970 +                           (66700 * (31 + 10 * BitStuffTime(bytecount))) /
42971 +                           1000;
42972 +                       retval =
42973 +                           64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42974 +                           retval;
42975 +               }
42976 +               break;
42977 +       default:
42978 +               DWC_WARN("Unknown device speed\n");
42979 +               retval = -1;
42980 +       }
42981 +
42982 +       return NS_TO_US(retval);
42983 +}
42984 +
42985 +/** 
42986 + * Initializes a QH structure.
42987 + *
42988 + * @param hcd The HCD state structure for the DWC OTG controller.
42989 + * @param qh  The QH to init.
42990 + * @param urb Holds the information about the device/endpoint that we need
42991 + *           to initialize the QH. 
42992 + */
42993 +#define SCHEDULE_SLOP 10
42994 +void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
42995 +{
42996 +       char *speed, *type;
42997 +       int dev_speed;
42998 +       uint32_t hub_addr, hub_port;
42999 +
43000 +       dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
43001 +
43002 +       /* Initialize QH */
43003 +       qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
43004 +       qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
43005 +
43006 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
43007 +       qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info);
43008 +       DWC_CIRCLEQ_INIT(&qh->qtd_list);
43009 +       DWC_LIST_INIT(&qh->qh_list_entry);
43010 +       qh->channel = NULL;
43011 +
43012 +       /* FS/LS Enpoint on HS Hub 
43013 +        * NOT virtual root hub */
43014 +       dev_speed = hcd->fops->speed(hcd, urb->priv);
43015 +
43016 +       hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port);
43017 +       qh->do_split = 0;
43018 +       if (microframe_schedule)
43019 +               qh->speed = dev_speed;
43020 +
43021 +
43022 +       if (((dev_speed == USB_SPEED_LOW) ||
43023 +            (dev_speed == USB_SPEED_FULL)) &&
43024 +           (hub_addr != 0 && hub_addr != 1)) {
43025 +               DWC_DEBUGPL(DBG_HCD,
43026 +                           "QH init: EP %d: TT found at hub addr %d, for port %d\n",
43027 +                           dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
43028 +                           hub_port);
43029 +               qh->do_split = 1;
43030 +       }
43031 +
43032 +       if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
43033 +               /* Compute scheduling parameters once and save them. */
43034 +               hprt0_data_t hprt;
43035 +
43036 +               /** @todo Account for split transfers in the bus time. */
43037 +               int bytecount =
43038 +                   dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);
43039 +
43040 +               qh->usecs =
43041 +                   calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed),
43042 +                                 qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS),
43043 +                                 bytecount);
43044 +               /* Start in a slightly future (micro)frame. */
43045 +               qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
43046 +                                                   SCHEDULE_SLOP);
43047 +               qh->interval = urb->interval;
43048 +
43049 +#if 0
43050 +               /* Increase interrupt polling rate for debugging. */
43051 +               if (qh->ep_type == UE_INTERRUPT) {
43052 +                       qh->interval = 8;
43053 +               }
43054 +#endif
43055 +               hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
43056 +               if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&
43057 +                   ((dev_speed == USB_SPEED_LOW) ||
43058 +                    (dev_speed == USB_SPEED_FULL))) {
43059 +                       qh->interval *= 8;
43060 +                       qh->sched_frame |= 0x7;
43061 +                       qh->start_split_frame = qh->sched_frame;
43062 +               }
43063 +
43064 +       }
43065 +
43066 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
43067 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - qh = %p\n", qh);
43068 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Device Address = %d\n",
43069 +                   dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
43070 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Endpoint %d, %s\n",
43071 +                   dwc_otg_hcd_get_ep_num(&urb->pipe_info),
43072 +                   dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
43073 +       switch (dev_speed) {
43074 +       case USB_SPEED_LOW:
43075 +               qh->dev_speed = DWC_OTG_EP_SPEED_LOW;
43076 +               speed = "low";
43077 +               break;
43078 +       case USB_SPEED_FULL:
43079 +               qh->dev_speed = DWC_OTG_EP_SPEED_FULL;
43080 +               speed = "full";
43081 +               break;
43082 +       case USB_SPEED_HIGH:
43083 +               qh->dev_speed = DWC_OTG_EP_SPEED_HIGH;
43084 +               speed = "high";
43085 +               break;
43086 +       default:
43087 +               speed = "?";
43088 +               break;
43089 +       }
43090 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Speed = %s\n", speed);
43091 +
43092 +       switch (qh->ep_type) {
43093 +       case UE_ISOCHRONOUS:
43094 +               type = "isochronous";
43095 +               break;
43096 +       case UE_INTERRUPT:
43097 +               type = "interrupt";
43098 +               break;
43099 +       case UE_CONTROL:
43100 +               type = "control";
43101 +               break;
43102 +       case UE_BULK:
43103 +               type = "bulk";
43104 +               break;
43105 +       default:
43106 +               type = "?";
43107 +               break;
43108 +       }
43109 +
43110 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Type = %s\n", type);
43111 +
43112 +#ifdef DEBUG
43113 +       if (qh->ep_type == UE_INTERRUPT) {
43114 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
43115 +                           qh->usecs);
43116 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
43117 +                           qh->interval);
43118 +       }
43119 +#endif
43120 +
43121 +}
43122 +
43123 +/**
43124 + * This function allocates and initializes a QH.
43125 + *
43126 + * @param hcd The HCD state structure for the DWC OTG controller.
43127 + * @param urb Holds the information about the device/endpoint that we need
43128 + *           to initialize the QH.
43129 + * @param atomic_alloc Flag to do atomic allocation if needed
43130 + *
43131 + * @return Returns pointer to the newly allocated QH, or NULL on error. */
43132 +dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
43133 +                                   dwc_otg_hcd_urb_t * urb, int atomic_alloc)
43134 +{
43135 +       dwc_otg_qh_t *qh;
43136 +
43137 +       /* Allocate memory */
43138 +       /** @todo add memflags argument */
43139 +       qh = dwc_otg_hcd_qh_alloc(atomic_alloc);
43140 +       if (qh == NULL) {
43141 +               DWC_ERROR("qh allocation failed");
43142 +               return NULL;
43143 +       }
43144 +
43145 +       qh_init(hcd, qh, urb);
43146 +
43147 +       if (hcd->core_if->dma_desc_enable
43148 +           && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) {
43149 +               dwc_otg_hcd_qh_free(hcd, qh);
43150 +               return NULL;
43151 +       }
43152 +
43153 +       return qh;
43154 +}
43155 +
43156 +/* microframe_schedule=0 start */
43157 +
43158 +/**
43159 + * Checks that a channel is available for a periodic transfer.
43160 + *
43161 + * @return 0 if successful, negative error code otherise.
43162 + */
43163 +static int periodic_channel_available(dwc_otg_hcd_t * hcd)
43164 +{
43165 +       /*
43166 +        * Currently assuming that there is a dedicated host channnel for each
43167 +        * periodic transaction plus at least one host channel for
43168 +        * non-periodic transactions.
43169 +        */
43170 +       int status;
43171 +       int num_channels;
43172 +
43173 +       num_channels = hcd->core_if->core_params->host_channels;
43174 +       if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels)
43175 +           && (hcd->periodic_channels < num_channels - 1)) {
43176 +               status = 0;
43177 +       } else {
43178 +               DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
43179 +                       __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels);    //NOTICE
43180 +               status = -DWC_E_NO_SPACE;
43181 +       }
43182 +
43183 +       return status;
43184 +}
43185 +
43186 +/**
43187 + * Checks that there is sufficient bandwidth for the specified QH in the
43188 + * periodic schedule. For simplicity, this calculation assumes that all the
43189 + * transfers in the periodic schedule may occur in the same (micro)frame.
43190 + *
43191 + * @param hcd The HCD state structure for the DWC OTG controller.
43192 + * @param qh QH containing periodic bandwidth required.
43193 + *
43194 + * @return 0 if successful, negative error code otherwise.
43195 + */
43196 +static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43197 +{
43198 +       int status;
43199 +       int16_t max_claimed_usecs;
43200 +
43201 +       status = 0;
43202 +
43203 +       if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) {
43204 +               /*
43205 +                * High speed mode.
43206 +                * Max periodic usecs is 80% x 125 usec = 100 usec.
43207 +                */
43208 +
43209 +               max_claimed_usecs = 100 - qh->usecs;
43210 +       } else {
43211 +               /*
43212 +                * Full speed mode.
43213 +                * Max periodic usecs is 90% x 1000 usec = 900 usec.
43214 +                */
43215 +               max_claimed_usecs = 900 - qh->usecs;
43216 +       }
43217 +
43218 +       if (hcd->periodic_usecs > max_claimed_usecs) {
43219 +               DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs);        //NOTICE
43220 +               status = -DWC_E_NO_SPACE;
43221 +       }
43222 +
43223 +       return status;
43224 +}
43225 +
43226 +/* microframe_schedule=0 end */
43227 +
43228 +/**
43229 + * Microframe scheduler
43230 + * track the total use in hcd->frame_usecs
43231 + * keep each qh use in qh->frame_usecs
43232 + * when surrendering the qh then donate the time back
43233 + */
43234 +const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };
43235 +
43236 +/*
43237 + * called from dwc_otg_hcd.c:dwc_otg_hcd_init
43238 + */
43239 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
43240 +{
43241 +       int i;
43242 +       for (i=0; i<8; i++) {
43243 +               _hcd->frame_usecs[i] = max_uframe_usecs[i];
43244 +       }
43245 +       return 0;
43246 +}
43247 +
43248 +static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43249 +{
43250 +       int i;
43251 +       unsigned short utime;
43252 +       int t_left;
43253 +       int ret;
43254 +       int done;
43255 +
43256 +       ret = -1;
43257 +       utime = _qh->usecs;
43258 +       t_left = utime;
43259 +       i = 0;
43260 +       done = 0;
43261 +       while (done == 0) {
43262 +               /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */
43263 +               if (utime <= _hcd->frame_usecs[i]) {
43264 +                       _hcd->frame_usecs[i] -= utime;
43265 +                       _qh->frame_usecs[i] += utime;
43266 +                       t_left -= utime;
43267 +                       ret = i;
43268 +                       done = 1;
43269 +                       return ret;
43270 +               } else {
43271 +                       i++;
43272 +                       if (i == 8) {
43273 +                               done = 1;
43274 +                               ret = -1;
43275 +                       }
43276 +               }
43277 +       }
43278 +       return ret;
43279 + }
43280 +
43281 +/*
43282 + * use this for FS apps that can span multiple uframes
43283 +  */
43284 +static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43285 +{
43286 +       int i;
43287 +       int j;
43288 +       unsigned short utime;
43289 +       int t_left;
43290 +       int ret;
43291 +       int done;
43292 +       unsigned short xtime;
43293 +
43294 +       ret = -1;
43295 +       utime = _qh->usecs;
43296 +       t_left = utime;
43297 +       i = 0;
43298 +       done = 0;
43299 +loop:
43300 +       while (done == 0) {
43301 +               if(_hcd->frame_usecs[i] <= 0) {
43302 +                       i++;
43303 +                       if (i == 8) {
43304 +                               done = 1;
43305 +                               ret = -1;
43306 +                       }
43307 +                       goto loop;
43308 +               }
43309 +
43310 +               /*
43311 +                * we need n consecutive slots
43312 +                * so use j as a start slot j plus j+1 must be enough time (for now)
43313 +                */
43314 +               xtime= _hcd->frame_usecs[i];
43315 +               for (j = i+1 ; j < 8 ; j++ ) {
43316 +                       /*
43317 +                        * if we add this frame remaining time to xtime we may
43318 +                        * be OK, if not we need to test j for a complete frame
43319 +                        */
43320 +                       if ((xtime+_hcd->frame_usecs[j]) < utime) {
43321 +                               if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) {
43322 +                                       j = 8;
43323 +                                       ret = -1;
43324 +                                       continue;
43325 +                               }
43326 +                       }
43327 +                       if (xtime >= utime) {
43328 +                               ret = i;
43329 +                               j = 8;  /* stop loop with a good value ret */
43330 +                               continue;
43331 +                       }
43332 +                       /* add the frame time to x time */
43333 +                       xtime += _hcd->frame_usecs[j];
43334 +                      /* we must have a fully available next frame or break */
43335 +                      if ((xtime < utime)
43336 +                                      && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) {
43337 +                              ret = -1;
43338 +                              j = 8;  /* stop loop with a bad value ret */
43339 +                              continue;
43340 +                      }
43341 +               }
43342 +               if (ret >= 0) {
43343 +                       t_left = utime;
43344 +                       for (j = i; (t_left>0) && (j < 8); j++ ) {
43345 +                               t_left -= _hcd->frame_usecs[j];
43346 +                               if ( t_left <= 0 ) {
43347 +                                       _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left;
43348 +                                       _hcd->frame_usecs[j]= -t_left;
43349 +                                       ret = i;
43350 +                                       done = 1;
43351 +                               } else {
43352 +                                       _qh->frame_usecs[j] += _hcd->frame_usecs[j];
43353 +                                       _hcd->frame_usecs[j] = 0;
43354 +                               }
43355 +                       }
43356 +               } else {
43357 +                       i++;
43358 +                       if (i == 8) {
43359 +                               done = 1;
43360 +                               ret = -1;
43361 +                       }
43362 +               }
43363 +       }
43364 +       return ret;
43365 +}
43366 +
43367 +static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43368 +{
43369 +       int ret;
43370 +       ret = -1;
43371 +
43372 +       if (_qh->speed == USB_SPEED_HIGH) {
43373 +               /* if this is a hs transaction we need a full frame */
43374 +               ret = find_single_uframe(_hcd, _qh);
43375 +       } else {
43376 +               /* if this is a fs transaction we may need a sequence of frames */
43377 +               ret = find_multi_uframe(_hcd, _qh);
43378 +       }
43379 +       return ret;
43380 +}
43381 +
43382 +/**
43383 + * Checks that the max transfer size allowed in a host channel is large enough
43384 + * to handle the maximum data transfer in a single (micro)frame for a periodic
43385 + * transfer.
43386 + *
43387 + * @param hcd The HCD state structure for the DWC OTG controller.
43388 + * @param qh QH for a periodic endpoint.
43389 + *
43390 + * @return 0 if successful, negative error code otherwise.
43391 + */
43392 +static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43393 +{
43394 +       int status;
43395 +       uint32_t max_xfer_size;
43396 +       uint32_t max_channel_xfer_size;
43397 +
43398 +       status = 0;
43399 +
43400 +       max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
43401 +       max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
43402 +
43403 +       if (max_xfer_size > max_channel_xfer_size) {
43404 +               DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n",
43405 +                               __func__, max_xfer_size, max_channel_xfer_size);        //NOTICE
43406 +               status = -DWC_E_NO_SPACE;
43407 +       }
43408 +
43409 +       return status;
43410 +}
43411 +
43412 +/**
43413 + * Schedules an interrupt or isochronous transfer in the periodic schedule.
43414 + *
43415 + * @param hcd The HCD state structure for the DWC OTG controller.
43416 + * @param qh QH for the periodic transfer. The QH should already contain the
43417 + * scheduling information.
43418 + *
43419 + * @return 0 if successful, negative error code otherwise.
43420 + */
43421 +static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43422 +{
43423 +       int status = 0;
43424 +
43425 +       if (microframe_schedule) {
43426 +               int frame;
43427 +               status = find_uframe(hcd, qh);
43428 +               frame = -1;
43429 +               if (status == 0) {
43430 +                       frame = 7;
43431 +               } else {
43432 +                       if (status > 0 )
43433 +                               frame = status-1;
43434 +               }
43435 +
43436 +               /* Set the new frame up */
43437 +               if (frame > -1) {
43438 +                       qh->sched_frame &= ~0x7;
43439 +                       qh->sched_frame |= (frame & 7);
43440 +               }
43441 +
43442 +               if (status != -1)
43443 +                       status = 0;
43444 +       } else {
43445 +               status = periodic_channel_available(hcd);
43446 +               if (status) {
43447 +                       DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__);        //NOTICE
43448 +                       return status;
43449 +               }
43450 +
43451 +               status = check_periodic_bandwidth(hcd, qh);
43452 +       }
43453 +       if (status) {
43454 +               DWC_INFO("%s: Insufficient periodic bandwidth for "
43455 +                           "periodic transfer.\n", __func__);
43456 +               return status;
43457 +       }
43458 +       status = check_max_xfer_size(hcd, qh);
43459 +       if (status) {
43460 +               DWC_INFO("%s: Channel max transfer size too small "
43461 +                           "for periodic transfer.\n", __func__);
43462 +               return status;
43463 +       }
43464 +
43465 +       if (hcd->core_if->dma_desc_enable) {
43466 +               /* Don't rely on SOF and start in ready schedule */
43467 +               DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
43468 +       }
43469 +       else {
43470 +       /* Always start in the inactive schedule. */
43471 +       DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
43472 +       }
43473 +
43474 +       if (!microframe_schedule) {
43475 +               /* Reserve the periodic channel. */
43476 +               hcd->periodic_channels++;
43477 +       }
43478 +
43479 +       /* Update claimed usecs per (micro)frame. */
43480 +       hcd->periodic_usecs += qh->usecs;
43481 +
43482 +       return status;
43483 +}
43484 +
43485 +/**
43486 + * This function adds a QH to either the non periodic or periodic schedule if
43487 + * it is not already in the schedule. If the QH is already in the schedule, no
43488 + * action is taken.
43489 + *
43490 + * @return 0 if successful, negative error code otherwise.
43491 + */
43492 +int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43493 +{
43494 +       int status = 0;
43495 +       gintmsk_data_t intr_mask = {.d32 = 0 };
43496 +
43497 +       if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43498 +               /* QH already in a schedule. */
43499 +               return status;
43500 +       }
43501 +
43502 +       /* Add the new QH to the appropriate schedule */
43503 +       if (dwc_qh_is_non_per(qh)) {
43504 +               /* Always start in the inactive schedule. */
43505 +               DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
43506 +                                    &qh->qh_list_entry);
43507 +       } else {
43508 +               status = schedule_periodic(hcd, qh);
43509 +               if ( !hcd->periodic_qh_count ) {
43510 +                       intr_mask.b.sofintr = 1;
43511 +                       DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43512 +                                                               intr_mask.d32, intr_mask.d32);
43513 +               }
43514 +               hcd->periodic_qh_count++;
43515 +       }
43516 +
43517 +       return status;
43518 +}
43519 +
43520 +/**
43521 + * Removes an interrupt or isochronous transfer from the periodic schedule.
43522 + *
43523 + * @param hcd The HCD state structure for the DWC OTG controller.
43524 + * @param qh QH for the periodic transfer.
43525 + */
43526 +static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43527 +{
43528 +       int i;
43529 +       DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43530 +
43531 +       /* Update claimed usecs per (micro)frame. */
43532 +       hcd->periodic_usecs -= qh->usecs;
43533 +
43534 +       if (!microframe_schedule) {
43535 +               /* Release the periodic channel reservation. */
43536 +               hcd->periodic_channels--;
43537 +       } else {
43538 +               for (i = 0; i < 8; i++) {
43539 +                       hcd->frame_usecs[i] += qh->frame_usecs[i];
43540 +                       qh->frame_usecs[i] = 0;
43541 +               }
43542 +       }
43543 +}
43544 +
43545 +/** 
43546 + * Removes a QH from either the non-periodic or periodic schedule.  Memory is
43547 + * not freed.
43548 + *
43549 + * @param hcd The HCD state structure.
43550 + * @param qh QH to remove from schedule. */
43551 +void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43552 +{
43553 +       gintmsk_data_t intr_mask = {.d32 = 0 };
43554 +
43555 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43556 +               /* QH is not in a schedule. */
43557 +               return;
43558 +       }
43559 +
43560 +       if (dwc_qh_is_non_per(qh)) {
43561 +               if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {
43562 +                       hcd->non_periodic_qh_ptr =
43563 +                           hcd->non_periodic_qh_ptr->next;
43564 +               }
43565 +               DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43566 +       } else {
43567 +               deschedule_periodic(hcd, qh);
43568 +               hcd->periodic_qh_count--;
43569 +               if( !hcd->periodic_qh_count ) {
43570 +                       intr_mask.b.sofintr = 1;
43571 +                               DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43572 +                                                                       intr_mask.d32, 0);
43573 +               }
43574 +       }
43575 +}
43576 +
43577 +/**
43578 + * Deactivates a QH. For non-periodic QHs, removes the QH from the active
43579 + * non-periodic schedule. The QH is added to the inactive non-periodic
43580 + * schedule if any QTDs are still attached to the QH.
43581 + *
43582 + * For periodic QHs, the QH is removed from the periodic queued schedule. If
43583 + * there are any QTDs still attached to the QH, the QH is added to either the
43584 + * periodic inactive schedule or the periodic ready schedule and its next
43585 + * scheduled frame is calculated. The QH is placed in the ready schedule if
43586 + * the scheduled frame has been reached already. Otherwise it's placed in the
43587 + * inactive schedule. If there are no QTDs attached to the QH, the QH is
43588 + * completely removed from the periodic schedule.
43589 + */
43590 +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
43591 +                              int sched_next_periodic_split)
43592 +{      
43593 +       if (dwc_qh_is_non_per(qh)) {
43594 +               dwc_otg_hcd_qh_remove(hcd, qh);
43595 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43596 +                       /* Add back to inactive non-periodic schedule. */
43597 +                       dwc_otg_hcd_qh_add(hcd, qh);
43598 +               }
43599 +       } else {
43600 +               uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
43601 +
43602 +               if (qh->do_split) {
43603 +                       /* Schedule the next continuing periodic split transfer */
43604 +                       if (sched_next_periodic_split) {
43605 +
43606 +                               qh->sched_frame = frame_number;
43607 +                               if (dwc_frame_num_le(frame_number,
43608 +                                                    dwc_frame_num_inc
43609 +                                                    (qh->start_split_frame,
43610 +                                                     1))) {
43611 +                                       /*
43612 +                                        * Allow one frame to elapse after start
43613 +                                        * split microframe before scheduling
43614 +                                        * complete split, but DONT if we are
43615 +                                        * doing the next start split in the
43616 +                                        * same frame for an ISOC out.
43617 +                                        */
43618 +                                       if ((qh->ep_type != UE_ISOCHRONOUS) ||
43619 +                                           (qh->ep_is_in != 0)) {
43620 +                                               qh->sched_frame =
43621 +                                                   dwc_frame_num_inc(qh->sched_frame, 1);
43622 +                                       }
43623 +                               }
43624 +                       } else {
43625 +                               qh->sched_frame =
43626 +                                   dwc_frame_num_inc(qh->start_split_frame,
43627 +                                                     qh->interval);
43628 +                               if (dwc_frame_num_le
43629 +                                   (qh->sched_frame, frame_number)) {
43630 +                                       qh->sched_frame = frame_number;
43631 +                               }
43632 +                               qh->sched_frame |= 0x7;
43633 +                               qh->start_split_frame = qh->sched_frame;
43634 +                       }
43635 +               } else {
43636 +                       qh->sched_frame =
43637 +                           dwc_frame_num_inc(qh->sched_frame, qh->interval);
43638 +                       if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
43639 +                               qh->sched_frame = frame_number;
43640 +                       }
43641 +               }
43642 +
43643 +               if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43644 +                       dwc_otg_hcd_qh_remove(hcd, qh);
43645 +               } else {
43646 +                       /*
43647 +                        * Remove from periodic_sched_queued and move to
43648 +                        * appropriate queue.
43649 +                        */
43650 +                       if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) ||
43651 +                       (!microframe_schedule && qh->sched_frame == frame_number)) {
43652 +                               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
43653 +                                                  &qh->qh_list_entry);
43654 +                       } else {
43655 +                               DWC_LIST_MOVE_HEAD
43656 +                                   (&hcd->periodic_sched_inactive,
43657 +                                    &qh->qh_list_entry);
43658 +                       }
43659 +               }
43660 +       }
43661 +}
43662 +
43663 +/** 
43664 + * This function allocates and initializes a QTD. 
43665 + *
43666 + * @param urb The URB to create a QTD from.  Each URB-QTD pair will end up
43667 + *           pointing to each other so each pair should have a unique correlation.
43668 + * @param atomic_alloc Flag to do atomic alloc if needed
43669 + *
43670 + * @return Returns pointer to the newly allocated QTD, or NULL on error. */
43671 +dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc)
43672 +{
43673 +       dwc_otg_qtd_t *qtd;
43674 +
43675 +       qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc);
43676 +       if (qtd == NULL) {
43677 +               return NULL;
43678 +       }
43679 +
43680 +       dwc_otg_hcd_qtd_init(qtd, urb);
43681 +       return qtd;
43682 +}
43683 +
43684 +/** 
43685 + * Initializes a QTD structure.
43686 + *
43687 + * @param qtd The QTD to initialize.
43688 + * @param urb The URB to use for initialization.  */
43689 +void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)
43690 +{
43691 +       dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t));
43692 +       qtd->urb = urb;
43693 +       if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) {
43694 +               /*
43695 +                * The only time the QTD data toggle is used is on the data
43696 +                * phase of control transfers. This phase always starts with
43697 +                * DATA1.
43698 +                */
43699 +               qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
43700 +               qtd->control_phase = DWC_OTG_CONTROL_SETUP;
43701 +       }
43702 +
43703 +       /* start split */
43704 +       qtd->complete_split = 0;
43705 +       qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
43706 +       qtd->isoc_split_offset = 0;
43707 +       qtd->in_process = 0;
43708 +
43709 +       /* Store the qtd ptr in the urb to reference what QTD. */
43710 +       urb->qtd = qtd;
43711 +       return;
43712 +}
43713 +
43714 +/**
43715 + * This function adds a QTD to the QTD-list of a QH.  It will find the correct
43716 + * QH to place the QTD into.  If it does not find a QH, then it will create a
43717 + * new QH. If the QH to which the QTD is added is not currently scheduled, it
43718 + * is placed into the proper schedule based on its EP type.
43719 + *
43720 + * @param[in] qtd The QTD to add
43721 + * @param[in] hcd The DWC HCD structure
43722 + * @param[out] qh out parameter to return queue head
43723 + * @param atomic_alloc Flag to do atomic alloc if needed
43724 + *
43725 + * @return 0 if successful, negative error code otherwise.
43726 + */
43727 +int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
43728 +                       dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
43729 +{
43730 +       int retval = 0;
43731 +       dwc_irqflags_t flags;
43732 +
43733 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
43734 +
43735 +       /*
43736 +        * Get the QH which holds the QTD-list to insert to. Create QH if it
43737 +        * doesn't exist.
43738 +        */
43739 +       if (*qh == NULL) {
43740 +               *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
43741 +               if (*qh == NULL) {
43742 +                       retval = -1;
43743 +                       goto done;
43744 +               }
43745 +       }
43746 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
43747 +       retval = dwc_otg_hcd_qh_add(hcd, *qh);
43748 +       if (retval == 0) {
43749 +               DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
43750 +                                       qtd_list_entry);
43751 +       }
43752 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
43753 +
43754 +done:
43755 +
43756 +       return retval;
43757 +}
43758 +
43759 +#endif /* DWC_DEVICE_ONLY */
43760 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
43761 new file mode 100644
43762 index 0000000..a7e9076
43763 --- /dev/null
43764 +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
43765 @@ -0,0 +1,185 @@
43766 +#ifndef _DWC_OS_DEP_H_
43767 +#define _DWC_OS_DEP_H_
43768 +
43769 +/**
43770 + * @file
43771 + *
43772 + * This file contains OS dependent structures.
43773 + *
43774 + */
43775 +
43776 +#include <linux/kernel.h>
43777 +#include <linux/module.h>
43778 +#include <linux/moduleparam.h>
43779 +#include <linux/init.h>
43780 +#include <linux/device.h>
43781 +#include <linux/errno.h>
43782 +#include <linux/types.h>
43783 +#include <linux/slab.h>
43784 +#include <linux/list.h>
43785 +#include <linux/interrupt.h>
43786 +#include <linux/ctype.h>
43787 +#include <linux/string.h>
43788 +#include <linux/dma-mapping.h>
43789 +#include <linux/jiffies.h>
43790 +#include <linux/delay.h>
43791 +#include <linux/timer.h>
43792 +#include <linux/workqueue.h>
43793 +#include <linux/stat.h>
43794 +#include <linux/pci.h>
43795 +
43796 +#include <linux/version.h>
43797 +
43798 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
43799 +# include <linux/irq.h>
43800 +#endif
43801 +
43802 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
43803 +# include <linux/usb/ch9.h>
43804 +#else
43805 +# include <linux/usb_ch9.h>
43806 +#endif
43807 +
43808 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
43809 +# include <linux/usb/gadget.h>
43810 +#else
43811 +# include <linux/usb_gadget.h>
43812 +#endif
43813 +
43814 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
43815 +# include <asm/irq.h>
43816 +#endif
43817 +
43818 +#ifdef PCI_INTERFACE
43819 +# include <asm/io.h>
43820 +#endif
43821 +
43822 +#ifdef LM_INTERFACE
43823 +# include <asm/unaligned.h>
43824 +# include <asm/sizes.h>
43825 +# include <asm/param.h>
43826 +# include <asm/io.h>
43827 +# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
43828 +#  include <asm/arch/hardware.h>
43829 +#  include <asm/arch/lm.h>
43830 +#  include <asm/arch/irqs.h>
43831 +#  include <asm/arch/regs-irq.h>
43832 +# else
43833 +/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -
43834 +   here we assume that the machine architecture provides definitions
43835 +   in its own header
43836 +*/
43837 +#  include <mach/lm.h>
43838 +#  include <mach/hardware.h>
43839 +# endif
43840 +#endif
43841 +
43842 +#ifdef PLATFORM_INTERFACE
43843 +#include <linux/platform_device.h>
43844 +#include <asm/mach/map.h>
43845 +#endif
43846 +
43847 +/** The OS page size */
43848 +#define DWC_OS_PAGE_SIZE       PAGE_SIZE
43849 +
43850 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
43851 +typedef int gfp_t;
43852 +#endif
43853 +
43854 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
43855 +# define IRQF_SHARED SA_SHIRQ
43856 +#endif
43857 +
43858 +typedef struct os_dependent {
43859 +       /** Base address returned from ioremap() */
43860 +       void *base;
43861 +
43862 +       /** Register offset for Diagnostic API */
43863 +       uint32_t reg_offset;
43864 +
43865 +#ifdef LM_INTERFACE
43866 +       struct lm_device *lmdev;
43867 +#elif  defined(PCI_INTERFACE)
43868 +       struct pci_dev *pcidev;
43869 +
43870 +       /** Start address of a PCI region */
43871 +       resource_size_t rsrc_start;
43872 +       
43873 +       /** Length address of a PCI region */
43874 +       resource_size_t rsrc_len;
43875 +#elif  defined(PLATFORM_INTERFACE)
43876 +       struct platform_device *platformdev;
43877 +#endif
43878 +
43879 +} os_dependent_t;
43880 +
43881 +#ifdef __cplusplus
43882 +}
43883 +#endif
43884 +
43885 +
43886 +
43887 +/* Type for the our device on the chosen bus */
43888 +#if   defined(LM_INTERFACE)
43889 +typedef struct lm_device       dwc_bus_dev_t;
43890 +#elif defined(PCI_INTERFACE)
43891 +typedef struct pci_dev         dwc_bus_dev_t;
43892 +#elif defined(PLATFORM_INTERFACE)
43893 +typedef struct platform_device dwc_bus_dev_t;
43894 +#endif
43895 +
43896 +/* Helper macro to retrieve drvdata from the device on the chosen bus */
43897 +#if    defined(LM_INTERFACE)
43898 +#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev)
43899 +#elif  defined(PCI_INTERFACE)
43900 +#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev)
43901 +#elif  defined(PLATFORM_INTERFACE)
43902 +#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev)
43903 +#endif
43904 +
43905 +/**
43906 + * Helper macro returning the otg_device structure of a given struct device
43907 + *
43908 + * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
43909 + */
43910 +#ifdef LM_INTERFACE
43911 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43912 +                struct lm_device *lm_dev = \
43913 +                        container_of(_dev, struct lm_device, dev); \
43914 +                _var = lm_get_drvdata(lm_dev); \
43915 +        } while (0)
43916 +
43917 +#elif defined(PCI_INTERFACE)
43918 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43919 +                _var = dev_get_drvdata(_dev); \
43920 +        } while (0)
43921 +
43922 +#elif defined(PLATFORM_INTERFACE)
43923 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43924 +                struct platform_device *platform_dev = \
43925 +                        container_of(_dev, struct platform_device, dev); \
43926 +                _var = platform_get_drvdata(platform_dev); \
43927 +        } while (0)
43928 +#endif
43929 +
43930 +
43931 +/**
43932 + * Helper macro returning the struct dev of the given struct os_dependent
43933 + *
43934 + * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep)
43935 + */
43936 +#ifdef LM_INTERFACE
43937 +#define DWC_OTG_OS_GETDEV(_osdep) \
43938 +        ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev)
43939 +#elif defined(PCI_INTERFACE)
43940 +#define DWC_OTG_OS_GETDEV(_osdep) \
43941 +        ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev)
43942 +#elif defined(PLATFORM_INTERFACE)
43943 +#define DWC_OTG_OS_GETDEV(_osdep) \
43944 +        ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev)
43945 +#endif
43946 +
43947 +
43948 +
43949 +
43950 +#endif /* _DWC_OS_DEP_H_ */
43951 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
43952 new file mode 100644
43953 index 0000000..c97d65c
43954 --- /dev/null
43955 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
43956 @@ -0,0 +1,2708 @@
43957 +/* ==========================================================================
43958 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
43959 + * $Revision: #101 $
43960 + * $Date: 2012/08/10 $
43961 + * $Change: 2047372 $
43962 + *
43963 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
43964 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
43965 + * otherwise expressly agreed to in writing between Synopsys and you.
43966 + *
43967 + * The Software IS NOT an item of Licensed Software or Licensed Product under
43968 + * any End User Software License Agreement or Agreement for Licensed Product
43969 + * with Synopsys or any supplement thereto. You are permitted to use and
43970 + * redistribute this Software in source and binary forms, with or without
43971 + * modification, provided that redistributions of source code must retain this
43972 + * notice. You may not view, use, disclose, copy or distribute this file or
43973 + * any information contained herein except pursuant to this license grant from
43974 + * Synopsys. If you do not agree with this notice, including the disclaimer
43975 + * below, then you are not authorized to use the Software.
43976 + *
43977 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
43978 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43979 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43980 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
43981 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43982 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43983 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
43984 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43985 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43986 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
43987 + * DAMAGE.
43988 + * ========================================================================== */
43989 +#ifndef DWC_HOST_ONLY
43990 +
43991 +/** @file
43992 + * This file implements PCD Core. All code in this file is portable and doesn't
43993 + * use any OS specific functions.
43994 + * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
43995 + * header file, which can be used to implement OS specific PCD interface.
43996 + *
43997 + * An important function of the PCD is managing interrupts generated
43998 + * by the DWC_otg controller. The implementation of the DWC_otg device
43999 + * mode interrupt service routines is in dwc_otg_pcd_intr.c.
44000 + *
44001 + * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
44002 + * @todo Does it work when the request size is greater than DEPTSIZ
44003 + * transfer size
44004 + *
44005 + */
44006 +
44007 +#include "dwc_otg_pcd.h"
44008 +
44009 +#ifdef DWC_UTE_CFI
44010 +#include "dwc_otg_cfi.h"
44011 +
44012 +extern int init_cfi(cfiobject_t * cfiobj);
44013 +#endif
44014 +
44015 +/**
44016 + * Choose endpoint from ep arrays using usb_ep structure.
44017 + */
44018 +static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
44019 +{
44020 +       int i;
44021 +       if (pcd->ep0.priv == handle) {
44022 +               return &pcd->ep0;
44023 +       }
44024 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
44025 +               if (pcd->in_ep[i].priv == handle)
44026 +                       return &pcd->in_ep[i];
44027 +               if (pcd->out_ep[i].priv == handle)
44028 +                       return &pcd->out_ep[i];
44029 +       }
44030 +
44031 +       return NULL;
44032 +}
44033 +
44034 +/**
44035 + * This function completes a request.  It call's the request call back.
44036 + */
44037 +void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
44038 +                         int32_t status)
44039 +{
44040 +       unsigned stopped = ep->stopped;
44041 +       
44042 +       DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);
44043 +       DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
44044 +
44045 +       /* don't modify queue heads during completion callback */
44046 +       ep->stopped = 1;
44047 +       /* spin_unlock/spin_lock now done in fops->complete() */
44048 +       ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
44049 +                               req->actual);
44050 +
44051 +       if (ep->pcd->request_pending > 0) {
44052 +               --ep->pcd->request_pending;
44053 +       }
44054 +
44055 +       ep->stopped = stopped;
44056 +       DWC_FREE(req);
44057 +}
44058 +
44059 +/**
44060 + * This function terminates all the requsts in the EP request queue.
44061 + */
44062 +void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
44063 +{
44064 +       dwc_otg_pcd_request_t *req;
44065 +
44066 +       ep->stopped = 1;
44067 +
44068 +       /* called with irqs blocked?? */
44069 +       while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
44070 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
44071 +               dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
44072 +       }
44073 +}
44074 +
44075 +void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
44076 +                      const struct dwc_otg_pcd_function_ops *fops)
44077 +{
44078 +       pcd->fops = fops;
44079 +}
44080 +
44081 +/**
44082 + * PCD Callback function for initializing the PCD when switching to
44083 + * device mode.
44084 + *
44085 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44086 + */
44087 +static int32_t dwc_otg_pcd_start_cb(void *p)
44088 +{
44089 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44090 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
44091 +
44092 +       /*
44093 +        * Initialized the Core for Device mode.
44094 +        */
44095 +       if (dwc_otg_is_device_mode(core_if)) {
44096 +               dwc_otg_core_dev_init(core_if);
44097 +               /* Set core_if's lock pointer to the pcd->lock */
44098 +               core_if->lock = pcd->lock;
44099 +       }
44100 +       return 1;
44101 +}
44102 +
44103 +/** CFI-specific buffer allocation function for EP */
44104 +#ifdef DWC_UTE_CFI
44105 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
44106 +                             size_t buflen, int flags)
44107 +{
44108 +       dwc_otg_pcd_ep_t *ep;
44109 +       ep = get_ep_from_handle(pcd, pep);
44110 +       if (!ep) {
44111 +               DWC_WARN("bad ep\n");
44112 +               return -DWC_E_INVALID;
44113 +       }
44114 +
44115 +       return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
44116 +                                         flags);
44117 +}
44118 +#else
44119 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
44120 +                             size_t buflen, int flags);
44121 +#endif
44122 +
44123 +/**
44124 + * PCD Callback function for notifying the PCD when resuming from
44125 + * suspend.
44126 + *
44127 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44128 + */
44129 +static int32_t dwc_otg_pcd_resume_cb(void *p)
44130 +{
44131 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44132 +
44133 +       if (pcd->fops->resume) {
44134 +               pcd->fops->resume(pcd);
44135 +       }
44136 +
44137 +       /* Stop the SRP timeout timer. */
44138 +       if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
44139 +           || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
44140 +               if (GET_CORE_IF(pcd)->srp_timer_started) {
44141 +                       GET_CORE_IF(pcd)->srp_timer_started = 0;
44142 +                       DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer);
44143 +               }
44144 +       }
44145 +       return 1;
44146 +}
44147 +
44148 +/**
44149 + * PCD Callback function for notifying the PCD device is suspended.
44150 + *
44151 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44152 + */
44153 +static int32_t dwc_otg_pcd_suspend_cb(void *p)
44154 +{
44155 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44156 +
44157 +       if (pcd->fops->suspend) {
44158 +               DWC_SPINUNLOCK(pcd->lock);
44159 +               pcd->fops->suspend(pcd);
44160 +               DWC_SPINLOCK(pcd->lock);
44161 +       }
44162 +
44163 +       return 1;
44164 +}
44165 +
44166 +/**
44167 + * PCD Callback function for stopping the PCD when switching to Host
44168 + * mode.
44169 + *
44170 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44171 + */
44172 +static int32_t dwc_otg_pcd_stop_cb(void *p)
44173 +{
44174 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44175 +       extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
44176 +
44177 +       dwc_otg_pcd_stop(pcd);
44178 +       return 1;
44179 +}
44180 +
44181 +/**
44182 + * PCD Callback structure for handling mode switching.
44183 + */
44184 +static dwc_otg_cil_callbacks_t pcd_callbacks = {
44185 +       .start = dwc_otg_pcd_start_cb,
44186 +       .stop = dwc_otg_pcd_stop_cb,
44187 +       .suspend = dwc_otg_pcd_suspend_cb,
44188 +       .resume_wakeup = dwc_otg_pcd_resume_cb,
44189 +       .p = 0,                 /* Set at registration */
44190 +};
44191 +
44192 +/**
44193 + * This function allocates a DMA Descriptor chain for the Endpoint
44194 + * buffer to be used for a transfer to/from the specified endpoint.
44195 + */
44196 +dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr,
44197 +                                                   uint32_t count)
44198 +{
44199 +       return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), 
44200 +                                                       dma_desc_addr);
44201 +}
44202 +
44203 +/**
44204 + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc.
44205 + */
44206 +void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
44207 +                               uint32_t dma_desc_addr, uint32_t count)
44208 +{
44209 +       DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
44210 +                    dma_desc_addr);
44211 +}
44212 +
44213 +#ifdef DWC_EN_ISOC
44214 +
44215 +/**
44216 + * This function initializes a descriptor chain for Isochronous transfer
44217 + *
44218 + * @param core_if Programming view of DWC_otg controller.
44219 + * @param dwc_ep The EP to start the transfer on.
44220 + *
44221 + */
44222 +void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
44223 +                                       dwc_ep_t * dwc_ep)
44224 +{
44225 +
44226 +       dsts_data_t dsts = {.d32 = 0 };
44227 +       depctl_data_t depctl = {.d32 = 0 };
44228 +       volatile uint32_t *addr;
44229 +       int i, j;
44230 +       uint32_t len;
44231 +
44232 +       if (dwc_ep->is_in)
44233 +               dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
44234 +       else
44235 +               dwc_ep->desc_cnt =
44236 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44237 +                   dwc_ep->bInterval;
44238 +
44239 +       /** Allocate descriptors for double buffering */
44240 +       dwc_ep->iso_desc_addr =
44241 +           dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
44242 +                                       dwc_ep->desc_cnt * 2);
44243 +       if (dwc_ep->desc_addr) {
44244 +               DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
44245 +               return;
44246 +       }
44247 +
44248 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44249 +
44250 +       /** ISO OUT EP */
44251 +       if (dwc_ep->is_in == 0) {
44252 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
44253 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44254 +               dma_addr_t dma_ad;
44255 +               uint32_t data_per_desc;
44256 +               dwc_otg_dev_out_ep_regs_t *out_regs =
44257 +                   core_if->dev_if->out_ep_regs[dwc_ep->num];
44258 +               int offset;
44259 +
44260 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
44261 +               dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma));
44262 +
44263 +               /** Buffer 0 descriptors setup */
44264 +               dma_ad = dwc_ep->dma_addr0;
44265 +
44266 +               sts.b_iso_out.bs = BS_HOST_READY;
44267 +               sts.b_iso_out.rxsts = 0;
44268 +               sts.b_iso_out.l = 0;
44269 +               sts.b_iso_out.sp = 0;
44270 +               sts.b_iso_out.ioc = 0;
44271 +               sts.b_iso_out.pid = 0;
44272 +               sts.b_iso_out.framenum = 0;
44273 +
44274 +               offset = 0;
44275 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44276 +                    i += dwc_ep->pkt_per_frm) {
44277 +
44278 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44279 +                               uint32_t len = (j + 1) * dwc_ep->maxpacket;
44280 +                               if (len > dwc_ep->data_per_frame)
44281 +                                       data_per_desc =
44282 +                                           dwc_ep->data_per_frame -
44283 +                                           j * dwc_ep->maxpacket;
44284 +                               else
44285 +                                       data_per_desc = dwc_ep->maxpacket;
44286 +                               len = data_per_desc % 4;
44287 +                               if (len)
44288 +                                       data_per_desc += 4 - len;
44289 +
44290 +                               sts.b_iso_out.rxbytes = data_per_desc;
44291 +                               dma_desc->buf = dma_ad;
44292 +                               dma_desc->status.d32 = sts.d32;
44293 +
44294 +                               offset += data_per_desc;
44295 +                               dma_desc++;
44296 +                               dma_ad += data_per_desc;
44297 +                       }
44298 +               }
44299 +
44300 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44301 +                       uint32_t len = (j + 1) * dwc_ep->maxpacket;
44302 +                       if (len > dwc_ep->data_per_frame)
44303 +                               data_per_desc =
44304 +                                   dwc_ep->data_per_frame -
44305 +                                   j * dwc_ep->maxpacket;
44306 +                       else
44307 +                               data_per_desc = dwc_ep->maxpacket;
44308 +                       len = data_per_desc % 4;
44309 +                       if (len)
44310 +                               data_per_desc += 4 - len;
44311 +                       sts.b_iso_out.rxbytes = data_per_desc;
44312 +                       dma_desc->buf = dma_ad;
44313 +                       dma_desc->status.d32 = sts.d32;
44314 +
44315 +                       offset += data_per_desc;
44316 +                       dma_desc++;
44317 +                       dma_ad += data_per_desc;
44318 +               }
44319 +
44320 +               sts.b_iso_out.ioc = 1;
44321 +               len = (j + 1) * dwc_ep->maxpacket;
44322 +               if (len > dwc_ep->data_per_frame)
44323 +                       data_per_desc =
44324 +                           dwc_ep->data_per_frame - j * dwc_ep->maxpacket;
44325 +               else
44326 +                       data_per_desc = dwc_ep->maxpacket;
44327 +               len = data_per_desc % 4;
44328 +               if (len)
44329 +                       data_per_desc += 4 - len;
44330 +               sts.b_iso_out.rxbytes = data_per_desc;
44331 +
44332 +               dma_desc->buf = dma_ad;
44333 +               dma_desc->status.d32 = sts.d32;
44334 +               dma_desc++;
44335 +
44336 +               /** Buffer 1 descriptors setup */
44337 +               sts.b_iso_out.ioc = 0;
44338 +               dma_ad = dwc_ep->dma_addr1;
44339 +
44340 +               offset = 0;
44341 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44342 +                    i += dwc_ep->pkt_per_frm) {
44343 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44344 +                               uint32_t len = (j + 1) * dwc_ep->maxpacket;
44345 +                               if (len > dwc_ep->data_per_frame)
44346 +                                       data_per_desc =
44347 +                                           dwc_ep->data_per_frame -
44348 +                                           j * dwc_ep->maxpacket;
44349 +                               else
44350 +                                       data_per_desc = dwc_ep->maxpacket;
44351 +                               len = data_per_desc % 4;
44352 +                               if (len)
44353 +                                       data_per_desc += 4 - len;
44354 +
44355 +                               data_per_desc =
44356 +                                   sts.b_iso_out.rxbytes = data_per_desc;
44357 +                               dma_desc->buf = dma_ad;
44358 +                               dma_desc->status.d32 = sts.d32;
44359 +
44360 +                               offset += data_per_desc;
44361 +                               dma_desc++;
44362 +                               dma_ad += data_per_desc;
44363 +                       }
44364 +               }
44365 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44366 +                       data_per_desc =
44367 +                           ((j + 1) * dwc_ep->maxpacket >
44368 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44369 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44370 +                       data_per_desc +=
44371 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44372 +                       sts.b_iso_out.rxbytes = data_per_desc;
44373 +                       dma_desc->buf = dma_ad;
44374 +                       dma_desc->status.d32 = sts.d32;
44375 +
44376 +                       offset += data_per_desc;
44377 +                       dma_desc++;
44378 +                       dma_ad += data_per_desc;
44379 +               }
44380 +
44381 +               sts.b_iso_out.ioc = 1;
44382 +               sts.b_iso_out.l = 1;
44383 +               data_per_desc =
44384 +                   ((j + 1) * dwc_ep->maxpacket >
44385 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44386 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44387 +               data_per_desc +=
44388 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44389 +               sts.b_iso_out.rxbytes = data_per_desc;
44390 +
44391 +               dma_desc->buf = dma_ad;
44392 +               dma_desc->status.d32 = sts.d32;
44393 +
44394 +               dwc_ep->next_frame = 0;
44395 +
44396 +               /** Write dma_ad into DOEPDMA register */
44397 +               DWC_WRITE_REG32(&(out_regs->doepdma),
44398 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
44399 +
44400 +       }
44401 +       /** ISO IN EP */
44402 +       else {
44403 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
44404 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44405 +               dma_addr_t dma_ad;
44406 +               dwc_otg_dev_in_ep_regs_t *in_regs =
44407 +                   core_if->dev_if->in_ep_regs[dwc_ep->num];
44408 +               unsigned int frmnumber;
44409 +               fifosize_data_t txfifosize, rxfifosize;
44410 +
44411 +               txfifosize.d32 =
44412 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->
44413 +                                  dtxfsts);
44414 +               rxfifosize.d32 =
44415 +                   DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
44416 +
44417 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
44418 +
44419 +               dma_ad = dwc_ep->dma_addr0;
44420 +
44421 +               dsts.d32 =
44422 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44423 +
44424 +               sts.b_iso_in.bs = BS_HOST_READY;
44425 +               sts.b_iso_in.txsts = 0;
44426 +               sts.b_iso_in.sp =
44427 +                   (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
44428 +               sts.b_iso_in.ioc = 0;
44429 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
44430 +
44431 +               frmnumber = dwc_ep->next_frame;
44432 +
44433 +               sts.b_iso_in.framenum = frmnumber;
44434 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
44435 +               sts.b_iso_in.l = 0;
44436 +
44437 +               /** Buffer 0 descriptors setup */
44438 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
44439 +                       dma_desc->buf = dma_ad;
44440 +                       dma_desc->status.d32 = sts.d32;
44441 +                       dma_desc++;
44442 +
44443 +                       dma_ad += dwc_ep->data_per_frame;
44444 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
44445 +               }
44446 +
44447 +               sts.b_iso_in.ioc = 1;
44448 +               dma_desc->buf = dma_ad;
44449 +               dma_desc->status.d32 = sts.d32;
44450 +               ++dma_desc;
44451 +
44452 +               /** Buffer 1 descriptors setup */
44453 +               sts.b_iso_in.ioc = 0;
44454 +               dma_ad = dwc_ep->dma_addr1;
44455 +
44456 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44457 +                    i += dwc_ep->pkt_per_frm) {
44458 +                       dma_desc->buf = dma_ad;
44459 +                       dma_desc->status.d32 = sts.d32;
44460 +                       dma_desc++;
44461 +
44462 +                       dma_ad += dwc_ep->data_per_frame;
44463 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
44464 +
44465 +                       sts.b_iso_in.ioc = 0;
44466 +               }
44467 +               sts.b_iso_in.ioc = 1;
44468 +               sts.b_iso_in.l = 1;
44469 +
44470 +               dma_desc->buf = dma_ad;
44471 +               dma_desc->status.d32 = sts.d32;
44472 +
44473 +               dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
44474 +
44475 +               /** Write dma_ad into diepdma register */
44476 +               DWC_WRITE_REG32(&(in_regs->diepdma),
44477 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
44478 +       }
44479 +       /** Enable endpoint, clear nak  */
44480 +       depctl.d32 = 0;
44481 +       depctl.b.epena = 1;
44482 +       depctl.b.usbactep = 1;
44483 +       depctl.b.cnak = 1;
44484 +
44485 +       DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44486 +       depctl.d32 = DWC_READ_REG32(addr);
44487 +}
44488 +
44489 +/**
44490 + * This function initializes a descriptor chain for Isochronous transfer
44491 + *
44492 + * @param core_if Programming view of DWC_otg controller.
44493 + * @param ep The EP to start the transfer on.
44494 + *
44495 + */
44496 +void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
44497 +                                      dwc_ep_t * ep)
44498 +{
44499 +       depctl_data_t depctl = {.d32 = 0 };
44500 +       volatile uint32_t *addr;
44501 +
44502 +       if (ep->is_in) {
44503 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44504 +       } else {
44505 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44506 +       }
44507 +
44508 +       if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
44509 +               return;
44510 +       } else {
44511 +               deptsiz_data_t deptsiz = {.d32 = 0 };
44512 +
44513 +               ep->xfer_len =
44514 +                   ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
44515 +               ep->pkt_cnt =
44516 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44517 +               ep->xfer_count = 0;
44518 +               ep->xfer_buff =
44519 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44520 +               ep->dma_addr =
44521 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44522 +
44523 +               if (ep->is_in) {
44524 +                       /* Program the transfer size and packet count
44525 +                        *      as follows: xfersize = N * maxpacket +
44526 +                        *      short_packet pktcnt = N + (short_packet
44527 +                        *      exist ? 1 : 0) 
44528 +                        */
44529 +                       deptsiz.b.mc = ep->pkt_per_frm;
44530 +                       deptsiz.b.xfersize = ep->xfer_len;
44531 +                       deptsiz.b.pktcnt =
44532 +                           (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44533 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
44534 +                                       dieptsiz, deptsiz.d32);
44535 +
44536 +                       /* Write the DMA register */
44537 +                       DWC_WRITE_REG32(&
44538 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
44539 +                                        diepdma), (uint32_t) ep->dma_addr);
44540 +
44541 +               } else {
44542 +                       deptsiz.b.pktcnt =
44543 +                           (ep->xfer_len + (ep->maxpacket - 1)) /
44544 +                           ep->maxpacket;
44545 +                       deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
44546 +
44547 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
44548 +                                       doeptsiz, deptsiz.d32);
44549 +
44550 +                       /* Write the DMA register */
44551 +                       DWC_WRITE_REG32(&
44552 +                                       (core_if->dev_if->out_ep_regs[ep->num]->
44553 +                                        doepdma), (uint32_t) ep->dma_addr);
44554 +
44555 +               }
44556 +               /** Enable endpoint, clear nak  */
44557 +               depctl.d32 = 0;
44558 +               depctl.b.epena = 1;
44559 +               depctl.b.cnak = 1;
44560 +
44561 +               DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44562 +       }
44563 +}
44564 +
44565 +/**
44566 + * This function does the setup for a data transfer for an EP and
44567 + * starts the transfer. For an IN transfer, the packets will be
44568 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
44569 + * the packets are unloaded from the Rx FIFO in the ISR.
44570 + *
44571 + * @param core_if Programming view of DWC_otg controller.
44572 + * @param ep The EP to start the transfer on.
44573 + */
44574 +
44575 +static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
44576 +                                         dwc_ep_t * ep)
44577 +{
44578 +       if (core_if->dma_enable) {
44579 +               if (core_if->dma_desc_enable) {
44580 +                       if (ep->is_in) {
44581 +                               ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
44582 +                       } else {
44583 +                               ep->desc_cnt = ep->pkt_cnt;
44584 +                       }
44585 +                       dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
44586 +               } else {
44587 +                       if (core_if->pti_enh_enable) {
44588 +                               dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
44589 +                       } else {
44590 +                               ep->cur_pkt_addr =
44591 +                                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->
44592 +                                   xfer_buff0;
44593 +                               ep->cur_pkt_dma_addr =
44594 +                                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->
44595 +                                   dma_addr0;
44596 +                               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44597 +                       }
44598 +               }
44599 +       } else {
44600 +               ep->cur_pkt_addr =
44601 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44602 +               ep->cur_pkt_dma_addr =
44603 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44604 +               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44605 +       }
44606 +}
44607 +
44608 +/**
44609 + * This function stops transfer for an EP and
44610 + * resets the ep's variables. 
44611 + *
44612 + * @param core_if Programming view of DWC_otg controller.
44613 + * @param ep The EP to start the transfer on.
44614 + */
44615 +
44616 +void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
44617 +{
44618 +       depctl_data_t depctl = {.d32 = 0 };
44619 +       volatile uint32_t *addr;
44620 +
44621 +       if (ep->is_in == 1) {
44622 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44623 +       } else {
44624 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44625 +       }
44626 +
44627 +       /* disable the ep */
44628 +       depctl.d32 = DWC_READ_REG32(addr);
44629 +
44630 +       depctl.b.epdis = 1;
44631 +       depctl.b.snak = 1;
44632 +
44633 +       DWC_WRITE_REG32(addr, depctl.d32);
44634 +
44635 +       if (core_if->dma_desc_enable &&
44636 +           ep->iso_desc_addr && ep->iso_dma_desc_addr) {
44637 +               dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
44638 +                                          ep->iso_dma_desc_addr,
44639 +                                          ep->desc_cnt * 2);
44640 +       }
44641 +
44642 +       /* reset varibales */
44643 +       ep->dma_addr0 = 0;
44644 +       ep->dma_addr1 = 0;
44645 +       ep->xfer_buff0 = 0;
44646 +       ep->xfer_buff1 = 0;
44647 +       ep->data_per_frame = 0;
44648 +       ep->data_pattern_frame = 0;
44649 +       ep->sync_frame = 0;
44650 +       ep->buf_proc_intrvl = 0;
44651 +       ep->bInterval = 0;
44652 +       ep->proc_buf_num = 0;
44653 +       ep->pkt_per_frm = 0;
44654 +       ep->pkt_per_frm = 0;
44655 +       ep->desc_cnt = 0;
44656 +       ep->iso_desc_addr = 0;
44657 +       ep->iso_dma_desc_addr = 0;
44658 +}
44659 +
44660 +int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
44661 +                            uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
44662 +                            dwc_dma_t dma1, int sync_frame, int dp_frame,
44663 +                            int data_per_frame, int start_frame,
44664 +                            int buf_proc_intrvl, void *req_handle,
44665 +                            int atomic_alloc)
44666 +{
44667 +       dwc_otg_pcd_ep_t *ep;
44668 +       dwc_irqflags_t flags = 0;
44669 +       dwc_ep_t *dwc_ep;
44670 +       int32_t frm_data;
44671 +       dsts_data_t dsts;
44672 +       dwc_otg_core_if_t *core_if;
44673 +
44674 +       ep = get_ep_from_handle(pcd, ep_handle);
44675 +
44676 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44677 +               DWC_WARN("bad ep\n");
44678 +               return -DWC_E_INVALID;
44679 +       }
44680 +
44681 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44682 +       core_if = GET_CORE_IF(pcd);
44683 +       dwc_ep = &ep->dwc_ep;
44684 +
44685 +       if (ep->iso_req_handle) {
44686 +               DWC_WARN("ISO request in progress\n");
44687 +       }
44688 +
44689 +       dwc_ep->dma_addr0 = dma0;
44690 +       dwc_ep->dma_addr1 = dma1;
44691 +
44692 +       dwc_ep->xfer_buff0 = buf0;
44693 +       dwc_ep->xfer_buff1 = buf1;
44694 +
44695 +       dwc_ep->data_per_frame = data_per_frame;
44696 +
44697 +       /** @todo - pattern data support is to be implemented in the future */
44698 +       dwc_ep->data_pattern_frame = dp_frame;
44699 +       dwc_ep->sync_frame = sync_frame;
44700 +
44701 +       dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
44702 +
44703 +       dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
44704 +
44705 +       dwc_ep->proc_buf_num = 0;
44706 +
44707 +       dwc_ep->pkt_per_frm = 0;
44708 +       frm_data = ep->dwc_ep.data_per_frame;
44709 +       while (frm_data > 0) {
44710 +               dwc_ep->pkt_per_frm++;
44711 +               frm_data -= ep->dwc_ep.maxpacket;
44712 +       }
44713 +
44714 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44715 +
44716 +       if (start_frame == -1) {
44717 +               dwc_ep->next_frame = dsts.b.soffn + 1;
44718 +               if (dwc_ep->bInterval != 1) {
44719 +                       dwc_ep->next_frame =
44720 +                           dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
44721 +                                                 dwc_ep->next_frame %
44722 +                                                 dwc_ep->bInterval);
44723 +               }
44724 +       } else {
44725 +               dwc_ep->next_frame = start_frame;
44726 +       }
44727 +
44728 +       if (!core_if->pti_enh_enable) {
44729 +               dwc_ep->pkt_cnt =
44730 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44731 +                   dwc_ep->bInterval;
44732 +       } else {
44733 +               dwc_ep->pkt_cnt =
44734 +                   (dwc_ep->data_per_frame *
44735 +                    (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
44736 +                    - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
44737 +       }
44738 +
44739 +       if (core_if->dma_desc_enable) {
44740 +               dwc_ep->desc_cnt =
44741 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44742 +                   dwc_ep->bInterval;
44743 +       }
44744 +
44745 +       if (atomic_alloc) {
44746 +               dwc_ep->pkt_info =
44747 +                   DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44748 +       } else {
44749 +               dwc_ep->pkt_info =
44750 +                   DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44751 +       }
44752 +       if (!dwc_ep->pkt_info) {
44753 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44754 +               return -DWC_E_NO_MEMORY;
44755 +       }
44756 +       if (core_if->pti_enh_enable) {
44757 +               dwc_memset(dwc_ep->pkt_info, 0,
44758 +                          sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44759 +       }
44760 +
44761 +       dwc_ep->cur_pkt = 0;
44762 +       ep->iso_req_handle = req_handle;
44763 +
44764 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44765 +       dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
44766 +       return 0;
44767 +}
44768 +
44769 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
44770 +                           void *req_handle)
44771 +{
44772 +       dwc_irqflags_t flags = 0;
44773 +       dwc_otg_pcd_ep_t *ep;
44774 +       dwc_ep_t *dwc_ep;
44775 +
44776 +       ep = get_ep_from_handle(pcd, ep_handle);
44777 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44778 +               DWC_WARN("bad ep\n");
44779 +               return -DWC_E_INVALID;
44780 +       }
44781 +       dwc_ep = &ep->dwc_ep;
44782 +
44783 +       dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
44784 +
44785 +       DWC_FREE(dwc_ep->pkt_info);
44786 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44787 +       if (ep->iso_req_handle != req_handle) {
44788 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44789 +               return -DWC_E_INVALID;
44790 +       }
44791 +
44792 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44793 +
44794 +       ep->iso_req_handle = 0;
44795 +       return 0;
44796 +}
44797 +
44798 +/**
44799 + * This function is used for perodical data exchnage between PCD and gadget drivers.
44800 + * for Isochronous EPs
44801 + *
44802 + *     - Every time a sync period completes this function is called to
44803 + *       perform data exchange between PCD and gadget
44804 + */
44805 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
44806 +                            void *req_handle)
44807 +{
44808 +       int i;
44809 +       dwc_ep_t *dwc_ep;
44810 +
44811 +       dwc_ep = &ep->dwc_ep;
44812 +
44813 +       DWC_SPINUNLOCK(ep->pcd->lock);
44814 +       pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
44815 +                                dwc_ep->proc_buf_num ^ 0x1);
44816 +       DWC_SPINLOCK(ep->pcd->lock);
44817 +
44818 +       for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
44819 +               dwc_ep->pkt_info[i].status = 0;
44820 +               dwc_ep->pkt_info[i].offset = 0;
44821 +               dwc_ep->pkt_info[i].length = 0;
44822 +       }
44823 +}
44824 +
44825 +int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
44826 +                                    void *iso_req_handle)
44827 +{
44828 +       dwc_otg_pcd_ep_t *ep;
44829 +       dwc_ep_t *dwc_ep;
44830 +
44831 +       ep = get_ep_from_handle(pcd, ep_handle);
44832 +       if (!ep->desc || ep->dwc_ep.num == 0) {
44833 +               DWC_WARN("bad ep\n");
44834 +               return -DWC_E_INVALID;
44835 +       }
44836 +       dwc_ep = &ep->dwc_ep;
44837 +
44838 +       return dwc_ep->pkt_cnt;
44839 +}
44840 +
44841 +void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
44842 +                                      void *iso_req_handle, int packet,
44843 +                                      int *status, int *actual, int *offset)
44844 +{
44845 +       dwc_otg_pcd_ep_t *ep;
44846 +       dwc_ep_t *dwc_ep;
44847 +
44848 +       ep = get_ep_from_handle(pcd, ep_handle);
44849 +       if (!ep)
44850 +               DWC_WARN("bad ep\n");
44851 +
44852 +       dwc_ep = &ep->dwc_ep;
44853 +
44854 +       *status = dwc_ep->pkt_info[packet].status;
44855 +       *actual = dwc_ep->pkt_info[packet].length;
44856 +       *offset = dwc_ep->pkt_info[packet].offset;
44857 +}
44858 +
44859 +#endif /* DWC_EN_ISOC */
44860 +
44861 +static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
44862 +                               uint32_t is_in, uint32_t ep_num)
44863 +{
44864 +       /* Init EP structure */
44865 +       pcd_ep->desc = 0;
44866 +       pcd_ep->pcd = pcd;
44867 +       pcd_ep->stopped = 1;
44868 +       pcd_ep->queue_sof = 0;
44869 +
44870 +       /* Init DWC ep structure */
44871 +       pcd_ep->dwc_ep.is_in = is_in;
44872 +       pcd_ep->dwc_ep.num = ep_num;
44873 +       pcd_ep->dwc_ep.active = 0;
44874 +       pcd_ep->dwc_ep.tx_fifo_num = 0;
44875 +       /* Control until ep is actvated */
44876 +       pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
44877 +       pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
44878 +       pcd_ep->dwc_ep.dma_addr = 0;
44879 +       pcd_ep->dwc_ep.start_xfer_buff = 0;
44880 +       pcd_ep->dwc_ep.xfer_buff = 0;
44881 +       pcd_ep->dwc_ep.xfer_len = 0;
44882 +       pcd_ep->dwc_ep.xfer_count = 0;
44883 +       pcd_ep->dwc_ep.sent_zlp = 0;
44884 +       pcd_ep->dwc_ep.total_len = 0;
44885 +       pcd_ep->dwc_ep.desc_addr = 0;
44886 +       pcd_ep->dwc_ep.dma_desc_addr = 0;
44887 +       DWC_CIRCLEQ_INIT(&pcd_ep->queue);
44888 +}
44889 +
44890 +/**
44891 + * Initialize ep's
44892 + */
44893 +static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
44894 +{
44895 +       int i;
44896 +       uint32_t hwcfg1;
44897 +       dwc_otg_pcd_ep_t *ep;
44898 +       int in_ep_cntr, out_ep_cntr;
44899 +       uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
44900 +       uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
44901 +
44902 +       /**
44903 +        * Initialize the EP0 structure.
44904 +        */
44905 +       ep = &pcd->ep0;
44906 +       dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
44907 +
44908 +       in_ep_cntr = 0;
44909 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
44910 +       for (i = 1; in_ep_cntr < num_in_eps; i++) {
44911 +               if ((hwcfg1 & 0x1) == 0) {
44912 +                       dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
44913 +                       in_ep_cntr++;
44914 +                       /**
44915 +                        * @todo NGS: Add direction to EP, based on contents
44916 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
44917 +                        * sprintf(";r
44918 +                        */
44919 +                       dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
44920 +
44921 +                       DWC_CIRCLEQ_INIT(&ep->queue);
44922 +               }
44923 +               hwcfg1 >>= 2;
44924 +       }
44925 +
44926 +       out_ep_cntr = 0;
44927 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
44928 +       for (i = 1; out_ep_cntr < num_out_eps; i++) {
44929 +               if ((hwcfg1 & 0x1) == 0) {
44930 +                       dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
44931 +                       out_ep_cntr++;
44932 +                       /**
44933 +                        * @todo NGS: Add direction to EP, based on contents
44934 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
44935 +                        * sprintf(";r
44936 +                        */
44937 +                       dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
44938 +                       DWC_CIRCLEQ_INIT(&ep->queue);
44939 +               }
44940 +               hwcfg1 >>= 2;
44941 +       }
44942 +
44943 +       pcd->ep0state = EP0_DISCONNECT;
44944 +       pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
44945 +       pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
44946 +}
44947 +
44948 +/**
44949 + * This function is called when the SRP timer expires. The SRP should
44950 + * complete within 6 seconds.
44951 + */
44952 +static void srp_timeout(void *ptr)
44953 +{
44954 +       gotgctl_data_t gotgctl;
44955 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
44956 +       volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
44957 +
44958 +       gotgctl.d32 = DWC_READ_REG32(addr);
44959 +
44960 +       core_if->srp_timer_started = 0;
44961 +       
44962 +       if (core_if->adp_enable) {
44963 +               if (gotgctl.b.bsesvld == 0) {
44964 +                       gpwrdn_data_t gpwrdn = {.d32 = 0 };
44965 +                       DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");
44966 +                       /* Power off the core */
44967 +                       if (core_if->power_down == 2) {
44968 +                               gpwrdn.b.pwrdnswtch = 1;
44969 +                               DWC_MODIFY_REG32(&core_if->
44970 +                                                core_global_regs->gpwrdn,
44971 +                                                gpwrdn.d32, 0);
44972 +                       }
44973 +
44974 +                       gpwrdn.d32 = 0;
44975 +                       gpwrdn.b.pmuintsel = 1;
44976 +                       gpwrdn.b.pmuactv = 1;
44977 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
44978 +                                        gpwrdn.d32);
44979 +                       dwc_otg_adp_probe_start(core_if);
44980 +               } else {
44981 +                       DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");
44982 +                       core_if->op_state = B_PERIPHERAL;
44983 +                       dwc_otg_core_init(core_if);
44984 +                       dwc_otg_enable_global_interrupts(core_if);
44985 +                       cil_pcd_start(core_if);
44986 +               }
44987 +       }
44988 +
44989 +       if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
44990 +           (core_if->core_params->i2c_enable)) {
44991 +               DWC_PRINTF("SRP Timeout\n");
44992 +
44993 +               if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
44994 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
44995 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
44996 +                       }
44997 +
44998 +                       /* Clear Session Request */
44999 +                       gotgctl.d32 = 0;
45000 +                       gotgctl.b.sesreq = 1;
45001 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,
45002 +                                        gotgctl.d32, 0);
45003 +
45004 +                       core_if->srp_success = 0;
45005 +               } else {
45006 +                       __DWC_ERROR("Device not connected/responding\n");
45007 +                       gotgctl.b.sesreq = 0;
45008 +                       DWC_WRITE_REG32(addr, gotgctl.d32);
45009 +               }
45010 +       } else if (gotgctl.b.sesreq) {
45011 +               DWC_PRINTF("SRP Timeout\n");
45012 +
45013 +               __DWC_ERROR("Device not connected/responding\n");
45014 +               gotgctl.b.sesreq = 0;
45015 +               DWC_WRITE_REG32(addr, gotgctl.d32);
45016 +       } else {
45017 +               DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
45018 +       }
45019 +}
45020 +
45021 +/**
45022 + * Tasklet
45023 + *
45024 + */
45025 +extern void start_next_request(dwc_otg_pcd_ep_t * ep);
45026 +
45027 +static void start_xfer_tasklet_func(void *data)
45028 +{
45029 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
45030 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45031 +
45032 +       int i;
45033 +       depctl_data_t diepctl;
45034 +
45035 +       DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
45036 +
45037 +       diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl);
45038 +
45039 +       if (pcd->ep0.queue_sof) {
45040 +               pcd->ep0.queue_sof = 0;
45041 +               start_next_request(&pcd->ep0);
45042 +               // break;
45043 +       }
45044 +
45045 +       for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
45046 +               depctl_data_t diepctl;
45047 +               diepctl.d32 =
45048 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
45049 +
45050 +               if (pcd->in_ep[i].queue_sof) {
45051 +                       pcd->in_ep[i].queue_sof = 0;
45052 +                       start_next_request(&pcd->in_ep[i]);
45053 +                       // break;
45054 +               }
45055 +       }
45056 +
45057 +       return;
45058 +}
45059 +
45060 +/**
45061 + * This function initialized the PCD portion of the driver.
45062 + *
45063 + */
45064 +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
45065 +{
45066 +       dwc_otg_pcd_t *pcd = NULL;
45067 +       dwc_otg_dev_if_t *dev_if;
45068 +       int i;
45069 +
45070 +       /*
45071 +        * Allocate PCD structure
45072 +        */
45073 +       pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t));
45074 +
45075 +       if (pcd == NULL) {
45076 +               return NULL;
45077 +       }
45078 +
45079 +       pcd->lock = DWC_SPINLOCK_ALLOC();
45080 +        DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n",
45081 +                    pcd, core_if);//GRAYG
45082 +       if (!pcd->lock) {
45083 +               DWC_ERROR("Could not allocate lock for pcd");
45084 +               DWC_FREE(pcd);
45085 +               return NULL;
45086 +       }
45087 +       /* Set core_if's lock pointer to hcd->lock */
45088 +       core_if->lock = pcd->lock;
45089 +       pcd->core_if = core_if;
45090 +
45091 +       dev_if = core_if->dev_if;
45092 +       dev_if->isoc_ep = NULL;
45093 +
45094 +       if (core_if->hwcfg4.b.ded_fifo_en) {
45095 +               DWC_PRINTF("Dedicated Tx FIFOs mode\n");
45096 +       } else {
45097 +               DWC_PRINTF("Shared Tx FIFO mode\n");
45098 +       }
45099 +
45100 +       /*
45101 +        * Initialized the Core for Device mode here if there is nod ADP support. 
45102 +        * Otherwise it will be done later in dwc_otg_adp_start routine.
45103 +        */                                                                                                                                                              
45104 +       if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) {
45105 +               dwc_otg_core_dev_init(core_if);
45106 +       }
45107 +
45108 +       /*
45109 +        * Register the PCD Callbacks.
45110 +        */
45111 +       dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
45112 +
45113 +       /*
45114 +        * Initialize the DMA buffer for SETUP packets
45115 +        */
45116 +       if (GET_CORE_IF(pcd)->dma_enable) {
45117 +               pcd->setup_pkt =
45118 +                   DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5,
45119 +                                 &pcd->setup_pkt_dma_handle);
45120 +               if (pcd->setup_pkt == NULL) {
45121 +                       DWC_FREE(pcd);
45122 +                       return NULL;
45123 +               }
45124 +
45125 +               pcd->status_buf =
45126 +                   DWC_DMA_ALLOC(sizeof(uint16_t),
45127 +                                 &pcd->status_buf_dma_handle);
45128 +               if (pcd->status_buf == NULL) {
45129 +                       DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
45130 +                                    pcd->setup_pkt, pcd->setup_pkt_dma_handle);
45131 +                       DWC_FREE(pcd);
45132 +                       return NULL;
45133 +               }
45134 +
45135 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
45136 +                       dev_if->setup_desc_addr[0] =
45137 +                           dwc_otg_ep_alloc_desc_chain
45138 +                           (&dev_if->dma_setup_desc_addr[0], 1);
45139 +                       dev_if->setup_desc_addr[1] =
45140 +                           dwc_otg_ep_alloc_desc_chain
45141 +                           (&dev_if->dma_setup_desc_addr[1], 1);
45142 +                       dev_if->in_desc_addr =
45143 +                           dwc_otg_ep_alloc_desc_chain
45144 +                           (&dev_if->dma_in_desc_addr, 1);
45145 +                       dev_if->out_desc_addr =
45146 +                           dwc_otg_ep_alloc_desc_chain
45147 +                           (&dev_if->dma_out_desc_addr, 1);
45148 +                       pcd->data_terminated = 0;
45149 +
45150 +                       if (dev_if->setup_desc_addr[0] == 0
45151 +                           || dev_if->setup_desc_addr[1] == 0
45152 +                           || dev_if->in_desc_addr == 0
45153 +                           || dev_if->out_desc_addr == 0) {
45154 +
45155 +                               if (dev_if->out_desc_addr)
45156 +                                       dwc_otg_ep_free_desc_chain
45157 +                                           (dev_if->out_desc_addr,
45158 +                                            dev_if->dma_out_desc_addr, 1);
45159 +                               if (dev_if->in_desc_addr)
45160 +                                       dwc_otg_ep_free_desc_chain
45161 +                                           (dev_if->in_desc_addr,
45162 +                                            dev_if->dma_in_desc_addr, 1);
45163 +                               if (dev_if->setup_desc_addr[1])
45164 +                                       dwc_otg_ep_free_desc_chain
45165 +                                           (dev_if->setup_desc_addr[1],
45166 +                                            dev_if->dma_setup_desc_addr[1], 1);
45167 +                               if (dev_if->setup_desc_addr[0])
45168 +                                       dwc_otg_ep_free_desc_chain
45169 +                                           (dev_if->setup_desc_addr[0],
45170 +                                            dev_if->dma_setup_desc_addr[0], 1);
45171 +
45172 +                               DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
45173 +                                            pcd->setup_pkt,
45174 +                                            pcd->setup_pkt_dma_handle);
45175 +                               DWC_DMA_FREE(sizeof(*pcd->status_buf),
45176 +                                            pcd->status_buf,
45177 +                                            pcd->status_buf_dma_handle);
45178 +
45179 +                               DWC_FREE(pcd);
45180 +
45181 +                               return NULL;
45182 +                       }
45183 +               }
45184 +       } else {
45185 +               pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5);
45186 +               if (pcd->setup_pkt == NULL) {
45187 +                       DWC_FREE(pcd);
45188 +                       return NULL;
45189 +               }
45190 +
45191 +               pcd->status_buf = DWC_ALLOC(sizeof(uint16_t));
45192 +               if (pcd->status_buf == NULL) {
45193 +                       DWC_FREE(pcd->setup_pkt);
45194 +                       DWC_FREE(pcd);
45195 +                       return NULL;
45196 +               }
45197 +       }
45198 +
45199 +       dwc_otg_pcd_reinit(pcd);
45200 +
45201 +       /* Allocate the cfi object for the PCD */
45202 +#ifdef DWC_UTE_CFI
45203 +       pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t));
45204 +       if (NULL == pcd->cfi)
45205 +               goto fail;
45206 +       if (init_cfi(pcd->cfi)) {
45207 +               CFI_INFO("%s: Failed to init the CFI object\n", __func__);
45208 +               goto fail;
45209 +       }
45210 +#endif
45211 +
45212 +       /* Initialize tasklets */
45213 +       pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet",
45214 +                                                start_xfer_tasklet_func, pcd);
45215 +       pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet",
45216 +                                               do_test_mode, pcd);
45217 +
45218 +       /* Initialize SRP timer */
45219 +       core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
45220 +       
45221 +       if (core_if->core_params->dev_out_nak) {
45222 +               /** 
45223 +               * Initialize xfer timeout timer. Implemented for
45224 +               * 2.93a feature "Device DDMA OUT NAK Enhancement"
45225 +               */
45226 +               for(i = 0; i < MAX_EPS_CHANNELS; i++) {
45227 +                       pcd->core_if->ep_xfer_timer[i] =
45228 +                               DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout,
45229 +                               &pcd->core_if->ep_xfer_info[i]);
45230 +               }
45231 +       }
45232 +       
45233 +       return pcd;
45234 +#ifdef DWC_UTE_CFI
45235 +fail:
45236 +#endif
45237 +       if (pcd->setup_pkt)
45238 +               DWC_FREE(pcd->setup_pkt);
45239 +       if (pcd->status_buf)
45240 +               DWC_FREE(pcd->status_buf);
45241 +#ifdef DWC_UTE_CFI
45242 +       if (pcd->cfi)
45243 +               DWC_FREE(pcd->cfi);
45244 +#endif
45245 +       if (pcd)
45246 +               DWC_FREE(pcd);
45247 +       return NULL;
45248 +
45249 +}
45250 +
45251 +/**
45252 + * Remove PCD specific data
45253 + */
45254 +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
45255 +{
45256 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
45257 +       int i;
45258 +       if (pcd->core_if->core_params->dev_out_nak) {
45259 +               for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45260 +                       DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]);
45261 +                       pcd->core_if->ep_xfer_info[i].state = 0;
45262 +               }
45263 +       }
45264 +
45265 +       if (GET_CORE_IF(pcd)->dma_enable) {
45266 +               DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
45267 +                            pcd->setup_pkt_dma_handle);
45268 +               DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf,
45269 +                            pcd->status_buf_dma_handle);
45270 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
45271 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
45272 +                                                  dev_if->dma_setup_desc_addr
45273 +                                                  [0], 1);
45274 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
45275 +                                                  dev_if->dma_setup_desc_addr
45276 +                                                  [1], 1);
45277 +                       dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
45278 +                                                  dev_if->dma_in_desc_addr, 1);
45279 +                       dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
45280 +                                                  dev_if->dma_out_desc_addr,
45281 +                                                  1);
45282 +               }
45283 +       } else {
45284 +               DWC_FREE(pcd->setup_pkt);
45285 +               DWC_FREE(pcd->status_buf);
45286 +       }
45287 +       DWC_SPINLOCK_FREE(pcd->lock);
45288 +       /* Set core_if's lock pointer to NULL */
45289 +       pcd->core_if->lock = NULL;
45290 +
45291 +       DWC_TASK_FREE(pcd->start_xfer_tasklet);
45292 +       DWC_TASK_FREE(pcd->test_mode_tasklet);
45293 +       if (pcd->core_if->core_params->dev_out_nak) {
45294 +               for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45295 +                       if (pcd->core_if->ep_xfer_timer[i]) {
45296 +                                       DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]);
45297 +                       }
45298 +               }
45299 +       }
45300 +
45301 +/* Release the CFI object's dynamic memory */
45302 +#ifdef DWC_UTE_CFI
45303 +       if (pcd->cfi->ops.release) {
45304 +               pcd->cfi->ops.release(pcd->cfi);
45305 +       }
45306 +#endif
45307 +
45308 +       DWC_FREE(pcd);
45309 +}
45310 +
45311 +/**
45312 + * Returns whether registered pcd is dual speed or not
45313 + */
45314 +uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
45315 +{
45316 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45317 +
45318 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
45319 +           ((core_if->hwcfg2.b.hs_phy_type == 2) &&
45320 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
45321 +            (core_if->core_params->ulpi_fs_ls))) {
45322 +               return 0;
45323 +       }
45324 +
45325 +       return 1;
45326 +}
45327 +
45328 +/**
45329 + * Returns whether registered pcd is OTG capable or not
45330 + */
45331 +uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
45332 +{
45333 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45334 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
45335 +
45336 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
45337 +       if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
45338 +               return 0;
45339 +       }
45340 +
45341 +       return 1;
45342 +}
45343 +
45344 +/**
45345 + * This function assigns periodic Tx FIFO to an periodic EP
45346 + * in shared Tx FIFO mode
45347 + */
45348 +static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
45349 +{
45350 +       uint32_t TxMsk = 1;
45351 +       int i;
45352 +
45353 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
45354 +               if ((TxMsk & core_if->tx_msk) == 0) {
45355 +                       core_if->tx_msk |= TxMsk;
45356 +                       return i + 1;
45357 +               }
45358 +               TxMsk <<= 1;
45359 +       }
45360 +       return 0;
45361 +}
45362 +
45363 +/**
45364 + * This function assigns periodic Tx FIFO to an periodic EP
45365 + * in shared Tx FIFO mode
45366 + */
45367 +static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
45368 +{
45369 +       uint32_t PerTxMsk = 1;
45370 +       int i;
45371 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
45372 +               if ((PerTxMsk & core_if->p_tx_msk) == 0) {
45373 +                       core_if->p_tx_msk |= PerTxMsk;
45374 +                       return i + 1;
45375 +               }
45376 +               PerTxMsk <<= 1;
45377 +       }
45378 +       return 0;
45379 +}
45380 +
45381 +/**
45382 + * This function releases periodic Tx FIFO
45383 + * in shared Tx FIFO mode
45384 + */
45385 +static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
45386 +                                 uint32_t fifo_num)
45387 +{
45388 +       core_if->p_tx_msk =
45389 +           (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
45390 +}
45391 +
45392 +/**
45393 + * This function releases periodic Tx FIFO
45394 + * in shared Tx FIFO mode
45395 + */
45396 +static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
45397 +{
45398 +       core_if->tx_msk =
45399 +           (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
45400 +}
45401 +
45402 +/**
45403 + * This function is being called from gadget 
45404 + * to enable PCD endpoint.
45405 + */
45406 +int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
45407 +                         const uint8_t * ep_desc, void *usb_ep)
45408 +{
45409 +       int num, dir;
45410 +       dwc_otg_pcd_ep_t *ep = NULL;
45411 +       const usb_endpoint_descriptor_t *desc;
45412 +       dwc_irqflags_t flags;
45413 +       fifosize_data_t dptxfsiz = {.d32 = 0 };
45414 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45415 +       gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45416 +       int retval = 0;
45417 +       int i, epcount;
45418 +
45419 +       desc = (const usb_endpoint_descriptor_t *)ep_desc;
45420 +
45421 +       if (!desc) {
45422 +               pcd->ep0.priv = usb_ep;
45423 +               ep = &pcd->ep0;
45424 +               retval = -DWC_E_INVALID;
45425 +               goto out;
45426 +       }
45427 +
45428 +       num = UE_GET_ADDR(desc->bEndpointAddress);
45429 +       dir = UE_GET_DIR(desc->bEndpointAddress);
45430 +
45431 +       if (!desc->wMaxPacketSize) {
45432 +               DWC_WARN("bad maxpacketsize\n");
45433 +               retval = -DWC_E_INVALID;
45434 +               goto out;
45435 +       }
45436 +
45437 +       if (dir == UE_DIR_IN) {
45438 +               epcount = pcd->core_if->dev_if->num_in_eps;
45439 +               for (i = 0; i < epcount; i++) {
45440 +                       if (num == pcd->in_ep[i].dwc_ep.num) {
45441 +                               ep = &pcd->in_ep[i];
45442 +                               break;
45443 +                       }
45444 +               }
45445 +       } else {
45446 +               epcount = pcd->core_if->dev_if->num_out_eps;
45447 +               for (i = 0; i < epcount; i++) {
45448 +                       if (num == pcd->out_ep[i].dwc_ep.num) {
45449 +                               ep = &pcd->out_ep[i];
45450 +                               break;
45451 +                       }
45452 +               }
45453 +       }
45454 +
45455 +       if (!ep) {
45456 +               DWC_WARN("bad address\n");
45457 +               retval = -DWC_E_INVALID;
45458 +               goto out;
45459 +       }
45460 +
45461 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45462 +
45463 +       ep->desc = desc;
45464 +       ep->priv = usb_ep;
45465 +
45466 +       /*
45467 +        * Activate the EP
45468 +        */
45469 +       ep->stopped = 0;
45470 +
45471 +       ep->dwc_ep.is_in = (dir == UE_DIR_IN);
45472 +       ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
45473 +
45474 +       ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
45475 +
45476 +       if (ep->dwc_ep.is_in) {
45477 +               if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45478 +                       ep->dwc_ep.tx_fifo_num = 0;
45479 +
45480 +                       if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
45481 +                               /*
45482 +                                * if ISOC EP then assign a Periodic Tx FIFO.
45483 +                                */
45484 +                               ep->dwc_ep.tx_fifo_num =
45485 +                                   assign_perio_tx_fifo(GET_CORE_IF(pcd));
45486 +                       }
45487 +               } else {
45488 +                       /*
45489 +                        * if Dedicated FIFOs mode is on then assign a Tx FIFO.
45490 +                        */
45491 +                       ep->dwc_ep.tx_fifo_num =
45492 +                           assign_tx_fifo(GET_CORE_IF(pcd));
45493 +               }
45494 +
45495 +               /* Calculating EP info controller base address */
45496 +               if (ep->dwc_ep.tx_fifo_num
45497 +                   && GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45498 +                       gdfifocfg.d32 =
45499 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
45500 +                                          core_global_regs->gdfifocfg);
45501 +                       gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45502 +                       dptxfsiz.d32 =
45503 +                           (DWC_READ_REG32
45504 +                            (&GET_CORE_IF(pcd)->core_global_regs->
45505 +                             dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16);
45506 +                       gdfifocfg.b.epinfobase =
45507 +                           gdfifocfgbase.d32 + dptxfsiz.d32;
45508 +                       if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45509 +                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45510 +                                               core_global_regs->gdfifocfg,
45511 +                                               gdfifocfg.d32);
45512 +                       }
45513 +               }
45514 +       }
45515 +       /* Set initial data PID. */
45516 +       if (ep->dwc_ep.type == UE_BULK) {
45517 +               ep->dwc_ep.data_pid_start = 0;
45518 +       }
45519 +
45520 +       /* Alloc DMA Descriptors */
45521 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
45522 +#ifndef DWC_UTE_PER_IO
45523 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45524 +#endif
45525 +                       ep->dwc_ep.desc_addr =
45526 +                           dwc_otg_ep_alloc_desc_chain(&ep->
45527 +                                                       dwc_ep.dma_desc_addr,
45528 +                                                       MAX_DMA_DESC_CNT);
45529 +                       if (!ep->dwc_ep.desc_addr) {
45530 +                               DWC_WARN("%s, can't allocate DMA descriptor\n",
45531 +                                        __func__);
45532 +                               retval = -DWC_E_SHUTDOWN;
45533 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45534 +                               goto out;
45535 +                       }
45536 +#ifndef DWC_UTE_PER_IO
45537 +               }
45538 +#endif
45539 +       }
45540 +
45541 +       DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
45542 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"),
45543 +                   ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
45544 +#ifdef DWC_UTE_PER_IO
45545 +       ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);
45546 +#endif
45547 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
45548 +               ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);
45549 +               ep->dwc_ep.frame_num = 0xFFFFFFFF;
45550 +       }               
45551 +
45552 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
45553 +
45554 +#ifdef DWC_UTE_CFI
45555 +       if (pcd->cfi->ops.ep_enable) {
45556 +               pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
45557 +       }
45558 +#endif
45559 +
45560 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45561 +
45562 +out:
45563 +       return retval;
45564 +}
45565 +
45566 +/**
45567 + * This function is being called from gadget 
45568 + * to disable PCD endpoint.
45569 + */
45570 +int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
45571 +{
45572 +       dwc_otg_pcd_ep_t *ep;
45573 +       dwc_irqflags_t flags;
45574 +       dwc_otg_dev_dma_desc_t *desc_addr;
45575 +       dwc_dma_t dma_desc_addr;
45576 +       gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45577 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45578 +       fifosize_data_t dptxfsiz = {.d32 = 0 };
45579 +
45580 +       ep = get_ep_from_handle(pcd, ep_handle);
45581 +
45582 +       if (!ep || !ep->desc) {
45583 +               DWC_DEBUGPL(DBG_PCD, "bad ep address\n");
45584 +               return -DWC_E_INVALID;
45585 +       }
45586 +
45587 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45588 +
45589 +       dwc_otg_request_nuke(ep);
45590 +
45591 +       dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
45592 +       if (pcd->core_if->core_params->dev_out_nak) {
45593 +               DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]);
45594 +               pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0;
45595 +       }
45596 +       ep->desc = NULL;
45597 +       ep->stopped = 1;
45598 +
45599 +       gdfifocfg.d32 =
45600 +           DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg);
45601 +       gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45602 +
45603 +       if (ep->dwc_ep.is_in) {
45604 +               if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45605 +                       /* Flush the Tx FIFO */
45606 +                       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd),
45607 +                                             ep->dwc_ep.tx_fifo_num);
45608 +               }
45609 +               release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45610 +               release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45611 +               if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45612 +                       /* Decreasing EPinfo Base Addr */
45613 +                       dptxfsiz.d32 =
45614 +                           (DWC_READ_REG32
45615 +                            (&GET_CORE_IF(pcd)->
45616 +                               core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16);
45617 +                       gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32;
45618 +                       if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45619 +                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg,
45620 +                                       gdfifocfg.d32);
45621 +                       }
45622 +               }
45623 +       }
45624 +
45625 +       /* Free DMA Descriptors */
45626 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
45627 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45628 +                       desc_addr = ep->dwc_ep.desc_addr;
45629 +                       dma_desc_addr = ep->dwc_ep.dma_desc_addr;
45630 +
45631 +                       /* Cannot call dma_free_coherent() with IRQs disabled */
45632 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45633 +                       dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
45634 +                                                  MAX_DMA_DESC_CNT);
45635 +
45636 +                       goto out_unlocked;
45637 +               }
45638 +       }
45639 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45640 +
45641 +out_unlocked:
45642 +       DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
45643 +                   ep->dwc_ep.is_in ? "IN" : "OUT");
45644 +       return 0;
45645 +
45646 +}
45647 +
45648 +/******************************************************************************/
45649 +#ifdef DWC_UTE_PER_IO
45650 +
45651 +/**
45652 + * Free the request and its extended parts
45653 + *
45654 + */
45655 +void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req)
45656 +{
45657 +       DWC_FREE(req->ext_req.per_io_frame_descs);
45658 +       DWC_FREE(req);
45659 +}
45660 +
45661 +/**
45662 + * Start the next request in the endpoint's queue.
45663 + *
45664 + */
45665 +int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd,
45666 +                                       dwc_otg_pcd_ep_t * ep)
45667 +{
45668 +       int i;
45669 +       dwc_otg_pcd_request_t *req = NULL;
45670 +       dwc_ep_t *dwcep = NULL;
45671 +       struct dwc_iso_xreq_port *ereq = NULL;
45672 +       struct dwc_iso_pkt_desc_port *ddesc_iso;
45673 +       uint16_t nat;
45674 +       depctl_data_t diepctl;
45675 +
45676 +       dwcep = &ep->dwc_ep;
45677 +
45678 +       if (dwcep->xiso_active_xfers > 0) {
45679 +#if 0  //Disable this to decrease s/w overhead that is crucial for Isoc transfers
45680 +               DWC_WARN("There are currently active transfers for EP%d \
45681 +                               (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers, 
45682 +                               dwcep->xiso_queued_xfers);
45683 +#endif
45684 +               return 0;
45685 +       }
45686 +
45687 +       nat = UGETW(ep->desc->wMaxPacketSize);
45688 +       nat = (nat >> 11) & 0x03;
45689 +
45690 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45691 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
45692 +               ereq = &req->ext_req;
45693 +               ep->stopped = 0;
45694 +
45695 +               /* Get the frame number */
45696 +               dwcep->xiso_frame_num =
45697 +                   dwc_otg_get_frame_number(GET_CORE_IF(pcd));
45698 +               DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num);
45699 +
45700 +               ddesc_iso = ereq->per_io_frame_descs;
45701 +
45702 +               if (dwcep->is_in) {
45703 +                       /* Setup DMA Descriptor chain for IN Isoc request */
45704 +                       for (i = 0; i < ereq->pio_pkt_count; i++) {
45705 +                               //if ((i % (nat + 1)) == 0)
45706 +                               if ( i > 0 )
45707 +                                       dwcep->xiso_frame_num =
45708 +                                           (dwcep->xiso_bInterval +
45709 +                                                                               dwcep->xiso_frame_num) & 0x3FFF;
45710 +                               dwcep->desc_addr[i].buf =
45711 +                                   req->dma + ddesc_iso[i].offset;
45712 +                               dwcep->desc_addr[i].status.b_iso_in.txbytes =
45713 +                                   ddesc_iso[i].length;
45714 +                               dwcep->desc_addr[i].status.b_iso_in.framenum =
45715 +                                   dwcep->xiso_frame_num;
45716 +                               dwcep->desc_addr[i].status.b_iso_in.bs =
45717 +                                   BS_HOST_READY;
45718 +                               dwcep->desc_addr[i].status.b_iso_in.txsts = 0;
45719 +                               dwcep->desc_addr[i].status.b_iso_in.sp =
45720 +                                   (ddesc_iso[i].length %
45721 +                                    dwcep->maxpacket) ? 1 : 0;
45722 +                               dwcep->desc_addr[i].status.b_iso_in.ioc = 0;
45723 +                               dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1;
45724 +                               dwcep->desc_addr[i].status.b_iso_in.l = 0;
45725 +
45726 +                               /* Process the last descriptor */
45727 +                               if (i == ereq->pio_pkt_count - 1) {
45728 +                                       dwcep->desc_addr[i].status.b_iso_in.ioc = 1;
45729 +                                       dwcep->desc_addr[i].status.b_iso_in.l = 1;
45730 +                               }
45731 +                       }
45732 +
45733 +                       /* Setup and start the transfer for this endpoint */
45734 +                       dwcep->xiso_active_xfers++;
45735 +                       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->
45736 +                                       in_ep_regs[dwcep->num]->diepdma,
45737 +                                       dwcep->dma_desc_addr);
45738 +                       diepctl.d32 = 0;
45739 +                       diepctl.b.epena = 1;
45740 +                       diepctl.b.cnak = 1;
45741 +                       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
45742 +                                        in_ep_regs[dwcep->num]->diepctl, 0,
45743 +                                        diepctl.d32);
45744 +               } else {
45745 +                       /* Setup DMA Descriptor chain for OUT Isoc request */
45746 +                       for (i = 0; i < ereq->pio_pkt_count; i++) {
45747 +                               //if ((i % (nat + 1)) == 0)
45748 +                               dwcep->xiso_frame_num = (dwcep->xiso_bInterval + 
45749 +                                                                               dwcep->xiso_frame_num) & 0x3FFF;
45750 +                               dwcep->desc_addr[i].buf =
45751 +                                   req->dma + ddesc_iso[i].offset;
45752 +                               dwcep->desc_addr[i].status.b_iso_out.rxbytes =
45753 +                                   ddesc_iso[i].length;
45754 +                               dwcep->desc_addr[i].status.b_iso_out.framenum =
45755 +                                   dwcep->xiso_frame_num;
45756 +                               dwcep->desc_addr[i].status.b_iso_out.bs =
45757 +                                   BS_HOST_READY;
45758 +                               dwcep->desc_addr[i].status.b_iso_out.rxsts = 0;
45759 +                               dwcep->desc_addr[i].status.b_iso_out.sp =
45760 +                                   (ddesc_iso[i].length %
45761 +                                    dwcep->maxpacket) ? 1 : 0;
45762 +                               dwcep->desc_addr[i].status.b_iso_out.ioc = 0;
45763 +                               dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1;
45764 +                               dwcep->desc_addr[i].status.b_iso_out.l = 0;
45765 +                               
45766 +                               /* Process the last descriptor */
45767 +                               if (i == ereq->pio_pkt_count - 1) {
45768 +                                       dwcep->desc_addr[i].status.b_iso_out.ioc = 1;
45769 +                                       dwcep->desc_addr[i].status.b_iso_out.l = 1;
45770 +                               }                       
45771 +                       }
45772 +                       
45773 +                       /* Setup and start the transfer for this endpoint */
45774 +                       dwcep->xiso_active_xfers++;
45775 +                       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45776 +                                       dev_if->out_ep_regs[dwcep->num]->
45777 +                                       doepdma, dwcep->dma_desc_addr);
45778 +                       diepctl.d32 = 0;
45779 +                       diepctl.b.epena = 1;
45780 +                       diepctl.b.cnak = 1;
45781 +                       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
45782 +                                        dev_if->out_ep_regs[dwcep->num]->
45783 +                                        doepctl, 0, diepctl.d32);
45784 +               }
45785 +
45786 +       } else {
45787 +               ep->stopped = 1;
45788 +       }
45789 +
45790 +       return 0;
45791 +}
45792 +
45793 +/**
45794 + *     - Remove the request from the queue
45795 + */
45796 +void complete_xiso_ep(dwc_otg_pcd_ep_t * ep)
45797 +{
45798 +       dwc_otg_pcd_request_t *req = NULL;
45799 +       struct dwc_iso_xreq_port *ereq = NULL;
45800 +       struct dwc_iso_pkt_desc_port *ddesc_iso = NULL;
45801 +       dwc_ep_t *dwcep = NULL;
45802 +       int i;
45803 +
45804 +       //DWC_DEBUG();
45805 +       dwcep = &ep->dwc_ep;
45806 +
45807 +       /* Get the first pending request from the queue */
45808 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45809 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
45810 +               if (!req) {
45811 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
45812 +                       return;
45813 +               }
45814 +               dwcep->xiso_active_xfers--;
45815 +               dwcep->xiso_queued_xfers--;
45816 +               /* Remove this request from the queue */
45817 +               DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
45818 +       } else {
45819 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
45820 +               return;
45821 +       }
45822 +
45823 +       ep->stopped = 1;
45824 +       ereq = &req->ext_req;
45825 +       ddesc_iso = ereq->per_io_frame_descs;
45826 +
45827 +       if (dwcep->xiso_active_xfers < 0) {
45828 +               DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num,
45829 +                        dwcep->xiso_active_xfers);
45830 +       }
45831 +
45832 +       /* Fill the Isoc descs of portable extended req from dma descriptors */
45833 +       for (i = 0; i < ereq->pio_pkt_count; i++) {
45834 +               if (dwcep->is_in) {     /* IN endpoints */
45835 +                       ddesc_iso[i].actual_length = ddesc_iso[i].length -
45836 +                           dwcep->desc_addr[i].status.b_iso_in.txbytes;
45837 +                       ddesc_iso[i].status =
45838 +                           dwcep->desc_addr[i].status.b_iso_in.txsts;
45839 +               } else {        /* OUT endpoints */
45840 +                       ddesc_iso[i].actual_length = ddesc_iso[i].length -
45841 +                           dwcep->desc_addr[i].status.b_iso_out.rxbytes;
45842 +                       ddesc_iso[i].status =
45843 +                           dwcep->desc_addr[i].status.b_iso_out.rxsts;
45844 +               }
45845 +       }
45846 +
45847 +       DWC_SPINUNLOCK(ep->pcd->lock);
45848 +
45849 +       /* Call the completion function in the non-portable logic */
45850 +       ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0,
45851 +                                     &req->ext_req);
45852 +
45853 +       DWC_SPINLOCK(ep->pcd->lock);
45854 +
45855 +       /* Free the request - specific freeing needed for extended request object */
45856 +       dwc_pcd_xiso_ereq_free(ep, req);
45857 +
45858 +       /* Start the next request */
45859 +       dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep);
45860 +
45861 +       return;
45862 +}
45863 +
45864 +/**
45865 + * Create and initialize the Isoc pkt descriptors of the extended request.
45866 + *
45867 + */
45868 +static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req,
45869 +                                            void *ereq_nonport,
45870 +                                            int atomic_alloc)
45871 +{
45872 +       struct dwc_iso_xreq_port *ereq = NULL;
45873 +       struct dwc_iso_xreq_port *req_mapped = NULL;
45874 +       struct dwc_iso_pkt_desc_port *ipds = NULL;      /* To be created in this function */
45875 +       uint32_t pkt_count;
45876 +       int i;
45877 +
45878 +       ereq = &req->ext_req;
45879 +       req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport;
45880 +       pkt_count = req_mapped->pio_pkt_count;
45881 +
45882 +       /* Create the isoc descs */
45883 +       if (atomic_alloc) {
45884 +               ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count);
45885 +       } else {
45886 +               ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count);
45887 +       }
45888 +
45889 +       if (!ipds) {
45890 +               DWC_ERROR("Failed to allocate isoc descriptors");
45891 +               return -DWC_E_NO_MEMORY;
45892 +       }
45893 +
45894 +       /* Initialize the extended request fields */
45895 +       ereq->per_io_frame_descs = ipds;
45896 +       ereq->error_count = 0;
45897 +       ereq->pio_alloc_pkt_count = pkt_count;
45898 +       ereq->pio_pkt_count = pkt_count;
45899 +       ereq->tr_sub_flags = req_mapped->tr_sub_flags;
45900 +
45901 +       /* Init the Isoc descriptors */
45902 +       for (i = 0; i < pkt_count; i++) {
45903 +               ipds[i].length = req_mapped->per_io_frame_descs[i].length;
45904 +               ipds[i].offset = req_mapped->per_io_frame_descs[i].offset;
45905 +               ipds[i].status = req_mapped->per_io_frame_descs[i].status;      /* 0 */
45906 +               ipds[i].actual_length =
45907 +                   req_mapped->per_io_frame_descs[i].actual_length;
45908 +       }
45909 +
45910 +       return 0;
45911 +}
45912 +
45913 +static void prn_ext_request(struct dwc_iso_xreq_port *ereq)
45914 +{
45915 +       struct dwc_iso_pkt_desc_port *xfd = NULL;
45916 +       int i;
45917 +
45918 +       DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs);
45919 +       DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags);
45920 +       DWC_DEBUG("error_count=%d", ereq->error_count);
45921 +       DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count);
45922 +       DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count);
45923 +       DWC_DEBUG("res=%d", ereq->res);
45924 +
45925 +       for (i = 0; i < ereq->pio_pkt_count; i++) {
45926 +               xfd = &ereq->per_io_frame_descs[0];
45927 +               DWC_DEBUG("FD #%d", i);
45928 +
45929 +               DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length);
45930 +               DWC_DEBUG("xfd->length=%d", xfd->length);
45931 +               DWC_DEBUG("xfd->offset=%d", xfd->offset);
45932 +               DWC_DEBUG("xfd->status=%d", xfd->status);
45933 +       }
45934 +}
45935 +
45936 +/**
45937 + *
45938 + */
45939 +int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
45940 +                             uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
45941 +                             int zero, void *req_handle, int atomic_alloc,
45942 +                             void *ereq_nonport)
45943 +{
45944 +       dwc_otg_pcd_request_t *req = NULL;
45945 +       dwc_otg_pcd_ep_t *ep;
45946 +       dwc_irqflags_t flags;
45947 +       int res;
45948 +
45949 +       ep = get_ep_from_handle(pcd, ep_handle);
45950 +       if (!ep) {
45951 +               DWC_WARN("bad ep\n");
45952 +               return -DWC_E_INVALID;
45953 +       }
45954 +
45955 +       /* We support this extension only for DDMA mode */
45956 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
45957 +               if (!GET_CORE_IF(pcd)->dma_desc_enable)
45958 +                       return -DWC_E_INVALID;
45959 +
45960 +       /* Create a dwc_otg_pcd_request_t object */
45961 +       if (atomic_alloc) {
45962 +               req = DWC_ALLOC_ATOMIC(sizeof(*req));
45963 +       } else {
45964 +               req = DWC_ALLOC(sizeof(*req));
45965 +       }
45966 +
45967 +       if (!req) {
45968 +               return -DWC_E_NO_MEMORY;
45969 +       }
45970 +
45971 +       /* Create the Isoc descs for this request which shall be the exact match
45972 +        * of the structure sent to us from the non-portable logic */
45973 +       res =
45974 +           dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc);
45975 +       if (res) {
45976 +               DWC_WARN("Failed to init the Isoc descriptors");
45977 +               DWC_FREE(req);
45978 +               return res;
45979 +       }
45980 +
45981 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45982 +
45983 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
45984 +       req->buf = buf;
45985 +       req->dma = dma_buf;
45986 +       req->length = buflen;
45987 +       req->sent_zlp = zero;
45988 +       req->priv = req_handle;
45989 +
45990 +       //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45991 +       ep->dwc_ep.dma_addr = dma_buf;
45992 +       ep->dwc_ep.start_xfer_buff = buf;
45993 +       ep->dwc_ep.xfer_buff = buf;
45994 +       ep->dwc_ep.xfer_len = 0;
45995 +       ep->dwc_ep.xfer_count = 0;
45996 +       ep->dwc_ep.sent_zlp = 0;
45997 +       ep->dwc_ep.total_len = buflen;
45998 +
45999 +       /* Add this request to the tail */
46000 +       DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46001 +       ep->dwc_ep.xiso_queued_xfers++;
46002 +
46003 +//DWC_DEBUG("CP_0");
46004 +//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags);
46005 +//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport);
46006 +//prn_ext_request(&req->ext_req);
46007 +
46008 +       //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46009 +
46010 +       /* If the req->status == ASAP  then check if there is any active transfer
46011 +        * for this endpoint. If no active transfers, then get the first entry
46012 +        * from the queue and start that transfer
46013 +        */
46014 +       if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) {
46015 +               res = dwc_otg_pcd_xiso_start_next_request(pcd, ep);
46016 +               if (res) {
46017 +                       DWC_WARN("Failed to start the next Isoc transfer");
46018 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46019 +                       DWC_FREE(req);
46020 +                       return res;
46021 +               }
46022 +       }
46023 +
46024 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46025 +       return 0;
46026 +}
46027 +
46028 +#endif
46029 +/* END ifdef DWC_UTE_PER_IO ***************************************************/
46030 +int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
46031 +                        uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
46032 +                        int zero, void *req_handle, int atomic_alloc)
46033 +{
46034 +       dwc_irqflags_t flags;
46035 +       dwc_otg_pcd_request_t *req;
46036 +       dwc_otg_pcd_ep_t *ep;
46037 +       uint32_t max_transfer;
46038 +
46039 +       ep = get_ep_from_handle(pcd, ep_handle);
46040 +       if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
46041 +               DWC_WARN("bad ep\n");
46042 +               return -DWC_E_INVALID;
46043 +       }
46044 +
46045 +       if (atomic_alloc) {
46046 +               req = DWC_ALLOC_ATOMIC(sizeof(*req));
46047 +       } else {
46048 +               req = DWC_ALLOC(sizeof(*req));
46049 +       }
46050 +
46051 +       if (!req) {
46052 +               return -DWC_E_NO_MEMORY;
46053 +       }
46054 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
46055 +       if (!GET_CORE_IF(pcd)->core_params->opt) {
46056 +               if (ep->dwc_ep.num != 0) {
46057 +                       DWC_ERROR("queue req %p, len %d buf %p\n",
46058 +                                 req_handle, buflen, buf);
46059 +               }
46060 +       }
46061 +
46062 +       req->buf = buf;
46063 +       req->dma = dma_buf;
46064 +       req->length = buflen;
46065 +       req->sent_zlp = zero;
46066 +       req->priv = req_handle;
46067 +       req->dw_align_buf = NULL;
46068 +       if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable
46069 +                       && !GET_CORE_IF(pcd)->dma_desc_enable)
46070 +               req->dw_align_buf = DWC_DMA_ALLOC(buflen,
46071 +                                &req->dw_align_buf_dma);
46072 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46073 +
46074 +       /*
46075 +        * After adding request to the queue for IN ISOC wait for In Token Received
46076 +        * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token 
46077 +        * Received when EP is disabled interrupt to obtain starting microframe
46078 +        * (odd/even) start transfer
46079 +        */
46080 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
46081 +               if (req != 0) {
46082 +                       depctl_data_t depctl = {.d32 =
46083 +                                   DWC_READ_REG32(&pcd->core_if->dev_if->
46084 +                                                  in_ep_regs[ep->dwc_ep.num]->
46085 +                                                  diepctl) };
46086 +                       ++pcd->request_pending;
46087 +
46088 +                       DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46089 +                       if (ep->dwc_ep.is_in) {
46090 +                               depctl.b.cnak = 1;
46091 +                               DWC_WRITE_REG32(&pcd->core_if->dev_if->
46092 +                                               in_ep_regs[ep->dwc_ep.num]->
46093 +                                               diepctl, depctl.d32);
46094 +                       }
46095 +                       
46096 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46097 +               }
46098 +               return 0;
46099 +       }
46100 +
46101 +       /*
46102 +        * For EP0 IN without premature status, zlp is required?
46103 +        */
46104 +       if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
46105 +               DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
46106 +               //_req->zero = 1;
46107 +       }
46108 +
46109 +       /* Start the transfer */
46110 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
46111 +               /* EP0 Transfer? */
46112 +               if (ep->dwc_ep.num == 0) {
46113 +                       switch (pcd->ep0state) {
46114 +                       case EP0_IN_DATA_PHASE:
46115 +                               DWC_DEBUGPL(DBG_PCD,
46116 +                                           "%s ep0: EP0_IN_DATA_PHASE\n",
46117 +                                           __func__);
46118 +                               break;
46119 +
46120 +                       case EP0_OUT_DATA_PHASE:
46121 +                               DWC_DEBUGPL(DBG_PCD,
46122 +                                           "%s ep0: EP0_OUT_DATA_PHASE\n",
46123 +                                           __func__);
46124 +                               if (pcd->request_config) {
46125 +                                       /* Complete STATUS PHASE */
46126 +                                       ep->dwc_ep.is_in = 1;
46127 +                                       pcd->ep0state = EP0_IN_STATUS_PHASE;
46128 +                               }
46129 +                               break;
46130 +
46131 +                       case EP0_IN_STATUS_PHASE:
46132 +                               DWC_DEBUGPL(DBG_PCD,
46133 +                                           "%s ep0: EP0_IN_STATUS_PHASE\n",
46134 +                                           __func__);
46135 +                               break;
46136 +
46137 +                       default:
46138 +                               DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
46139 +                                           pcd->ep0state);
46140 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46141 +                               return -DWC_E_SHUTDOWN;
46142 +                       }
46143 +
46144 +                       ep->dwc_ep.dma_addr = dma_buf;
46145 +                       ep->dwc_ep.start_xfer_buff = buf;
46146 +                       ep->dwc_ep.xfer_buff = buf;
46147 +                       ep->dwc_ep.xfer_len = buflen;
46148 +                       ep->dwc_ep.xfer_count = 0;
46149 +                       ep->dwc_ep.sent_zlp = 0;
46150 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
46151 +
46152 +                       if (zero) {
46153 +                               if ((ep->dwc_ep.xfer_len %
46154 +                                    ep->dwc_ep.maxpacket == 0)
46155 +                                   && (ep->dwc_ep.xfer_len != 0)) {
46156 +                                       ep->dwc_ep.sent_zlp = 1;
46157 +                               }
46158 +
46159 +                       }
46160 +
46161 +                       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
46162 +                                                  &ep->dwc_ep);
46163 +               }               // non-ep0 endpoints
46164 +               else {
46165 +#ifdef DWC_UTE_CFI
46166 +                       if (ep->dwc_ep.buff_mode != BM_STANDARD) {
46167 +                               /* store the request length */
46168 +                               ep->dwc_ep.cfi_req_len = buflen;
46169 +                               pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
46170 +                                                               ep, req);
46171 +                       } else {
46172 +#endif
46173 +                               max_transfer =
46174 +                                   GET_CORE_IF(ep->pcd)->core_params->
46175 +                                   max_transfer_size;
46176 +
46177 +                               /* Setup and start the Transfer */
46178 +                               if (req->dw_align_buf){
46179 +                                       if (ep->dwc_ep.is_in)
46180 +                                               dwc_memcpy(req->dw_align_buf,
46181 +                                                          buf, buflen);
46182 +                                       ep->dwc_ep.dma_addr =
46183 +                                           req->dw_align_buf_dma;
46184 +                                       ep->dwc_ep.start_xfer_buff =
46185 +                                           req->dw_align_buf;
46186 +                                       ep->dwc_ep.xfer_buff =
46187 +                                           req->dw_align_buf;
46188 +                               } else {
46189 +                                       ep->dwc_ep.dma_addr = dma_buf;
46190 +                                       ep->dwc_ep.start_xfer_buff = buf;
46191 +                                        ep->dwc_ep.xfer_buff = buf;    
46192 +                               }
46193 +                               ep->dwc_ep.xfer_len = 0;
46194 +                               ep->dwc_ep.xfer_count = 0;
46195 +                               ep->dwc_ep.sent_zlp = 0;
46196 +                               ep->dwc_ep.total_len = buflen;
46197 +
46198 +                               ep->dwc_ep.maxxfer = max_transfer;
46199 +                               if (GET_CORE_IF(pcd)->dma_desc_enable) {
46200 +                                       uint32_t out_max_xfer =
46201 +                                           DDMA_MAX_TRANSFER_SIZE -
46202 +                                           (DDMA_MAX_TRANSFER_SIZE % 4);
46203 +                                       if (ep->dwc_ep.is_in) {
46204 +                                               if (ep->dwc_ep.maxxfer >
46205 +                                                   DDMA_MAX_TRANSFER_SIZE) {
46206 +                                                       ep->dwc_ep.maxxfer =
46207 +                                                           DDMA_MAX_TRANSFER_SIZE;
46208 +                                               }
46209 +                                       } else {
46210 +                                               if (ep->dwc_ep.maxxfer >
46211 +                                                   out_max_xfer) {
46212 +                                                       ep->dwc_ep.maxxfer =
46213 +                                                           out_max_xfer;
46214 +                                               }
46215 +                                       }
46216 +                               }
46217 +                               if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
46218 +                                       ep->dwc_ep.maxxfer -=
46219 +                                           (ep->dwc_ep.maxxfer %
46220 +                                            ep->dwc_ep.maxpacket);
46221 +                               }
46222 +
46223 +                               if (zero) {
46224 +                                       if ((ep->dwc_ep.total_len %
46225 +                                            ep->dwc_ep.maxpacket == 0)
46226 +                                           && (ep->dwc_ep.total_len != 0)) {
46227 +                                               ep->dwc_ep.sent_zlp = 1;
46228 +                                       }
46229 +                               }
46230 +#ifdef DWC_UTE_CFI
46231 +                       }
46232 +#endif
46233 +                       dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
46234 +                                                 &ep->dwc_ep);
46235 +               }
46236 +       }
46237 +
46238 +       if (req != 0) {
46239 +               ++pcd->request_pending;
46240 +               DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46241 +               if (ep->dwc_ep.is_in && ep->stopped
46242 +                   && !(GET_CORE_IF(pcd)->dma_enable)) {
46243 +                       /** @todo NGS Create a function for this. */
46244 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
46245 +                       diepmsk.b.intktxfemp = 1;
46246 +                       if (GET_CORE_IF(pcd)->multiproc_int_enable) {
46247 +                               DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46248 +                                                dev_if->dev_global_regs->diepeachintmsk
46249 +                                                [ep->dwc_ep.num], 0,
46250 +                                                diepmsk.d32);
46251 +                       } else {
46252 +                               DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46253 +                                                dev_if->dev_global_regs->
46254 +                                                diepmsk, 0, diepmsk.d32);
46255 +                       }
46256 +
46257 +               }
46258 +       }
46259 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46260 +
46261 +       return 0;
46262 +}
46263 +
46264 +int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
46265 +                          void *req_handle)
46266 +{
46267 +       dwc_irqflags_t flags;
46268 +       dwc_otg_pcd_request_t *req;
46269 +       dwc_otg_pcd_ep_t *ep;
46270 +
46271 +       ep = get_ep_from_handle(pcd, ep_handle);
46272 +       if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
46273 +               DWC_WARN("bad argument\n");
46274 +               return -DWC_E_INVALID;
46275 +       }
46276 +
46277 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46278 +
46279 +       /* make sure it's actually queued on this endpoint */
46280 +       DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
46281 +               if (req->priv == (void *)req_handle) {
46282 +                       break;
46283 +               }
46284 +       }
46285 +
46286 +       if (req->priv != (void *)req_handle) {
46287 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46288 +               return -DWC_E_INVALID;
46289 +       }
46290 +
46291 +       if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
46292 +               dwc_otg_request_done(ep, req, -DWC_E_RESTART);
46293 +       } else {
46294 +               req = NULL;
46295 +       }
46296 +
46297 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46298 +
46299 +       return req ? 0 : -DWC_E_SHUTDOWN;
46300 +
46301 +}
46302 +
46303 +/**
46304 + * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests
46305 + *
46306 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
46307 + * requests. If the gadget driver clears the halt status, it will
46308 + * automatically unwedge the endpoint.
46309 + *
46310 + * Returns zero on success, else negative DWC error code.
46311 + */
46312 +int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle)
46313 +{
46314 +       dwc_otg_pcd_ep_t *ep;
46315 +       dwc_irqflags_t flags;
46316 +       int retval = 0;
46317 +
46318 +       ep = get_ep_from_handle(pcd, ep_handle);
46319 +
46320 +       if ((!ep->desc && ep != &pcd->ep0) ||
46321 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46322 +               DWC_WARN("%s, bad ep\n", __func__);
46323 +               return -DWC_E_INVALID;
46324 +       }
46325 +
46326 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46327 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46328 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46329 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
46330 +               retval = -DWC_E_AGAIN;
46331 +       } else {
46332 +                /* This code needs to be reviewed */
46333 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46334 +                       dtxfsts_data_t txstatus;
46335 +                       fifosize_data_t txfifosize;
46336 +
46337 +                       txfifosize.d32 =
46338 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
46339 +                                          core_global_regs->dtxfsiz[ep->dwc_ep.
46340 +                                                                    tx_fifo_num]);
46341 +                       txstatus.d32 =
46342 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
46343 +                                          dev_if->in_ep_regs[ep->dwc_ep.num]->
46344 +                                          dtxfsts);
46345 +
46346 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46347 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46348 +                               retval = -DWC_E_AGAIN;
46349 +                       } else {
46350 +                               if (ep->dwc_ep.num == 0) {
46351 +                                       pcd->ep0state = EP0_STALL;
46352 +                               }
46353 +
46354 +                               ep->stopped = 1;
46355 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46356 +                                                    &ep->dwc_ep);
46357 +                       }
46358 +               } else {
46359 +                       if (ep->dwc_ep.num == 0) {
46360 +                               pcd->ep0state = EP0_STALL;
46361 +                       }
46362 +
46363 +                       ep->stopped = 1;
46364 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46365 +               }
46366 +       }
46367 +
46368 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46369 +
46370 +       return retval;
46371 +}
46372 +   
46373 +int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
46374 +{
46375 +       dwc_otg_pcd_ep_t *ep;
46376 +       dwc_irqflags_t flags;
46377 +       int retval = 0;
46378 +
46379 +       ep = get_ep_from_handle(pcd, ep_handle);
46380 +
46381 +       if (!ep || (!ep->desc && ep != &pcd->ep0) ||
46382 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46383 +               DWC_WARN("%s, bad ep\n", __func__);
46384 +               return -DWC_E_INVALID;
46385 +       }
46386 +
46387 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46388 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46389 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46390 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
46391 +               retval = -DWC_E_AGAIN;
46392 +       } else if (value == 0) {
46393 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46394 +       } else if (value == 1) {
46395 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46396 +                       dtxfsts_data_t txstatus;
46397 +                       fifosize_data_t txfifosize;
46398 +
46399 +                       txfifosize.d32 =
46400 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->
46401 +                                          dtxfsiz[ep->dwc_ep.tx_fifo_num]);
46402 +                       txstatus.d32 =
46403 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
46404 +                                          in_ep_regs[ep->dwc_ep.num]->dtxfsts);
46405 +
46406 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46407 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46408 +                               retval = -DWC_E_AGAIN;
46409 +                       } else {
46410 +                               if (ep->dwc_ep.num == 0) {
46411 +                                       pcd->ep0state = EP0_STALL;
46412 +                               }
46413 +
46414 +                               ep->stopped = 1;
46415 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46416 +                                                    &ep->dwc_ep);
46417 +                       }
46418 +               } else {
46419 +                       if (ep->dwc_ep.num == 0) {
46420 +                               pcd->ep0state = EP0_STALL;
46421 +                       }
46422 +
46423 +                       ep->stopped = 1;
46424 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46425 +               }
46426 +       } else if (value == 2) {
46427 +               ep->dwc_ep.stall_clear_flag = 0;
46428 +       } else if (value == 3) {
46429 +               ep->dwc_ep.stall_clear_flag = 1;
46430 +       }
46431 +
46432 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46433 +
46434 +       return retval;
46435 +}
46436 +
46437 +/**
46438 + * This function initiates remote wakeup of the host from suspend state.
46439 + */
46440 +void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
46441 +{
46442 +       dctl_data_t dctl = { 0 };
46443 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46444 +       dsts_data_t dsts;
46445 +
46446 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
46447 +       if (!dsts.b.suspsts) {
46448 +               DWC_WARN("Remote wakeup while is not in suspend state\n");
46449 +       }
46450 +       /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
46451 +       if (pcd->remote_wakeup_enable) {
46452 +               if (set) {
46453 +
46454 +                       if (core_if->adp_enable) {
46455 +                               gpwrdn_data_t gpwrdn;
46456 +
46457 +                               dwc_otg_adp_probe_stop(core_if);
46458 +
46459 +                               /* Mask SRP detected interrupt from Power Down Logic */
46460 +                               gpwrdn.d32 = 0;
46461 +                               gpwrdn.b.srp_det_msk = 1;
46462 +                               DWC_MODIFY_REG32(&core_if->
46463 +                                                core_global_regs->gpwrdn,
46464 +                                                gpwrdn.d32, 0);
46465 +
46466 +                               /* Disable Power Down Logic */
46467 +                               gpwrdn.d32 = 0;
46468 +                               gpwrdn.b.pmuactv = 1;
46469 +                               DWC_MODIFY_REG32(&core_if->
46470 +                                                core_global_regs->gpwrdn,
46471 +                                                gpwrdn.d32, 0);
46472 +
46473 +                               /*
46474 +                                * Initialize the Core for Device mode.
46475 +                                */
46476 +                               core_if->op_state = B_PERIPHERAL;
46477 +                               dwc_otg_core_init(core_if);
46478 +                               dwc_otg_enable_global_interrupts(core_if);
46479 +                               cil_pcd_start(core_if);
46480 +
46481 +                               dwc_otg_initiate_srp(core_if);
46482 +                       }
46483 +
46484 +                       dctl.b.rmtwkupsig = 1;
46485 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46486 +                                        dctl, 0, dctl.d32);
46487 +                       DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46488 +
46489 +                       dwc_mdelay(2);
46490 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46491 +                                        dctl, dctl.d32, 0);
46492 +                       DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
46493 +               }
46494 +       } else {
46495 +               DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
46496 +       }
46497 +}
46498 +
46499 +#ifdef CONFIG_USB_DWC_OTG_LPM
46500 +/**
46501 + * This function initiates remote wakeup of the host from L1 sleep state.
46502 + */
46503 +void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
46504 +{
46505 +       glpmcfg_data_t lpmcfg;
46506 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46507 +
46508 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46509 +
46510 +       /* Check if we are in L1 state */
46511 +       if (!lpmcfg.b.prt_sleep_sts) {
46512 +               DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
46513 +               return;
46514 +       }
46515 +
46516 +       /* Check if host allows remote wakeup */
46517 +       if (!lpmcfg.b.rem_wkup_en) {
46518 +               DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
46519 +               return;
46520 +       }
46521 +
46522 +       /* Check if Resume OK */
46523 +       if (!lpmcfg.b.sleep_state_resumeok) {
46524 +               DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
46525 +               return;
46526 +       }
46527 +
46528 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46529 +       lpmcfg.b.en_utmi_sleep = 0;
46530 +       lpmcfg.b.hird_thres &= (~(1 << 4));
46531 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
46532 +
46533 +       if (set) {
46534 +               dctl_data_t dctl = {.d32 = 0 };
46535 +               dctl.b.rmtwkupsig = 1;
46536 +               /* Set RmtWkUpSig bit to start remote wakup signaling.
46537 +                * Hardware will automatically clear this bit.
46538 +                */
46539 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,
46540 +                                0, dctl.d32);
46541 +               DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46542 +       }
46543 +
46544 +}
46545 +#endif
46546 +
46547 +/**
46548 + * Performs remote wakeup.
46549 + */
46550 +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
46551 +{
46552 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46553 +       dwc_irqflags_t flags;
46554 +       if (dwc_otg_is_device_mode(core_if)) {
46555 +               DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46556 +#ifdef CONFIG_USB_DWC_OTG_LPM
46557 +               if (core_if->lx_state == DWC_OTG_L1) {
46558 +                       dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
46559 +               } else {
46560 +#endif
46561 +                       dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
46562 +#ifdef CONFIG_USB_DWC_OTG_LPM
46563 +               }
46564 +#endif
46565 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46566 +       }
46567 +       return;
46568 +}
46569 +
46570 +void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs)
46571 +{
46572 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46573 +       dctl_data_t dctl = { 0 };
46574 +
46575 +       if (dwc_otg_is_device_mode(core_if)) {
46576 +               dctl.b.sftdiscon = 1;
46577 +               DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs);
46578 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
46579 +               dwc_udelay(no_of_usecs);
46580 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0);
46581 +               
46582 +       } else{
46583 +               DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n");
46584 +       }
46585 +       return;
46586 +
46587 +}
46588 +
46589 +int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
46590 +{
46591 +       dsts_data_t dsts;
46592 +       gotgctl_data_t gotgctl;
46593 +
46594 +       /*
46595 +        * This function starts the Protocol if no session is in progress. If
46596 +        * a session is already in progress, but the device is suspended,
46597 +        * remote wakeup signaling is started.
46598 +        */
46599 +
46600 +       /* Check if valid session */
46601 +       gotgctl.d32 =
46602 +           DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
46603 +       if (gotgctl.b.bsesvld) {
46604 +               /* Check if suspend state */
46605 +               dsts.d32 =
46606 +                   DWC_READ_REG32(&
46607 +                                  (GET_CORE_IF(pcd)->dev_if->
46608 +                                   dev_global_regs->dsts));
46609 +               if (dsts.b.suspsts) {
46610 +                       dwc_otg_pcd_remote_wakeup(pcd, 1);
46611 +               }
46612 +       } else {
46613 +               dwc_otg_pcd_initiate_srp(pcd);
46614 +       }
46615 +
46616 +       return 0;
46617 +
46618 +}
46619 +
46620 +/**
46621 + * Start the SRP timer to detect when the SRP does not complete within
46622 + * 6 seconds.
46623 + *
46624 + * @param pcd the pcd structure.
46625 + */
46626 +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
46627 +{
46628 +       dwc_irqflags_t flags;
46629 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46630 +       dwc_otg_initiate_srp(GET_CORE_IF(pcd));
46631 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46632 +}
46633 +
46634 +int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
46635 +{
46636 +       return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
46637 +}
46638 +
46639 +int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
46640 +{
46641 +       return GET_CORE_IF(pcd)->core_params->lpm_enable;
46642 +}
46643 +
46644 +uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
46645 +{
46646 +       return pcd->b_hnp_enable;
46647 +}
46648 +
46649 +uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
46650 +{
46651 +       return pcd->a_hnp_support;
46652 +}
46653 +
46654 +uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
46655 +{
46656 +       return pcd->a_alt_hnp_support;
46657 +}
46658 +
46659 +int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
46660 +{
46661 +       return pcd->remote_wakeup_enable;
46662 +}
46663 +
46664 +#endif /* DWC_HOST_ONLY */
46665 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
46666 new file mode 100644
46667 index 0000000..8ef7ba6
46668 --- /dev/null
46669 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
46670 @@ -0,0 +1,266 @@
46671 +/* ==========================================================================
46672 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
46673 + * $Revision: #48 $
46674 + * $Date: 2012/08/10 $
46675 + * $Change: 2047372 $
46676 + *
46677 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46678 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46679 + * otherwise expressly agreed to in writing between Synopsys and you.
46680 + *
46681 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46682 + * any End User Software License Agreement or Agreement for Licensed Product
46683 + * with Synopsys or any supplement thereto. You are permitted to use and
46684 + * redistribute this Software in source and binary forms, with or without
46685 + * modification, provided that redistributions of source code must retain this
46686 + * notice. You may not view, use, disclose, copy or distribute this file or
46687 + * any information contained herein except pursuant to this license grant from
46688 + * Synopsys. If you do not agree with this notice, including the disclaimer
46689 + * below, then you are not authorized to use the Software.
46690 + *
46691 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46692 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46693 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46694 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46695 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46696 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46697 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46698 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46699 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46700 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46701 + * DAMAGE.
46702 + * ========================================================================== */
46703 +#ifndef DWC_HOST_ONLY
46704 +#if !defined(__DWC_PCD_H__)
46705 +#define __DWC_PCD_H__
46706 +
46707 +#include "dwc_otg_os_dep.h"
46708 +#include "usb.h"
46709 +#include "dwc_otg_cil.h"
46710 +#include "dwc_otg_pcd_if.h"
46711 +struct cfiobject;
46712 +
46713 +/**
46714 + * @file
46715 + *
46716 + * This file contains the structures, constants, and interfaces for
46717 + * the Perpherial Contoller Driver (PCD).
46718 + *
46719 + * The Peripheral Controller Driver (PCD) for Linux will implement the
46720 + * Gadget API, so that the existing Gadget drivers can be used. For
46721 + * the Mass Storage Function driver the File-backed USB Storage Gadget
46722 + * (FBS) driver will be used.  The FBS driver supports the
46723 + * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
46724 + * transports.
46725 + *
46726 + */
46727 +
46728 +/** Invalid DMA Address */
46729 +#define DWC_DMA_ADDR_INVALID   (~(dwc_dma_t)0)
46730 +
46731 +/** Max Transfer size for any EP */
46732 +#define DDMA_MAX_TRANSFER_SIZE 65535
46733 +
46734 +/**
46735 + * Get the pointer to the core_if from the pcd pointer.
46736 + */
46737 +#define GET_CORE_IF( _pcd ) (_pcd->core_if)
46738 +
46739 +/**
46740 + * States of EP0.
46741 + */
46742 +typedef enum ep0_state {
46743 +       EP0_DISCONNECT,         /* no host */
46744 +       EP0_IDLE,
46745 +       EP0_IN_DATA_PHASE,
46746 +       EP0_OUT_DATA_PHASE,
46747 +       EP0_IN_STATUS_PHASE,
46748 +       EP0_OUT_STATUS_PHASE,
46749 +       EP0_STALL,
46750 +} ep0state_e;
46751 +
46752 +/** Fordward declaration.*/
46753 +struct dwc_otg_pcd;
46754 +
46755 +/** DWC_otg iso request structure.
46756 + *
46757 + */
46758 +typedef struct usb_iso_request dwc_otg_pcd_iso_request_t;
46759 +
46760 +#ifdef DWC_UTE_PER_IO
46761 +
46762 +/**
46763 + * This shall be the exact analogy of the same type structure defined in the
46764 + * usb_gadget.h. Each descriptor contains
46765 + */
46766 +struct dwc_iso_pkt_desc_port {
46767 +       uint32_t offset;
46768 +       uint32_t length;        /* expected length */
46769 +       uint32_t actual_length;
46770 +       uint32_t status;
46771 +};
46772 +
46773 +struct dwc_iso_xreq_port {
46774 +       /** transfer/submission flag */
46775 +       uint32_t tr_sub_flags;
46776 +       /** Start the request ASAP */
46777 +#define DWC_EREQ_TF_ASAP               0x00000002
46778 +       /** Just enqueue the request w/o initiating a transfer */
46779 +#define DWC_EREQ_TF_ENQUEUE            0x00000004
46780 +
46781 +       /**
46782 +       * count of ISO packets attached to this request - shall
46783 +       * not exceed the pio_alloc_pkt_count
46784 +       */
46785 +       uint32_t pio_pkt_count;
46786 +       /** count of ISO packets allocated for this request */
46787 +       uint32_t pio_alloc_pkt_count;
46788 +       /** number of ISO packet errors */
46789 +       uint32_t error_count;
46790 +       /** reserved for future extension */
46791 +       uint32_t res;
46792 +       /** Will be allocated and freed in the UTE gadget and based on the CFC value */
46793 +       struct dwc_iso_pkt_desc_port *per_io_frame_descs;
46794 +};
46795 +#endif
46796 +/** DWC_otg request structure.
46797 + * This structure is a list of requests.
46798 + */
46799 +typedef struct dwc_otg_pcd_request {
46800 +       void *priv;
46801 +       void *buf;
46802 +       dwc_dma_t dma;
46803 +       uint32_t length;
46804 +       uint32_t actual;
46805 +       unsigned sent_zlp:1;
46806 +    /**
46807 +     * Used instead of original buffer if
46808 +     * it(physical address) is not dword-aligned.
46809 +     **/
46810 +     uint8_t *dw_align_buf;
46811 +     dwc_dma_t dw_align_buf_dma;
46812 +
46813 +        DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;
46814 +#ifdef DWC_UTE_PER_IO
46815 +       struct dwc_iso_xreq_port ext_req;
46816 +       //void *priv_ereq_nport; /*  */
46817 +#endif
46818 +} dwc_otg_pcd_request_t;
46819 +
46820 +DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request);
46821 +
46822 +/**      PCD EP structure.
46823 + * This structure describes an EP, there is an array of EPs in the PCD
46824 + * structure.
46825 + */
46826 +typedef struct dwc_otg_pcd_ep {
46827 +       /** USB EP Descriptor */
46828 +       const usb_endpoint_descriptor_t *desc;
46829 +
46830 +       /** queue of dwc_otg_pcd_requests. */
46831 +       struct req_list queue;
46832 +       unsigned stopped:1;
46833 +       unsigned disabling:1;
46834 +       unsigned dma:1;
46835 +       unsigned queue_sof:1;
46836 +
46837 +#ifdef DWC_EN_ISOC
46838 +       /** ISOC req handle passed */
46839 +       void *iso_req_handle;
46840 +#endif                         //_EN_ISOC_
46841 +
46842 +       /** DWC_otg ep data. */
46843 +       dwc_ep_t dwc_ep;
46844 +
46845 +       /** Pointer to PCD */
46846 +       struct dwc_otg_pcd *pcd;
46847 +
46848 +       void *priv;
46849 +} dwc_otg_pcd_ep_t;
46850 +
46851 +/** DWC_otg PCD Structure.
46852 + * This structure encapsulates the data for the dwc_otg PCD.
46853 + */
46854 +struct dwc_otg_pcd {
46855 +       const struct dwc_otg_pcd_function_ops *fops;
46856 +       /** The DWC otg device pointer */
46857 +       struct dwc_otg_device *otg_dev;
46858 +       /** Core Interface */
46859 +       dwc_otg_core_if_t *core_if;
46860 +       /** State of EP0 */
46861 +       ep0state_e ep0state;
46862 +       /** EP0 Request is pending */
46863 +       unsigned ep0_pending:1;
46864 +       /** Indicates when SET CONFIGURATION Request is in process */
46865 +       unsigned request_config:1;
46866 +       /** The state of the Remote Wakeup Enable. */
46867 +       unsigned remote_wakeup_enable:1;
46868 +       /** The state of the B-Device HNP Enable. */
46869 +       unsigned b_hnp_enable:1;
46870 +       /** The state of A-Device HNP Support. */
46871 +       unsigned a_hnp_support:1;
46872 +       /** The state of the A-Device Alt HNP support. */
46873 +       unsigned a_alt_hnp_support:1;
46874 +       /** Count of pending Requests */
46875 +       unsigned request_pending;
46876 +
46877 +       /** SETUP packet for EP0
46878 +        * This structure is allocated as a DMA buffer on PCD initialization
46879 +        * with enough space for up to 3 setup packets.
46880 +        */
46881 +       union {
46882 +               usb_device_request_t req;
46883 +               uint32_t d32[2];
46884 +       } *setup_pkt;
46885 +
46886 +       dwc_dma_t setup_pkt_dma_handle;
46887 +
46888 +       /* Additional buffer and flag for CTRL_WR premature case */
46889 +       uint8_t *backup_buf;
46890 +       unsigned data_terminated;
46891 +
46892 +       /** 2-byte dma buffer used to return status from GET_STATUS */
46893 +       uint16_t *status_buf;
46894 +       dwc_dma_t status_buf_dma_handle;
46895 +
46896 +       /** EP0 */
46897 +       dwc_otg_pcd_ep_t ep0;
46898 +
46899 +       /** Array of IN EPs. */
46900 +       dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];
46901 +       /** Array of OUT EPs. */
46902 +       dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];
46903 +       /** number of valid EPs in the above array. */
46904 +//        unsigned      num_eps : 4;
46905 +       dwc_spinlock_t *lock;
46906 +
46907 +       /** Tasklet to defer starting of TEST mode transmissions until
46908 +        *      Status Phase has been completed.
46909 +        */
46910 +       dwc_tasklet_t *test_mode_tasklet;
46911 +
46912 +       /** Tasklet to delay starting of xfer in DMA mode */
46913 +       dwc_tasklet_t *start_xfer_tasklet;
46914 +
46915 +       /** The test mode to enter when the tasklet is executed. */
46916 +       unsigned test_mode;
46917 +       /** The cfi_api structure that implements most of the CFI API
46918 +        * and OTG specific core configuration functionality
46919 +        */
46920 +#ifdef DWC_UTE_CFI
46921 +       struct cfiobject *cfi;
46922 +#endif
46923 +
46924 +};
46925 +
46926 +//FIXME this functions should be static, and this prototypes should be removed
46927 +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep);
46928 +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep,
46929 +                                dwc_otg_pcd_request_t * req, int32_t status);
46930 +
46931 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
46932 +                            void *req_handle);
46933 +
46934 +extern void do_test_mode(void *data);
46935 +#endif
46936 +#endif /* DWC_HOST_ONLY */
46937 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
46938 new file mode 100644
46939 index 0000000..c8d2e0e
46940 --- /dev/null
46941 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
46942 @@ -0,0 +1,360 @@
46943 +/* ==========================================================================
46944 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
46945 + * $Revision: #11 $
46946 + * $Date: 2011/10/26 $
46947 + * $Change: 1873028 $
46948 + *
46949 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46950 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46951 + * otherwise expressly agreed to in writing between Synopsys and you.
46952 + *
46953 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46954 + * any End User Software License Agreement or Agreement for Licensed Product
46955 + * with Synopsys or any supplement thereto. You are permitted to use and
46956 + * redistribute this Software in source and binary forms, with or without
46957 + * modification, provided that redistributions of source code must retain this
46958 + * notice. You may not view, use, disclose, copy or distribute this file or
46959 + * any information contained herein except pursuant to this license grant from
46960 + * Synopsys. If you do not agree with this notice, including the disclaimer
46961 + * below, then you are not authorized to use the Software.
46962 + *
46963 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46964 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46965 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46966 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46967 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46968 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46969 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46970 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46971 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46972 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46973 + * DAMAGE.
46974 + * ========================================================================== */
46975 +#ifndef DWC_HOST_ONLY
46976 +
46977 +#if !defined(__DWC_PCD_IF_H__)
46978 +#define __DWC_PCD_IF_H__
46979 +
46980 +//#include "dwc_os.h"
46981 +#include "dwc_otg_core_if.h"
46982 +
46983 +/** @file
46984 + * This file defines DWC_OTG PCD Core API.
46985 + */
46986 +
46987 +struct dwc_otg_pcd;
46988 +typedef struct dwc_otg_pcd dwc_otg_pcd_t;
46989 +
46990 +/** Maxpacket size for EP0 */
46991 +#define MAX_EP0_SIZE   64
46992 +/** Maxpacket size for any EP */
46993 +#define MAX_PACKET_SIZE 1024
46994 +
46995 +/** @name Function Driver Callbacks */
46996 +/** @{ */
46997 +
46998 +/** This function will be called whenever a previously queued request has
46999 + * completed.  The status value will be set to -DWC_E_SHUTDOWN to indicated a
47000 + * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset,
47001 + * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid
47002 + * parameters. */
47003 +typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
47004 +                                   void *req_handle, int32_t status,
47005 +                                   uint32_t actual);
47006 +/**
47007 + * This function will be called whenever a previousle queued ISOC request has
47008 + * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count
47009 + * function.
47010 + * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_*
47011 + * functions.
47012 + */
47013 +typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
47014 +                                        void *req_handle, int proc_buf_num);
47015 +/** This function should handle any SETUP request that cannot be handled by the
47016 + * PCD Core.  This includes most GET_DESCRIPTORs, SET_CONFIGS, Any
47017 + * class-specific requests, etc.  The function must non-blocking.
47018 + *
47019 + * Returns 0 on success.
47020 + * Returns -DWC_E_NOT_SUPPORTED if the request is not supported.
47021 + * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes.
47022 + * Returns -DWC_E_SHUTDOWN on any other error. */
47023 +typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes);
47024 +/** This is called whenever the device has been disconnected.  The function
47025 + * driver should take appropriate action to clean up all pending requests in the
47026 + * PCD Core, remove all endpoints (except ep0), and initialize back to reset
47027 + * state. */
47028 +typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd);
47029 +/** This function is called when device has been connected. */
47030 +typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed);
47031 +/** This function is called when device has been suspended */
47032 +typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd);
47033 +/** This function is called when device has received LPM tokens, i.e.
47034 + * device has been sent to sleep state. */
47035 +typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd);
47036 +/** This function is called when device has been resumed
47037 + * from suspend(L2) or L1 sleep state. */
47038 +typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd);
47039 +/** This function is called whenever hnp params has been changed.
47040 + * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions
47041 + * to get hnp parameters. */
47042 +typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd);
47043 +/** This function is called whenever USB RESET is detected. */
47044 +typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd);
47045 +
47046 +typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes);
47047 +
47048 +/**
47049 + *
47050 + * @param ep_handle    Void pointer to the usb_ep structure
47051 + * @param ereq_port Pointer to the extended request structure created in the
47052 + *                                     portable part.
47053 + */
47054 +typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
47055 +                                    void *req_handle, int32_t status,
47056 +                                    void *ereq_port);
47057 +/** Function Driver Ops Data Structure */
47058 +struct dwc_otg_pcd_function_ops {
47059 +       dwc_connect_cb_t connect;
47060 +       dwc_disconnect_cb_t disconnect;
47061 +       dwc_setup_cb_t setup;
47062 +       dwc_completion_cb_t complete;
47063 +       dwc_isoc_completion_cb_t isoc_complete;
47064 +       dwc_suspend_cb_t suspend;
47065 +       dwc_sleep_cb_t sleep;
47066 +       dwc_resume_cb_t resume;
47067 +       dwc_reset_cb_t reset;
47068 +       dwc_hnp_params_changed_cb_t hnp_changed;
47069 +       cfi_setup_cb_t cfi_setup;
47070 +#ifdef DWC_UTE_PER_IO
47071 +       xiso_completion_cb_t xisoc_complete;
47072 +#endif
47073 +};
47074 +/** @} */
47075 +
47076 +/** @name Function Driver Functions */
47077 +/** @{ */
47078 +
47079 +/** Call this function to get pointer on dwc_otg_pcd_t,
47080 + * this pointer will be used for all PCD API functions.
47081 + *
47082 + * @param core_if The DWC_OTG Core
47083 + */
47084 +extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);
47085 +
47086 +/** Frees PCD allocated by dwc_otg_pcd_init
47087 + *
47088 + * @param pcd The PCD
47089 + */
47090 +extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd);
47091 +
47092 +/** Call this to bind the function driver to the PCD Core.
47093 + *
47094 + * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function.
47095 + * @param fops The Function Driver Ops data structure containing pointers to all callbacks.
47096 + */
47097 +extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
47098 +                             const struct dwc_otg_pcd_function_ops *fops);
47099 +
47100 +/** Enables an endpoint for use.  This function enables an endpoint in
47101 + * the PCD.  The endpoint is described by the ep_desc which has the
47102 + * same format as a USB ep descriptor.  The ep_handle parameter is used to refer
47103 + * to the endpoint from other API functions and in callbacks.  Normally this
47104 + * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the
47105 + * core for that interface.
47106 + *
47107 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47108 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47109 + * Returns 0 on success.
47110 + *
47111 + * @param pcd The PCD
47112 + * @param ep_desc Endpoint descriptor
47113 + * @param usb_ep Handle on endpoint, that will be used to identify endpoint.
47114 + */
47115 +extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
47116 +                                const uint8_t * ep_desc, void *usb_ep);
47117 +
47118 +/** Disable the endpoint referenced by ep_handle.
47119 + *
47120 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47121 + * Returns -DWC_E_SHUTDOWN if any other error occurred.
47122 + * Returns 0 on success. */
47123 +extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);
47124 +
47125 +/** Queue a data transfer request on the endpoint referenced by ep_handle.
47126 + * After the transfer is completes, the complete callback will be called with
47127 + * the request status.
47128 + *
47129 + * @param pcd The PCD
47130 + * @param ep_handle The handle of the endpoint
47131 + * @param buf The buffer for the data
47132 + * @param dma_buf The DMA buffer for the data
47133 + * @param buflen The length of the data transfer
47134 + * @param zero Specifies whether to send zero length last packet.
47135 + * @param req_handle Set this handle to any value to use to reference this
47136 + * request in the ep_dequeue function or from the complete callback
47137 + * @param atomic_alloc If driver need to perform atomic allocations
47138 + * for internal data structures.
47139 + *
47140 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47141 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47142 + * Returns 0 on success. */
47143 +extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
47144 +                               uint8_t * buf, dwc_dma_t dma_buf,
47145 +                               uint32_t buflen, int zero, void *req_handle,
47146 +                               int atomic_alloc);
47147 +#ifdef DWC_UTE_PER_IO
47148 +/**
47149 + *
47150 + * @param ereq_nonport Pointer to the extended request part of the
47151 + *                                             usb_request structure defined in usb_gadget.h file.
47152 + */
47153 +extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
47154 +                                    uint8_t * buf, dwc_dma_t dma_buf,
47155 +                                    uint32_t buflen, int zero,
47156 +                                    void *req_handle, int atomic_alloc,
47157 +                                    void *ereq_nonport);
47158 +
47159 +#endif
47160 +
47161 +/** De-queue the specified data transfer that has not yet completed.
47162 + *
47163 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47164 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47165 + * Returns 0 on success. */
47166 +extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
47167 +                                 void *req_handle);
47168 +
47169 +/** Halt (STALL) an endpoint or clear it.
47170 + *
47171 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47172 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47173 + * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later
47174 + * Returns 0 on success. */
47175 +extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value);
47176 +
47177 +/** This function */
47178 +extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle);
47179 +
47180 +/** This function should be called on every hardware interrupt */
47181 +extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);
47182 +
47183 +/** This function returns current frame number */
47184 +extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd);
47185 +
47186 +/**
47187 + * Start isochronous transfers on the endpoint referenced by ep_handle.
47188 + * For isochronous transfers duble buffering is used.
47189 + * After processing each of buffers comlete callback will be called with
47190 + * status for each transaction.
47191 + *
47192 + * @param pcd The PCD
47193 + * @param ep_handle The handle of the endpoint
47194 + * @param buf0 The virtual address of first data buffer
47195 + * @param buf1 The virtual address of second data buffer
47196 + * @param dma0 The DMA address of first data buffer
47197 + * @param dma1 The DMA address of second data buffer
47198 + * @param sync_frame Data pattern frame number
47199 + * @param dp_frame Data size for pattern frame
47200 + * @param data_per_frame Data size for regular frame
47201 + * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP.
47202 + * @param buf_proc_intrvl Interval of ISOC Buffer processing
47203 + * @param req_handle Handle of ISOC request
47204 + * @param atomic_alloc Specefies whether to perform atomic allocation for
47205 + *                     internal data structures.
47206 + *
47207 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
47208 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function.
47209 + * Returns -DW_E_SHUTDOWN for any other error.
47210 + * Returns 0 on success
47211 + */
47212 +extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
47213 +                                   uint8_t * buf0, uint8_t * buf1,
47214 +                                   dwc_dma_t dma0, dwc_dma_t dma1,
47215 +                                   int sync_frame, int dp_frame,
47216 +                                   int data_per_frame, int start_frame,
47217 +                                   int buf_proc_intrvl, void *req_handle,
47218 +                                   int atomic_alloc);
47219 +
47220 +/** Stop ISOC transfers on endpoint referenced by ep_handle.
47221 + *
47222 + * @param pcd The PCD
47223 + * @param ep_handle The handle of the endpoint
47224 + * @param req_handle Handle of ISOC request
47225 + *
47226 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function
47227 + * Returns 0 on success
47228 + */
47229 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
47230 +                           void *req_handle);
47231 +
47232 +/** Get ISOC packet status.
47233 + *
47234 + * @param pcd The PCD
47235 + * @param ep_handle The handle of the endpoint
47236 + * @param iso_req_handle Isochronoush request handle
47237 + * @param packet Number of packet
47238 + * @param status Out parameter for returning status
47239 + * @param actual Out parameter for returning actual length
47240 + * @param offset Out parameter for returning offset
47241 + *
47242 + */
47243 +extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd,
47244 +                                             void *ep_handle,
47245 +                                             void *iso_req_handle, int packet,
47246 +                                             int *status, int *actual,
47247 +                                             int *offset);
47248 +
47249 +/** Get ISOC packet count.
47250 + *
47251 + * @param pcd The PCD
47252 + * @param ep_handle The handle of the endpoint
47253 + * @param iso_req_handle
47254 + */
47255 +extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd,
47256 +                                           void *ep_handle,
47257 +                                           void *iso_req_handle);
47258 +
47259 +/** This function starts the SRP Protocol if no session is in progress. If
47260 + * a session is already in progress, but the device is suspended,
47261 + * remote wakeup signaling is started.
47262 + */
47263 +extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd);
47264 +
47265 +/** This function returns 1 if LPM support is enabled, and 0 otherwise. */
47266 +extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd);
47267 +
47268 +/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */
47269 +extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd);
47270 +
47271 +/** Initiate SRP */
47272 +extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd);
47273 +
47274 +/** Starts remote wakeup signaling. */
47275 +extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set);
47276 +
47277 +/** Starts micorsecond soft disconnect. */
47278 +extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs);
47279 +/** This function returns whether device is dualspeed.*/
47280 +extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd);
47281 +
47282 +/** This function returns whether device is otg. */
47283 +extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd);
47284 +
47285 +/** These functions allow to get hnp parameters */
47286 +extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd);
47287 +extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd);
47288 +extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd);
47289 +
47290 +/** CFI specific Interface functions */
47291 +/** Allocate a cfi buffer */
47292 +extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep,
47293 +                                    dwc_dma_t * addr, size_t buflen,
47294 +                                    int flags);
47295 +
47296 +/******************************************************************************/
47297 +
47298 +/** @} */
47299 +
47300 +#endif                         /* __DWC_PCD_IF_H__ */
47301 +
47302 +#endif                         /* DWC_HOST_ONLY */
47303 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
47304 new file mode 100644
47305 index 0000000..27061d3
47306 --- /dev/null
47307 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
47308 @@ -0,0 +1,5147 @@
47309 +/* ==========================================================================
47310 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
47311 + * $Revision: #116 $
47312 + * $Date: 2012/08/10 $
47313 + * $Change: 2047372 $
47314 + *
47315 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
47316 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
47317 + * otherwise expressly agreed to in writing between Synopsys and you.
47318 + *
47319 + * The Software IS NOT an item of Licensed Software or Licensed Product under
47320 + * any End User Software License Agreement or Agreement for Licensed Product
47321 + * with Synopsys or any supplement thereto. You are permitted to use and
47322 + * redistribute this Software in source and binary forms, with or without
47323 + * modification, provided that redistributions of source code must retain this
47324 + * notice. You may not view, use, disclose, copy or distribute this file or
47325 + * any information contained herein except pursuant to this license grant from
47326 + * Synopsys. If you do not agree with this notice, including the disclaimer
47327 + * below, then you are not authorized to use the Software.
47328 + *
47329 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
47330 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47331 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47332 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
47333 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47334 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47335 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47336 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47337 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47338 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
47339 + * DAMAGE.
47340 + * ========================================================================== */
47341 +#ifndef DWC_HOST_ONLY
47342 +
47343 +#include "dwc_otg_pcd.h"
47344 +
47345 +#ifdef DWC_UTE_CFI
47346 +#include "dwc_otg_cfi.h"
47347 +#endif
47348 +
47349 +#ifdef DWC_UTE_PER_IO
47350 +extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep);
47351 +#endif
47352 +//#define PRINT_CFI_DMA_DESCS
47353 +
47354 +#define DEBUG_EP0
47355 +
47356 +/**
47357 + * This function updates OTG.
47358 + */
47359 +static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
47360 +{
47361 +
47362 +       if (reset) {
47363 +               pcd->b_hnp_enable = 0;
47364 +               pcd->a_hnp_support = 0;
47365 +               pcd->a_alt_hnp_support = 0;
47366 +       }
47367 +
47368 +       if (pcd->fops->hnp_changed) {
47369 +               pcd->fops->hnp_changed(pcd);
47370 +       }
47371 +}
47372 +
47373 +/** @file
47374 + * This file contains the implementation of the PCD Interrupt handlers.
47375 + *
47376 + * The PCD handles the device interrupts.  Many conditions can cause a
47377 + * device interrupt. When an interrupt occurs, the device interrupt
47378 + * service routine determines the cause of the interrupt and
47379 + * dispatches handling to the appropriate function. These interrupt
47380 + * handling functions are described below.
47381 + * All interrupt registers are processed from LSB to MSB.
47382 + */
47383 +
47384 +/**
47385 + * This function prints the ep0 state for debug purposes.
47386 + */
47387 +static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
47388 +{
47389 +#ifdef DEBUG
47390 +       char str[40];
47391 +
47392 +       switch (pcd->ep0state) {
47393 +       case EP0_DISCONNECT:
47394 +               dwc_strcpy(str, "EP0_DISCONNECT");
47395 +               break;
47396 +       case EP0_IDLE:
47397 +               dwc_strcpy(str, "EP0_IDLE");
47398 +               break;
47399 +       case EP0_IN_DATA_PHASE:
47400 +               dwc_strcpy(str, "EP0_IN_DATA_PHASE");
47401 +               break;
47402 +       case EP0_OUT_DATA_PHASE:
47403 +               dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
47404 +               break;
47405 +       case EP0_IN_STATUS_PHASE:
47406 +               dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
47407 +               break;
47408 +       case EP0_OUT_STATUS_PHASE:
47409 +               dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
47410 +               break;
47411 +       case EP0_STALL:
47412 +               dwc_strcpy(str, "EP0_STALL");
47413 +               break;
47414 +       default:
47415 +               dwc_strcpy(str, "EP0_INVALID");
47416 +       }
47417 +
47418 +       DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
47419 +#endif
47420 +}
47421 +
47422 +/**
47423 + * This function calculate the size of the payload in the memory 
47424 + * for out endpoints and prints size for debug purposes(used in 
47425 + * 2.93a DevOutNak feature).
47426 + */
47427 +static inline void print_memory_payload(dwc_otg_pcd_t * pcd,  dwc_ep_t * ep)
47428 +{
47429 +#ifdef DEBUG
47430 +       deptsiz_data_t deptsiz_init = {.d32 = 0 };
47431 +       deptsiz_data_t deptsiz_updt = {.d32 = 0 };
47432 +       int pack_num;
47433 +       unsigned payload;
47434 +       
47435 +       deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num];
47436 +       deptsiz_updt.d32 =
47437 +               DWC_READ_REG32(&pcd->core_if->dev_if->
47438 +                                               out_ep_regs[ep->num]->doeptsiz);
47439 +       /* Payload will be */
47440 +       payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize;
47441 +       /* Packet count is decremented every time a packet
47442 +        * is written to the RxFIFO not in to the external memory
47443 +        * So, if payload == 0, then it means no packet was sent to ext memory*/
47444 +       pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt);
47445 +       DWC_DEBUGPL(DBG_PCDV,
47446 +               "Payload for EP%d-%s\n",
47447 +               ep->num, (ep->is_in ? "IN" : "OUT"));
47448 +       DWC_DEBUGPL(DBG_PCDV,
47449 +               "Number of transfered bytes = 0x%08x\n", payload);
47450 +       DWC_DEBUGPL(DBG_PCDV,
47451 +               "Number of transfered packets = %d\n", pack_num);       
47452 +#endif 
47453 +}
47454 +
47455 +
47456 +#ifdef DWC_UTE_CFI
47457 +static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
47458 +                             const uint8_t * epname, int descnum)
47459 +{
47460 +       CFI_INFO
47461 +           ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
47462 +            epname, descnum, ddesc->buf, ddesc->status.b.bytes,
47463 +            ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
47464 +            ddesc->status.b.bs);
47465 +}
47466 +#endif
47467 +
47468 +/**
47469 + * This function returns pointer to in ep struct with number ep_num
47470 + */
47471 +static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47472 +{
47473 +       int i;
47474 +       int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47475 +       if (ep_num == 0) {
47476 +               return &pcd->ep0;
47477 +       } else {
47478 +               for (i = 0; i < num_in_eps; ++i) {
47479 +                       if (pcd->in_ep[i].dwc_ep.num == ep_num)
47480 +                               return &pcd->in_ep[i];
47481 +               }
47482 +               return 0;
47483 +       }
47484 +}
47485 +
47486 +/**
47487 + * This function returns pointer to out ep struct with number ep_num
47488 + */
47489 +static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47490 +{
47491 +       int i;
47492 +       int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47493 +       if (ep_num == 0) {
47494 +               return &pcd->ep0;
47495 +       } else {
47496 +               for (i = 0; i < num_out_eps; ++i) {
47497 +                       if (pcd->out_ep[i].dwc_ep.num == ep_num)
47498 +                               return &pcd->out_ep[i];
47499 +               }
47500 +               return 0;
47501 +       }
47502 +}
47503 +
47504 +/**
47505 + * This functions gets a pointer to an EP from the wIndex address
47506 + * value of the control request.
47507 + */
47508 +dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
47509 +{
47510 +       dwc_otg_pcd_ep_t *ep;
47511 +       uint32_t ep_num = UE_GET_ADDR(wIndex);
47512 +
47513 +       if (ep_num == 0) {
47514 +               ep = &pcd->ep0;
47515 +       } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) {   /* in ep */
47516 +               ep = &pcd->in_ep[ep_num - 1];
47517 +       } else {
47518 +               ep = &pcd->out_ep[ep_num - 1];
47519 +       }
47520 +
47521 +       return ep;
47522 +}
47523 +
47524 +/**
47525 + * This function checks the EP request queue, if the queue is not
47526 + * empty the next request is started.
47527 + */
47528 +void start_next_request(dwc_otg_pcd_ep_t * ep)
47529 +{
47530 +       dwc_otg_pcd_request_t *req = 0;
47531 +       uint32_t max_transfer =
47532 +           GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
47533 +
47534 +#ifdef DWC_UTE_CFI
47535 +       struct dwc_otg_pcd *pcd;
47536 +       pcd = ep->pcd;
47537 +#endif
47538 +
47539 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
47540 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
47541 +
47542 +#ifdef DWC_UTE_CFI
47543 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
47544 +                       ep->dwc_ep.cfi_req_len = req->length;
47545 +                       pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
47546 +               } else {
47547 +#endif
47548 +                       /* Setup and start the Transfer */
47549 +                       if (req->dw_align_buf) {
47550 +                               ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
47551 +                               ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
47552 +                               ep->dwc_ep.xfer_buff = req->dw_align_buf;
47553 +                       } else {
47554 +                               ep->dwc_ep.dma_addr = req->dma;
47555 +                               ep->dwc_ep.start_xfer_buff = req->buf;
47556 +                               ep->dwc_ep.xfer_buff = req->buf;
47557 +                       }
47558 +                       ep->dwc_ep.sent_zlp = 0;
47559 +                       ep->dwc_ep.total_len = req->length;
47560 +                       ep->dwc_ep.xfer_len = 0;
47561 +                       ep->dwc_ep.xfer_count = 0;
47562 +
47563 +                       ep->dwc_ep.maxxfer = max_transfer;
47564 +                       if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
47565 +                               uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
47566 +                                   - (DDMA_MAX_TRANSFER_SIZE % 4);
47567 +                               if (ep->dwc_ep.is_in) {
47568 +                                       if (ep->dwc_ep.maxxfer >
47569 +                                           DDMA_MAX_TRANSFER_SIZE) {
47570 +                                               ep->dwc_ep.maxxfer =
47571 +                                                   DDMA_MAX_TRANSFER_SIZE;
47572 +                                       }
47573 +                               } else {
47574 +                                       if (ep->dwc_ep.maxxfer > out_max_xfer) {
47575 +                                               ep->dwc_ep.maxxfer =
47576 +                                                   out_max_xfer;
47577 +                                       }
47578 +                               }
47579 +                       }
47580 +                       if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
47581 +                               ep->dwc_ep.maxxfer -=
47582 +                                   (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
47583 +                       }
47584 +                       if (req->sent_zlp) {
47585 +                               if ((ep->dwc_ep.total_len %
47586 +                                    ep->dwc_ep.maxpacket == 0)
47587 +                                   && (ep->dwc_ep.total_len != 0)) {
47588 +                                       ep->dwc_ep.sent_zlp = 1;
47589 +                               }
47590 +
47591 +                       }
47592 +#ifdef DWC_UTE_CFI
47593 +               }
47594 +#endif
47595 +               dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
47596 +       } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
47597 +               DWC_PRINTF("There are no more ISOC requests \n");
47598 +               ep->dwc_ep.frame_num = 0xFFFFFFFF;
47599 +       }
47600 +}
47601 +
47602 +/**
47603 + * This function handles the SOF Interrupts. At this time the SOF
47604 + * Interrupt is disabled.
47605 + */
47606 +int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
47607 +{
47608 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47609 +
47610 +       gintsts_data_t gintsts;
47611 +
47612 +       DWC_DEBUGPL(DBG_PCD, "SOF\n");
47613 +
47614 +       /* Clear interrupt */
47615 +       gintsts.d32 = 0;
47616 +       gintsts.b.sofintr = 1;
47617 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
47618 +
47619 +       return 1;
47620 +}
47621 +
47622 +/**
47623 + * This function handles the Rx Status Queue Level Interrupt, which
47624 + * indicates that there is a least one packet in the Rx FIFO.  The
47625 + * packets are moved from the FIFO to memory, where they will be
47626 + * processed when the Endpoint Interrupt Register indicates Transfer
47627 + * Complete or SETUP Phase Done.
47628 + *
47629 + * Repeat the following until the Rx Status Queue is empty:
47630 + *      -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
47631 + *             info
47632 + *      -# If Receive FIFO is empty then skip to step Clear the interrupt
47633 + *             and exit
47634 + *      -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
47635 + *             SETUP data to the buffer
47636 + *      -# If OUT Data Packet call dwc_otg_read_packet to copy the data
47637 + *             to the destination buffer
47638 + */
47639 +int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
47640 +{
47641 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47642 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47643 +       gintmsk_data_t gintmask = {.d32 = 0 };
47644 +       device_grxsts_data_t status;
47645 +       dwc_otg_pcd_ep_t *ep;
47646 +       gintsts_data_t gintsts;
47647 +#ifdef DEBUG
47648 +       static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
47649 +#endif
47650 +
47651 +       //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
47652 +       /* Disable the Rx Status Queue Level interrupt */
47653 +       gintmask.b.rxstsqlvl = 1;
47654 +       DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
47655 +
47656 +       /* Get the Status from the top of the FIFO */
47657 +       status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
47658 +
47659 +       DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
47660 +                   "pktsts:%x Frame:%d(0x%0x)\n",
47661 +                   status.b.epnum, status.b.bcnt,
47662 +                   dpid_str[status.b.dpid],
47663 +                   status.b.pktsts, status.b.fn, status.b.fn);
47664 +       /* Get pointer to EP structure */
47665 +       ep = get_out_ep(pcd, status.b.epnum);
47666 +
47667 +       switch (status.b.pktsts) {
47668 +       case DWC_DSTS_GOUT_NAK:
47669 +               DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
47670 +               break;
47671 +       case DWC_STS_DATA_UPDT:
47672 +               DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
47673 +               if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
47674 +                       /** @todo NGS Check for buffer overflow? */
47675 +                       dwc_otg_read_packet(core_if,
47676 +                                           ep->dwc_ep.xfer_buff,
47677 +                                           status.b.bcnt);
47678 +                       ep->dwc_ep.xfer_count += status.b.bcnt;
47679 +                       ep->dwc_ep.xfer_buff += status.b.bcnt;
47680 +               }
47681 +               break;
47682 +       case DWC_STS_XFER_COMP:
47683 +               DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
47684 +               break;
47685 +       case DWC_DSTS_SETUP_COMP:
47686 +#ifdef DEBUG_EP0
47687 +               DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
47688 +#endif
47689 +               break;
47690 +       case DWC_DSTS_SETUP_UPDT:
47691 +               dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
47692 +#ifdef DEBUG_EP0
47693 +               DWC_DEBUGPL(DBG_PCD,
47694 +                           "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
47695 +                           pcd->setup_pkt->req.bmRequestType,
47696 +                           pcd->setup_pkt->req.bRequest,
47697 +                           UGETW(pcd->setup_pkt->req.wValue),
47698 +                           UGETW(pcd->setup_pkt->req.wIndex),
47699 +                           UGETW(pcd->setup_pkt->req.wLength));
47700 +#endif
47701 +               ep->dwc_ep.xfer_count += status.b.bcnt;
47702 +               break;
47703 +       default:
47704 +               DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
47705 +                           status.b.pktsts);
47706 +               break;
47707 +       }
47708 +
47709 +       /* Enable the Rx Status Queue Level interrupt */
47710 +       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
47711 +       /* Clear interrupt */
47712 +       gintsts.d32 = 0;
47713 +       gintsts.b.rxstsqlvl = 1;
47714 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47715 +
47716 +       //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
47717 +       return 1;
47718 +}
47719 +
47720 +/**
47721 + * This function examines the Device IN Token Learning Queue to
47722 + * determine the EP number of the last IN token received.  This
47723 + * implementation is for the Mass Storage device where there are only
47724 + * 2 IN EPs (Control-IN and BULK-IN).
47725 + *
47726 + * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
47727 + * are 8 EP Numbers in each of the other possible DTKNQ Registers.
47728 + *
47729 + * @param core_if Programming view of DWC_otg controller.
47730 + *
47731 + */
47732 +static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
47733 +{
47734 +       dwc_otg_device_global_regs_t *dev_global_regs =
47735 +           core_if->dev_if->dev_global_regs;
47736 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
47737 +       /* Number of Token Queue Registers */
47738 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
47739 +       dtknq1_data_t dtknqr1;
47740 +       uint32_t in_tkn_epnums[4];
47741 +       int ndx = 0;
47742 +       int i = 0;
47743 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
47744 +       int epnum = 0;
47745 +
47746 +       //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
47747 +
47748 +       /* Read the DTKNQ Registers */
47749 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
47750 +               in_tkn_epnums[i] = DWC_READ_REG32(addr);
47751 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
47752 +                           in_tkn_epnums[i]);
47753 +               if (addr == &dev_global_regs->dvbusdis) {
47754 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
47755 +               } else {
47756 +                       ++addr;
47757 +               }
47758 +
47759 +       }
47760 +
47761 +       /* Copy the DTKNQR1 data to the bit field. */
47762 +       dtknqr1.d32 = in_tkn_epnums[0];
47763 +       /* Get the EP numbers */
47764 +       in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
47765 +       ndx = dtknqr1.b.intknwptr - 1;
47766 +
47767 +       //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
47768 +       if (ndx == -1) {
47769 +               /** @todo Find a simpler way to calculate the max
47770 +                * queue position.*/
47771 +               int cnt = TOKEN_Q_DEPTH;
47772 +               if (TOKEN_Q_DEPTH <= 6) {
47773 +                       cnt = TOKEN_Q_DEPTH - 1;
47774 +               } else if (TOKEN_Q_DEPTH <= 14) {
47775 +                       cnt = TOKEN_Q_DEPTH - 7;
47776 +               } else if (TOKEN_Q_DEPTH <= 22) {
47777 +                       cnt = TOKEN_Q_DEPTH - 15;
47778 +               } else {
47779 +                       cnt = TOKEN_Q_DEPTH - 23;
47780 +               }
47781 +               epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
47782 +       } else {
47783 +               if (ndx <= 5) {
47784 +                       epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
47785 +               } else if (ndx <= 13) {
47786 +                       ndx -= 6;
47787 +                       epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
47788 +               } else if (ndx <= 21) {
47789 +                       ndx -= 14;
47790 +                       epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
47791 +               } else if (ndx <= 29) {
47792 +                       ndx -= 22;
47793 +                       epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
47794 +               }
47795 +       }
47796 +       //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
47797 +       return epnum;
47798 +}
47799 +
47800 +/**
47801 + * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
47802 + * The active request is checked for the next packet to be loaded into
47803 + * the non-periodic Tx FIFO.
47804 + */
47805 +int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
47806 +{
47807 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47808 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47809 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
47810 +       gnptxsts_data_t txstatus = {.d32 = 0 };
47811 +       gintsts_data_t gintsts;
47812 +
47813 +       int epnum = 0;
47814 +       dwc_otg_pcd_ep_t *ep = 0;
47815 +       uint32_t len = 0;
47816 +       int dwords;
47817 +
47818 +       /* Get the epnum from the IN Token Learning Queue. */
47819 +       epnum = get_ep_of_last_in_token(core_if);
47820 +       ep = get_in_ep(pcd, epnum);
47821 +
47822 +       DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
47823 +
47824 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
47825 +
47826 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47827 +       if (len > ep->dwc_ep.maxpacket) {
47828 +               len = ep->dwc_ep.maxpacket;
47829 +       }
47830 +       dwords = (len + 3) / 4;
47831 +
47832 +       /* While there is space in the queue and space in the FIFO and
47833 +        * More data to tranfer, Write packets to the Tx FIFO */
47834 +       txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
47835 +       DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
47836 +
47837 +       while (txstatus.b.nptxqspcavail > 0 &&
47838 +              txstatus.b.nptxfspcavail > dwords &&
47839 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
47840 +               /* Write the FIFO */
47841 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
47842 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47843 +
47844 +               if (len > ep->dwc_ep.maxpacket) {
47845 +                       len = ep->dwc_ep.maxpacket;
47846 +               }
47847 +
47848 +               dwords = (len + 3) / 4;
47849 +               txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
47850 +               DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
47851 +       }
47852 +
47853 +       DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
47854 +                   DWC_READ_REG32(&global_regs->gnptxsts));
47855 +
47856 +       /* Clear interrupt */
47857 +       gintsts.d32 = 0;
47858 +       gintsts.b.nptxfempty = 1;
47859 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47860 +
47861 +       return 1;
47862 +}
47863 +
47864 +/**
47865 + * This function is called when dedicated Tx FIFO Empty interrupt occurs.
47866 + * The active request is checked for the next packet to be loaded into
47867 + * apropriate Tx FIFO.
47868 + */
47869 +static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
47870 +{
47871 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47872 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
47873 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
47874 +       dtxfsts_data_t txstatus = {.d32 = 0 };
47875 +       dwc_otg_pcd_ep_t *ep = 0;
47876 +       uint32_t len = 0;
47877 +       int dwords;
47878 +
47879 +       ep = get_in_ep(pcd, epnum);
47880 +
47881 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
47882 +
47883 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
47884 +
47885 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47886 +
47887 +       if (len > ep->dwc_ep.maxpacket) {
47888 +               len = ep->dwc_ep.maxpacket;
47889 +       }
47890 +
47891 +       dwords = (len + 3) / 4;
47892 +
47893 +       /* While there is space in the queue and space in the FIFO and
47894 +        * More data to tranfer, Write packets to the Tx FIFO */
47895 +       txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
47896 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
47897 +
47898 +       while (txstatus.b.txfspcavail > dwords &&
47899 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
47900 +              ep->dwc_ep.xfer_len != 0) {
47901 +               /* Write the FIFO */
47902 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
47903 +
47904 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47905 +               if (len > ep->dwc_ep.maxpacket) {
47906 +                       len = ep->dwc_ep.maxpacket;
47907 +               }
47908 +
47909 +               dwords = (len + 3) / 4;
47910 +               txstatus.d32 =
47911 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
47912 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
47913 +                           txstatus.d32);
47914 +       }
47915 +
47916 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
47917 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
47918 +
47919 +       return 1;
47920 +}
47921 +
47922 +/**
47923 + * This function is called when the Device is disconnected. It stops
47924 + * any active requests and informs the Gadget driver of the
47925 + * disconnect.
47926 + */
47927 +void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
47928 +{
47929 +       int i, num_in_eps, num_out_eps;
47930 +       dwc_otg_pcd_ep_t *ep;
47931 +
47932 +       gintmsk_data_t intr_mask = {.d32 = 0 };
47933 +
47934 +       DWC_SPINLOCK(pcd->lock);
47935 +
47936 +       num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47937 +       num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47938 +
47939 +       DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
47940 +       /* don't disconnect drivers more than once */
47941 +       if (pcd->ep0state == EP0_DISCONNECT) {
47942 +               DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
47943 +               DWC_SPINUNLOCK(pcd->lock);
47944 +               return;
47945 +       }
47946 +       pcd->ep0state = EP0_DISCONNECT;
47947 +
47948 +       /* Reset the OTG state. */
47949 +       dwc_otg_pcd_update_otg(pcd, 1);
47950 +
47951 +       /* Disable the NP Tx Fifo Empty Interrupt. */
47952 +       intr_mask.b.nptxfempty = 1;
47953 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
47954 +                        intr_mask.d32, 0);
47955 +
47956 +       /* Flush the FIFOs */
47957 +       /**@todo NGS Flush Periodic FIFOs */
47958 +       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
47959 +       dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
47960 +
47961 +       /* prevent new request submissions, kill any outstanding requests  */
47962 +       ep = &pcd->ep0;
47963 +       dwc_otg_request_nuke(ep);
47964 +       /* prevent new request submissions, kill any outstanding requests  */
47965 +       for (i = 0; i < num_in_eps; i++) {
47966 +               dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
47967 +               dwc_otg_request_nuke(ep);
47968 +       }
47969 +       /* prevent new request submissions, kill any outstanding requests  */
47970 +       for (i = 0; i < num_out_eps; i++) {
47971 +               dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
47972 +               dwc_otg_request_nuke(ep);
47973 +       }
47974 +
47975 +       /* report disconnect; the driver is already quiesced */
47976 +       if (pcd->fops->disconnect) {
47977 +               DWC_SPINUNLOCK(pcd->lock);
47978 +               pcd->fops->disconnect(pcd);
47979 +               DWC_SPINLOCK(pcd->lock);
47980 +       }
47981 +       DWC_SPINUNLOCK(pcd->lock);
47982 +}
47983 +
47984 +/**
47985 + * This interrupt indicates that ...
47986 + */
47987 +int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
47988 +{
47989 +       gintmsk_data_t intr_mask = {.d32 = 0 };
47990 +       gintsts_data_t gintsts;
47991 +
47992 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
47993 +       intr_mask.b.i2cintr = 1;
47994 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
47995 +                        intr_mask.d32, 0);
47996 +
47997 +       /* Clear interrupt */
47998 +       gintsts.d32 = 0;
47999 +       gintsts.b.i2cintr = 1;
48000 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48001 +                       gintsts.d32);
48002 +       return 1;
48003 +}
48004 +
48005 +/**
48006 + * This interrupt indicates that ...
48007 + */
48008 +int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
48009 +{
48010 +       gintsts_data_t gintsts;
48011 +#if defined(VERBOSE)
48012 +       DWC_PRINTF("Early Suspend Detected\n");
48013 +#endif
48014 +
48015 +       /* Clear interrupt */
48016 +       gintsts.d32 = 0;
48017 +       gintsts.b.erlysuspend = 1;
48018 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48019 +                       gintsts.d32);
48020 +       return 1;
48021 +}
48022 +
48023 +/**
48024 + * This function configures EPO to receive SETUP packets.
48025 + *
48026 + * @todo NGS: Update the comments from the HW FS.
48027 + *
48028 + *     -# Program the following fields in the endpoint specific registers
48029 + *     for Control OUT EP 0, in order to receive a setup packet
48030 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
48031 + *       setup packets)
48032 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
48033 + *       to back setup packets)
48034 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
48035 + *               store any setup packets received
48036 + *
48037 + * @param core_if Programming view of DWC_otg controller.
48038 + * @param pcd    Programming view of the PCD.
48039 + */
48040 +static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
48041 +                                dwc_otg_pcd_t * pcd)
48042 +{
48043 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48044 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
48045 +       dwc_otg_dev_dma_desc_t *dma_desc;
48046 +       depctl_data_t doepctl = {.d32 = 0 };
48047 +
48048 +#ifdef VERBOSE
48049 +       DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
48050 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
48051 +#endif
48052 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
48053 +               doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
48054 +               if (doepctl.b.epena) {
48055 +                       return;
48056 +               }
48057 +       }
48058 +
48059 +       doeptsize0.b.supcnt = 3;
48060 +       doeptsize0.b.pktcnt = 1;
48061 +       doeptsize0.b.xfersize = 8 * 3;
48062 +
48063 +       if (core_if->dma_enable) {
48064 +               if (!core_if->dma_desc_enable) {
48065 +                       /** put here as for Hermes mode deptisz register should not be written */
48066 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
48067 +                                       doeptsize0.d32);
48068 +
48069 +                       /** @todo dma needs to handle multiple setup packets (up to 3) */
48070 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
48071 +                                       pcd->setup_pkt_dma_handle);
48072 +               } else {
48073 +                       dev_if->setup_desc_index =
48074 +                           (dev_if->setup_desc_index + 1) & 1;
48075 +                       dma_desc =
48076 +                           dev_if->setup_desc_addr[dev_if->setup_desc_index];
48077 +
48078 +                       /** DMA Descriptor Setup */
48079 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
48080 +                       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
48081 +                               dma_desc->status.b.sr = 0;
48082 +                               dma_desc->status.b.mtrf = 0;
48083 +                       }
48084 +                       dma_desc->status.b.l = 1;
48085 +                       dma_desc->status.b.ioc = 1;
48086 +                       dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
48087 +                       dma_desc->buf = pcd->setup_pkt_dma_handle;
48088 +                       dma_desc->status.b.sts = 0;
48089 +                       dma_desc->status.b.bs = BS_HOST_READY;
48090 +
48091 +                       /** DOEPDMA0 Register write */
48092 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
48093 +                                       dev_if->dma_setup_desc_addr
48094 +                                       [dev_if->setup_desc_index]);
48095 +               }
48096 +
48097 +       } else {
48098 +               /** put here as for Hermes mode deptisz register should not be written */
48099 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
48100 +                               doeptsize0.d32);
48101 +       }
48102 +
48103 +       /** DOEPCTL0 Register write cnak will be set after setup interrupt */
48104 +       doepctl.d32 = 0;
48105 +       doepctl.b.epena = 1;
48106 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
48107 +       doepctl.b.cnak = 1;
48108 +       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
48109 +       } else {
48110 +               DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
48111 +       }
48112 +
48113 +#ifdef VERBOSE
48114 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
48115 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
48116 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
48117 +                   DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
48118 +#endif
48119 +}
48120 +
48121 +/**
48122 + * This interrupt occurs when a USB Reset is detected. When the USB
48123 + * Reset Interrupt occurs the device state is set to DEFAULT and the
48124 + * EP0 state is set to IDLE.
48125 + *     -#      Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
48126 + *     -#      Unmask the following interrupt bits
48127 + *             - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
48128 + *     - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
48129 + *     - DOEPMSK.SETUP = 1
48130 + *     - DOEPMSK.XferCompl = 1
48131 + *     - DIEPMSK.XferCompl = 1
48132 + *     - DIEPMSK.TimeOut = 1
48133 + *     -# Program the following fields in the endpoint specific registers
48134 + *     for Control OUT EP 0, in order to receive a setup packet
48135 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
48136 + *       setup packets)
48137 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
48138 + *       to back setup packets)
48139 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
48140 + *               store any setup packets received
48141 + * At this point, all the required initialization, except for enabling
48142 + * the control 0 OUT endpoint is done, for receiving SETUP packets.
48143 + */
48144 +int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
48145 +{
48146 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48147 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48148 +       depctl_data_t doepctl = {.d32 = 0 };
48149 +       depctl_data_t diepctl = {.d32 = 0 };
48150 +       daint_data_t daintmsk = {.d32 = 0 };
48151 +       doepmsk_data_t doepmsk = {.d32 = 0 };
48152 +       diepmsk_data_t diepmsk = {.d32 = 0 };
48153 +       dcfg_data_t dcfg = {.d32 = 0 };
48154 +       grstctl_t resetctl = {.d32 = 0 };
48155 +       dctl_data_t dctl = {.d32 = 0 };
48156 +       int i = 0;
48157 +       gintsts_data_t gintsts;
48158 +       pcgcctl_data_t power = {.d32 = 0 };
48159 +
48160 +       power.d32 = DWC_READ_REG32(core_if->pcgcctl);
48161 +       if (power.b.stoppclk) {
48162 +               power.d32 = 0;
48163 +               power.b.stoppclk = 1;
48164 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48165 +
48166 +               power.b.pwrclmp = 1;
48167 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48168 +
48169 +               power.b.rstpdwnmodule = 1;
48170 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48171 +       }
48172 +
48173 +       core_if->lx_state = DWC_OTG_L0;
48174 +
48175 +       DWC_PRINTF("USB RESET\n");
48176 +#ifdef DWC_EN_ISOC
48177 +       for (i = 1; i < 16; ++i) {
48178 +               dwc_otg_pcd_ep_t *ep;
48179 +               dwc_ep_t *dwc_ep;
48180 +               ep = get_in_ep(pcd, i);
48181 +               if (ep != 0) {
48182 +                       dwc_ep = &ep->dwc_ep;
48183 +                       dwc_ep->next_frame = 0xffffffff;
48184 +               }
48185 +       }
48186 +#endif /* DWC_EN_ISOC */
48187 +
48188 +       /* reset the HNP settings */
48189 +       dwc_otg_pcd_update_otg(pcd, 1);
48190 +
48191 +       /* Clear the Remote Wakeup Signalling */
48192 +       dctl.b.rmtwkupsig = 1;
48193 +       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
48194 +
48195 +       /* Set NAK for all OUT EPs */
48196 +       doepctl.b.snak = 1;
48197 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
48198 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
48199 +       }
48200 +
48201 +       /* Flush the NP Tx FIFO */
48202 +       dwc_otg_flush_tx_fifo(core_if, 0x10);
48203 +       /* Flush the Learning Queue */
48204 +       resetctl.b.intknqflsh = 1;
48205 +       DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
48206 +
48207 +       if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
48208 +               core_if->start_predict = 0;
48209 +               for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
48210 +                       core_if->nextep_seq[i] = 0xff;  // 0xff - EP not active
48211 +               }
48212 +               core_if->nextep_seq[0] = 0;     
48213 +               core_if->first_in_nextep_seq = 0;
48214 +               diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
48215 +               diepctl.b.nextep = 0;
48216 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
48217 +               
48218 +               /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
48219 +               dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48220 +               dcfg.b.epmscnt = 2;
48221 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48222 +
48223 +               DWC_DEBUGPL(DBG_PCDV,
48224 +                           "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
48225 +                       __func__, core_if->first_in_nextep_seq);
48226 +               for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
48227 +                       DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
48228 +               }
48229 +       }
48230 +
48231 +       if (core_if->multiproc_int_enable) {
48232 +               daintmsk.b.inep0 = 1;
48233 +               daintmsk.b.outep0 = 1;
48234 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk,
48235 +                               daintmsk.d32);
48236 +
48237 +               doepmsk.b.setup = 1;
48238 +               doepmsk.b.xfercompl = 1;
48239 +               doepmsk.b.ahberr = 1;
48240 +               doepmsk.b.epdisabled = 1;
48241 +
48242 +               if ((core_if->dma_desc_enable) ||
48243 +                   (core_if->dma_enable
48244 +                    && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48245 +                       doepmsk.b.stsphsercvd = 1;
48246 +               }
48247 +               if (core_if->dma_desc_enable)
48248 +                       doepmsk.b.bna = 1;
48249 +/*             
48250 +               doepmsk.b.babble = 1;
48251 +               doepmsk.b.nyet = 1;
48252 +               
48253 +               if (core_if->dma_enable) {
48254 +                       doepmsk.b.nak = 1;
48255 +               }
48256 +*/
48257 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0],
48258 +                               doepmsk.d32);
48259 +
48260 +               diepmsk.b.xfercompl = 1;
48261 +               diepmsk.b.timeout = 1;
48262 +               diepmsk.b.epdisabled = 1;
48263 +               diepmsk.b.ahberr = 1;
48264 +               diepmsk.b.intknepmis = 1; 
48265 +               if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48266 +                       diepmsk.b.intknepmis = 0; 
48267 +
48268 +/*             if (core_if->dma_desc_enable) {
48269 +                       diepmsk.b.bna = 1;
48270 +               }
48271 +*/
48272 +/*             
48273 +               if (core_if->dma_enable) {
48274 +                       diepmsk.b.nak = 1;
48275 +               }
48276 +*/
48277 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0],
48278 +                               diepmsk.d32);
48279 +       } else {
48280 +               daintmsk.b.inep0 = 1;
48281 +               daintmsk.b.outep0 = 1;
48282 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,
48283 +                               daintmsk.d32);
48284 +
48285 +               doepmsk.b.setup = 1;
48286 +               doepmsk.b.xfercompl = 1;
48287 +               doepmsk.b.ahberr = 1;
48288 +               doepmsk.b.epdisabled = 1;
48289 +
48290 +               if ((core_if->dma_desc_enable) ||
48291 +                   (core_if->dma_enable
48292 +                    && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48293 +                       doepmsk.b.stsphsercvd = 1;
48294 +               }
48295 +               if (core_if->dma_desc_enable)
48296 +                       doepmsk.b.bna = 1;
48297 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
48298 +
48299 +               diepmsk.b.xfercompl = 1;
48300 +               diepmsk.b.timeout = 1;
48301 +               diepmsk.b.epdisabled = 1;
48302 +               diepmsk.b.ahberr = 1;
48303 +               if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48304 +                       diepmsk.b.intknepmis = 0; 
48305 +/*
48306 +               if (core_if->dma_desc_enable) {
48307 +                       diepmsk.b.bna = 1;
48308 +               }
48309 +*/
48310 +
48311 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
48312 +       }
48313 +
48314 +       /* Reset Device Address */
48315 +       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48316 +       dcfg.b.devaddr = 0;
48317 +       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48318 +
48319 +       /* setup EP0 to receive SETUP packets */
48320 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a)
48321 +               ep0_out_start(core_if, pcd);
48322 +
48323 +       /* Clear interrupt */
48324 +       gintsts.d32 = 0;
48325 +       gintsts.b.usbreset = 1;
48326 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48327 +
48328 +       return 1;
48329 +}
48330 +
48331 +/**
48332 + * Get the device speed from the device status register and convert it
48333 + * to USB speed constant.
48334 + *
48335 + * @param core_if Programming view of DWC_otg controller.
48336 + */
48337 +static int get_device_speed(dwc_otg_core_if_t * core_if)
48338 +{
48339 +       dsts_data_t dsts;
48340 +       int speed = 0;
48341 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
48342 +
48343 +       switch (dsts.b.enumspd) {
48344 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
48345 +               speed = USB_SPEED_HIGH;
48346 +               break;
48347 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
48348 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
48349 +               speed = USB_SPEED_FULL;
48350 +               break;
48351 +
48352 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
48353 +               speed = USB_SPEED_LOW;
48354 +               break;
48355 +       }
48356 +
48357 +       return speed;
48358 +}
48359 +
48360 +/**
48361 + * Read the device status register and set the device speed in the
48362 + * data structure.
48363 + * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
48364 + */
48365 +int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
48366 +{
48367 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48368 +       gintsts_data_t gintsts;
48369 +       gusbcfg_data_t gusbcfg;
48370 +       dwc_otg_core_global_regs_t *global_regs =
48371 +           GET_CORE_IF(pcd)->core_global_regs;
48372 +       uint8_t utmi16b, utmi8b;
48373 +       int speed;
48374 +       DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
48375 +
48376 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
48377 +               utmi16b = 6;    //vahrama old value was 6;
48378 +               utmi8b = 9;
48379 +       } else {
48380 +               utmi16b = 4;
48381 +               utmi8b = 8;
48382 +       }
48383 +       dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
48384 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) {
48385 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
48386 +       }
48387 +
48388 +#ifdef DEBUG_EP0
48389 +       print_ep0_state(pcd);
48390 +#endif
48391 +
48392 +       if (pcd->ep0state == EP0_DISCONNECT) {
48393 +               pcd->ep0state = EP0_IDLE;
48394 +       } else if (pcd->ep0state == EP0_STALL) {
48395 +               pcd->ep0state = EP0_IDLE;
48396 +       }
48397 +
48398 +       pcd->ep0state = EP0_IDLE;
48399 +
48400 +       ep0->stopped = 0;
48401 +
48402 +       speed = get_device_speed(GET_CORE_IF(pcd));
48403 +       pcd->fops->connect(pcd, speed);
48404 +
48405 +       /* Set USB turnaround time based on device speed and PHY interface. */
48406 +       gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
48407 +       if (speed == USB_SPEED_HIGH) {
48408 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48409 +                   DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
48410 +                       /* ULPI interface */
48411 +                       gusbcfg.b.usbtrdtim = 9;
48412 +               }
48413 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48414 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
48415 +                       /* UTMI+ interface */
48416 +                       if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
48417 +                               gusbcfg.b.usbtrdtim = utmi8b;
48418 +                       } else if (GET_CORE_IF(pcd)->hwcfg4.
48419 +                                  b.utmi_phy_data_width == 1) {
48420 +                               gusbcfg.b.usbtrdtim = utmi16b;
48421 +                       } else if (GET_CORE_IF(pcd)->
48422 +                                  core_params->phy_utmi_width == 8) {
48423 +                               gusbcfg.b.usbtrdtim = utmi8b;
48424 +                       } else {
48425 +                               gusbcfg.b.usbtrdtim = utmi16b;
48426 +                       }
48427 +               }
48428 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48429 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
48430 +                       /* UTMI+  OR  ULPI interface */
48431 +                       if (gusbcfg.b.ulpi_utmi_sel == 1) {
48432 +                               /* ULPI interface */
48433 +                               gusbcfg.b.usbtrdtim = 9;
48434 +                       } else {
48435 +                               /* UTMI+ interface */
48436 +                               if (GET_CORE_IF(pcd)->
48437 +                                   core_params->phy_utmi_width == 16) {
48438 +                                       gusbcfg.b.usbtrdtim = utmi16b;
48439 +                               } else {
48440 +                                       gusbcfg.b.usbtrdtim = utmi8b;
48441 +                               }
48442 +                       }
48443 +               }
48444 +       } else {
48445 +               /* Full or low speed */
48446 +               gusbcfg.b.usbtrdtim = 9;
48447 +       }
48448 +       DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
48449 +
48450 +       /* Clear interrupt */
48451 +       gintsts.d32 = 0;
48452 +       gintsts.b.enumdone = 1;
48453 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48454 +                       gintsts.d32);
48455 +       return 1;
48456 +}
48457 +
48458 +/**
48459 + * This interrupt indicates that the ISO OUT Packet was dropped due to
48460 + * Rx FIFO full or Rx Status Queue Full.  If this interrupt occurs
48461 + * read all the data from the Rx FIFO.
48462 + */
48463 +int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
48464 +{
48465 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48466 +       gintsts_data_t gintsts;
48467 +
48468 +       DWC_WARN("INTERRUPT Handler not implemented for %s\n",
48469 +                "ISOC Out Dropped");
48470 +
48471 +       intr_mask.b.isooutdrop = 1;
48472 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48473 +                        intr_mask.d32, 0);
48474 +
48475 +       /* Clear interrupt */
48476 +       gintsts.d32 = 0;
48477 +       gintsts.b.isooutdrop = 1;
48478 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48479 +                       gintsts.d32);
48480 +
48481 +       return 1;
48482 +}
48483 +
48484 +/**
48485 + * This interrupt indicates the end of the portion of the micro-frame
48486 + * for periodic transactions.  If there is a periodic transaction for
48487 + * the next frame, load the packets into the EP periodic Tx FIFO.
48488 + */
48489 +int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
48490 +{
48491 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48492 +       gintsts_data_t gintsts;
48493 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
48494 +
48495 +       intr_mask.b.eopframe = 1;
48496 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48497 +                        intr_mask.d32, 0);
48498 +
48499 +       /* Clear interrupt */
48500 +       gintsts.d32 = 0;
48501 +       gintsts.b.eopframe = 1;
48502 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48503 +                       gintsts.d32);
48504 +
48505 +       return 1;
48506 +}
48507 +
48508 +/**
48509 + * This interrupt indicates that EP of the packet on the top of the
48510 + * non-periodic Tx FIFO does not match EP of the IN Token received.
48511 + *
48512 + * The "Device IN Token Queue" Registers are read to determine the
48513 + * order the IN Tokens have been received. The non-periodic Tx FIFO
48514 + * is flushed, so it can be reloaded in the order seen in the IN Token
48515 + * Queue.
48516 + */
48517 +int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd)
48518 +{
48519 +       gintsts_data_t gintsts;
48520 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48521 +       dctl_data_t dctl;
48522 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48523 +
48524 +       if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) {
48525 +               core_if->start_predict = 1;
48526 +       
48527 +               DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48528 +       
48529 +               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
48530 +               if (!gintsts.b.ginnakeff) {
48531 +                       /* Disable EP Mismatch interrupt */
48532 +                       intr_mask.d32 = 0;
48533 +                       intr_mask.b.epmismatch = 1;
48534 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
48535 +                       /* Enable the Global IN NAK Effective Interrupt */
48536 +                       intr_mask.d32 = 0;
48537 +                       intr_mask.b.ginnakeff = 1;
48538 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
48539 +                       /* Set the global non-periodic IN NAK handshake */
48540 +                       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48541 +                       dctl.b.sgnpinnak = 1;
48542 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48543 +               } else {
48544 +                       DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");
48545 +               }
48546 +               /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()
48547 +                * handler after Global IN NAK Effective interrupt will be asserted */
48548 +       }
48549 +       /* Clear interrupt */
48550 +       gintsts.d32 = 0;
48551 +       gintsts.b.epmismatch = 1;
48552 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48553 +
48554 +       return 1;
48555 +}
48556 +
48557 +/**
48558 + * This interrupt is valid only in DMA mode. This interrupt indicates that the
48559 + * core has stopped fetching data for IN endpoints due to the unavailability of
48560 + * TxFIFO space or Request Queue space. This interrupt is used by the
48561 + * application for an endpoint mismatch algorithm.
48562 + * 
48563 + * @param pcd The PCD 
48564 + */
48565 +int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd)
48566 +{
48567 +       gintsts_data_t gintsts;
48568 +       gintmsk_data_t gintmsk_data;
48569 +       dctl_data_t dctl;
48570 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48571 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48572 +       
48573 +       /* Clear the global non-periodic IN NAK handshake */
48574 +       dctl.d32 = 0;
48575 +       dctl.b.cgnpinnak = 1;
48576 +       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); 
48577 +       
48578 +       /* Mask GINTSTS.FETSUSP interrupt */
48579 +       gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
48580 +       gintmsk_data.b.fetsusp = 0;
48581 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32);
48582 +
48583 +       /* Clear interrupt */
48584 +       gintsts.d32 = 0;
48585 +       gintsts.b.fetsusp = 1;
48586 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48587 +
48588 +       return 1;
48589 +}
48590 +/**
48591 + * This funcion stalls EP0.
48592 + */
48593 +static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
48594 +{
48595 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48596 +       usb_device_request_t *ctrl = &pcd->setup_pkt->req;
48597 +       DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
48598 +                ctrl->bmRequestType, ctrl->bRequest, err_val);
48599 +
48600 +       ep0->dwc_ep.is_in = 1;
48601 +       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
48602 +       pcd->ep0.stopped = 1;
48603 +       pcd->ep0state = EP0_IDLE;
48604 +       ep0_out_start(GET_CORE_IF(pcd), pcd);
48605 +}
48606 +
48607 +/**
48608 + * This functions delegates the setup command to the gadget driver.
48609 + */
48610 +static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
48611 +                                  usb_device_request_t * ctrl)
48612 +{
48613 +       int ret = 0;
48614 +       DWC_SPINUNLOCK(pcd->lock);
48615 +       ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
48616 +       DWC_SPINLOCK(pcd->lock);
48617 +       if (ret < 0) {
48618 +               ep0_do_stall(pcd, ret);
48619 +       }
48620 +
48621 +       /** @todo This is a g_file_storage gadget driver specific
48622 +        * workaround: a DELAYED_STATUS result from the fsg_setup
48623 +        * routine will result in the gadget queueing a EP0 IN status
48624 +        * phase for a two-stage control transfer. Exactly the same as
48625 +        * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
48626 +        * specific request.  Need a generic way to know when the gadget
48627 +        * driver will queue the status phase. Can we assume when we
48628 +        * call the gadget driver setup() function that it will always
48629 +        * queue and require the following flag? Need to look into
48630 +        * this.
48631 +        */
48632 +
48633 +       if (ret == 256 + 999) {
48634 +               pcd->request_config = 1;
48635 +       }
48636 +}
48637 +
48638 +#ifdef DWC_UTE_CFI
48639 +/**
48640 + * This functions delegates the CFI setup commands to the gadget driver.
48641 + * This function will return a negative value to indicate a failure.
48642 + */
48643 +static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
48644 +                                  struct cfi_usb_ctrlrequest *ctrl_req)
48645 +{
48646 +       int ret = 0;
48647 +
48648 +       if (pcd->fops && pcd->fops->cfi_setup) {
48649 +               DWC_SPINUNLOCK(pcd->lock);
48650 +               ret = pcd->fops->cfi_setup(pcd, ctrl_req);
48651 +               DWC_SPINLOCK(pcd->lock);
48652 +               if (ret < 0) {
48653 +                       ep0_do_stall(pcd, ret);
48654 +                       return ret;
48655 +               }
48656 +       }
48657 +
48658 +       return ret;
48659 +}
48660 +#endif
48661 +
48662 +/**
48663 + * This function starts the Zero-Length Packet for the IN status phase
48664 + * of a 2 stage control transfer.
48665 + */
48666 +static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
48667 +{
48668 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48669 +       if (pcd->ep0state == EP0_STALL) {
48670 +               return;
48671 +       }
48672 +
48673 +       pcd->ep0state = EP0_IN_STATUS_PHASE;
48674 +
48675 +       /* Prepare for more SETUP Packets */
48676 +       DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
48677 +       if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a)
48678 +           && (pcd->core_if->dma_desc_enable)
48679 +           && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) {
48680 +               DWC_DEBUGPL(DBG_PCDV,
48681 +                           "Data terminated wait next packet in out_desc_addr\n");
48682 +               pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr);
48683 +               pcd->data_terminated = 1;
48684 +       }
48685 +       ep0->dwc_ep.xfer_len = 0;
48686 +       ep0->dwc_ep.xfer_count = 0;
48687 +       ep0->dwc_ep.is_in = 1;
48688 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48689 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48690 +
48691 +       /* Prepare for more SETUP Packets */
48692 +       //ep0_out_start(GET_CORE_IF(pcd), pcd);
48693 +}
48694 +
48695 +/**
48696 + * This function starts the Zero-Length Packet for the OUT status phase
48697 + * of a 2 stage control transfer.
48698 + */
48699 +static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
48700 +{
48701 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48702 +       if (pcd->ep0state == EP0_STALL) {
48703 +               DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
48704 +               return;
48705 +       }
48706 +       pcd->ep0state = EP0_OUT_STATUS_PHASE;
48707 +
48708 +       DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
48709 +       ep0->dwc_ep.xfer_len = 0;
48710 +       ep0->dwc_ep.xfer_count = 0;
48711 +       ep0->dwc_ep.is_in = 0;
48712 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48713 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48714 +
48715 +       /* Prepare for more SETUP Packets */
48716 +       if (GET_CORE_IF(pcd)->dma_enable == 0) {
48717 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
48718 +       }
48719 +}
48720 +
48721 +/**
48722 + * Clear the EP halt (STALL) and if pending requests start the
48723 + * transfer.
48724 + */
48725 +static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
48726 +{
48727 +       if (ep->dwc_ep.stall_clear_flag == 0)
48728 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
48729 +
48730 +       /* Reactive the EP */
48731 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
48732 +       if (ep->stopped) {
48733 +               ep->stopped = 0;
48734 +               /* If there is a request in the EP queue start it */
48735 +
48736 +               /** @todo FIXME: this causes an EP mismatch in DMA mode.
48737 +                * epmismatch not yet implemented. */
48738 +
48739 +               /*
48740 +                * Above fixme is solved by implmenting a tasklet to call the
48741 +                * start_next_request(), outside of interrupt context at some
48742 +                * time after the current time, after a clear-halt setup packet.
48743 +                * Still need to implement ep mismatch in the future if a gadget
48744 +                * ever uses more than one endpoint at once
48745 +                */
48746 +               ep->queue_sof = 1;
48747 +               DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
48748 +       }
48749 +       /* Start Control Status Phase */
48750 +       do_setup_in_status_phase(pcd);
48751 +}
48752 +
48753 +/**
48754 + * This function is called when the SET_FEATURE TEST_MODE Setup packet
48755 + * is sent from the host.  The Device Control register is written with
48756 + * the Test Mode bits set to the specified Test Mode.  This is done as
48757 + * a tasklet so that the "Status" phase of the control transfer
48758 + * completes before transmitting the TEST packets.
48759 + *
48760 + * @todo This has not been tested since the tasklet struct was put
48761 + * into the PCD struct!
48762 + *
48763 + */
48764 +void do_test_mode(void *data)
48765 +{
48766 +       dctl_data_t dctl;
48767 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
48768 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48769 +       int test_mode = pcd->test_mode;
48770 +
48771 +//        DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
48772 +
48773 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48774 +       switch (test_mode) {
48775 +       case 1:         // TEST_J
48776 +               dctl.b.tstctl = 1;
48777 +               break;
48778 +
48779 +       case 2:         // TEST_K
48780 +               dctl.b.tstctl = 2;
48781 +               break;
48782 +
48783 +       case 3:         // TEST_SE0_NAK
48784 +               dctl.b.tstctl = 3;
48785 +               break;
48786 +
48787 +       case 4:         // TEST_PACKET
48788 +               dctl.b.tstctl = 4;
48789 +               break;
48790 +
48791 +       case 5:         // TEST_FORCE_ENABLE
48792 +               dctl.b.tstctl = 5;
48793 +               break;
48794 +       }
48795 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48796 +}
48797 +
48798 +/**
48799 + * This function process the GET_STATUS Setup Commands.
48800 + */
48801 +static inline void do_get_status(dwc_otg_pcd_t * pcd)
48802 +{
48803 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48804 +       dwc_otg_pcd_ep_t *ep;
48805 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48806 +       uint16_t *status = pcd->status_buf;
48807 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48808 +
48809 +#ifdef DEBUG_EP0
48810 +       DWC_DEBUGPL(DBG_PCD,
48811 +                   "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
48812 +                   ctrl.bmRequestType, ctrl.bRequest,
48813 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48814 +                   UGETW(ctrl.wLength));
48815 +#endif
48816 +
48817 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48818 +       case UT_DEVICE:
48819 +               if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */
48820 +                       DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));
48821 +                       DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);
48822 +                       DWC_PRINTF("OTG CAP - %d, %d\n",
48823 +                                  core_if->core_params->otg_cap,
48824 +                                               DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
48825 +                       if (core_if->otg_ver == 1
48826 +                           && core_if->core_params->otg_cap ==
48827 +                           DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48828 +                               uint8_t *otgsts = (uint8_t*)pcd->status_buf;
48829 +                               *otgsts = (core_if->otg_sts & 0x1);
48830 +                               pcd->ep0_pending = 1;
48831 +                               ep0->dwc_ep.start_xfer_buff =
48832 +                                   (uint8_t *) otgsts;
48833 +                               ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts;
48834 +                               ep0->dwc_ep.dma_addr =
48835 +                                   pcd->status_buf_dma_handle;
48836 +                               ep0->dwc_ep.xfer_len = 1;
48837 +                               ep0->dwc_ep.xfer_count = 0;
48838 +                               ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
48839 +                               dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
48840 +                                                          &ep0->dwc_ep);
48841 +                               return;
48842 +                       } else {
48843 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48844 +                               return;
48845 +                       }
48846 +                       break;
48847 +               } else {
48848 +                       *status = 0x1;  /* Self powered */
48849 +                       *status |= pcd->remote_wakeup_enable << 1;
48850 +                       break;
48851 +               }
48852 +       case UT_INTERFACE:
48853 +               *status = 0;
48854 +               break;
48855 +
48856 +       case UT_ENDPOINT:
48857 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48858 +               if (ep == 0 || UGETW(ctrl.wLength) > 2) {
48859 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48860 +                       return;
48861 +               }
48862 +               /** @todo check for EP stall */
48863 +               *status = ep->stopped;
48864 +               break;
48865 +       }
48866 +       pcd->ep0_pending = 1;
48867 +       ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
48868 +       ep0->dwc_ep.xfer_buff = (uint8_t *) status;
48869 +       ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
48870 +       ep0->dwc_ep.xfer_len = 2;
48871 +       ep0->dwc_ep.xfer_count = 0;
48872 +       ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
48873 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48874 +}
48875 +
48876 +/**
48877 + * This function process the SET_FEATURE Setup Commands.
48878 + */
48879 +static inline void do_set_feature(dwc_otg_pcd_t * pcd)
48880 +{
48881 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48882 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
48883 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48884 +       dwc_otg_pcd_ep_t *ep = 0;
48885 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
48886 +       gotgctl_data_t gotgctl = {.d32 = 0 };
48887 +
48888 +       DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
48889 +                   ctrl.bmRequestType, ctrl.bRequest,
48890 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48891 +                   UGETW(ctrl.wLength));
48892 +       DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
48893 +
48894 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48895 +       case UT_DEVICE:
48896 +               switch (UGETW(ctrl.wValue)) {
48897 +               case UF_DEVICE_REMOTE_WAKEUP:
48898 +                       pcd->remote_wakeup_enable = 1;
48899 +                       break;
48900 +
48901 +               case UF_TEST_MODE:
48902 +                       /* Setup the Test Mode tasklet to do the Test
48903 +                        * Packet generation after the SETUP Status
48904 +                        * phase has completed. */
48905 +
48906 +                       /** @todo This has not been tested since the
48907 +                        * tasklet struct was put into the PCD
48908 +                        * struct! */
48909 +                       pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
48910 +                       DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
48911 +                       break;
48912 +
48913 +               case UF_DEVICE_B_HNP_ENABLE:
48914 +                       DWC_DEBUGPL(DBG_PCDV,
48915 +                                   "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
48916 +
48917 +                       /* dev may initiate HNP */
48918 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48919 +                               pcd->b_hnp_enable = 1;
48920 +                               dwc_otg_pcd_update_otg(pcd, 0);
48921 +                               DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
48922 +                               /**@todo Is the gotgctl.devhnpen cleared
48923 +                                * by a USB Reset? */
48924 +                               gotgctl.b.devhnpen = 1;
48925 +                               gotgctl.b.hnpreq = 1;
48926 +                               DWC_WRITE_REG32(&global_regs->gotgctl,
48927 +                                               gotgctl.d32);
48928 +                       } else {
48929 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48930 +                               return;
48931 +                       }
48932 +                       break;
48933 +
48934 +               case UF_DEVICE_A_HNP_SUPPORT:
48935 +                       /* RH port supports HNP */
48936 +                       DWC_DEBUGPL(DBG_PCDV,
48937 +                                   "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
48938 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48939 +                               pcd->a_hnp_support = 1;
48940 +                               dwc_otg_pcd_update_otg(pcd, 0);
48941 +                       } else {
48942 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48943 +                               return;
48944 +                       }
48945 +                       break;
48946 +
48947 +               case UF_DEVICE_A_ALT_HNP_SUPPORT:
48948 +                       /* other RH port does */
48949 +                       DWC_DEBUGPL(DBG_PCDV,
48950 +                                   "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
48951 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48952 +                               pcd->a_alt_hnp_support = 1;
48953 +                               dwc_otg_pcd_update_otg(pcd, 0);
48954 +                       } else {
48955 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48956 +                               return;
48957 +                       }
48958 +                       break;
48959 +
48960 +               default:
48961 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48962 +                       return;
48963 +
48964 +               }
48965 +               do_setup_in_status_phase(pcd);
48966 +               break;
48967 +
48968 +       case UT_INTERFACE:
48969 +               do_gadget_setup(pcd, &ctrl);
48970 +               break;
48971 +
48972 +       case UT_ENDPOINT:
48973 +               if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
48974 +                       ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48975 +                       if (ep == 0) {
48976 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48977 +                               return;
48978 +                       }
48979 +                       ep->stopped = 1;
48980 +                       dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
48981 +               }
48982 +               do_setup_in_status_phase(pcd);
48983 +               break;
48984 +       }
48985 +}
48986 +
48987 +/**
48988 + * This function process the CLEAR_FEATURE Setup Commands.
48989 + */
48990 +static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
48991 +{
48992 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48993 +       dwc_otg_pcd_ep_t *ep = 0;
48994 +
48995 +       DWC_DEBUGPL(DBG_PCD,
48996 +                   "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
48997 +                   ctrl.bmRequestType, ctrl.bRequest,
48998 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48999 +                   UGETW(ctrl.wLength));
49000 +
49001 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
49002 +       case UT_DEVICE:
49003 +               switch (UGETW(ctrl.wValue)) {
49004 +               case UF_DEVICE_REMOTE_WAKEUP:
49005 +                       pcd->remote_wakeup_enable = 0;
49006 +                       break;
49007 +
49008 +               case UF_TEST_MODE:
49009 +                       /** @todo Add CLEAR_FEATURE for TEST modes. */
49010 +                       break;
49011 +
49012 +               default:
49013 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49014 +                       return;
49015 +               }
49016 +               do_setup_in_status_phase(pcd);
49017 +               break;
49018 +
49019 +       case UT_ENDPOINT:
49020 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
49021 +               if (ep == 0) {
49022 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49023 +                       return;
49024 +               }
49025 +
49026 +               pcd_clear_halt(pcd, ep);
49027 +
49028 +               break;
49029 +       }
49030 +}
49031 +
49032 +/**
49033 + * This function process the SET_ADDRESS Setup Commands.
49034 + */
49035 +static inline void do_set_address(dwc_otg_pcd_t * pcd)
49036 +{
49037 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
49038 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
49039 +
49040 +       if (ctrl.bmRequestType == UT_DEVICE) {
49041 +               dcfg_data_t dcfg = {.d32 = 0 };
49042 +
49043 +#ifdef DEBUG_EP0
49044 +//                      DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
49045 +#endif
49046 +               dcfg.b.devaddr = UGETW(ctrl.wValue);
49047 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
49048 +               do_setup_in_status_phase(pcd);
49049 +       }
49050 +}
49051 +
49052 +/**
49053 + *     This function processes SETUP commands. In Linux, the USB Command
49054 + *     processing is done in two places - the first being the PCD and the
49055 + *     second in the Gadget Driver (for example, the File-Backed Storage
49056 + *     Gadget Driver).
49057 + *
49058 + * <table>
49059 + * <tr><td>Command     </td><td>Driver </td><td>Description</td></tr>
49060 + *
49061 + * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
49062 + * defined in chapter 9 of the USB 2.0 Specification chapter 9
49063 + * </td></tr>
49064 + *
49065 + * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
49066 + * requests are the ENDPOINT_HALT feature is procesed, all others the
49067 + * interface requests are ignored.</td></tr>
49068 + *
49069 + * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
49070 + * requests are processed by the PCD.  Interface requests are passed
49071 + * to the Gadget Driver.</td></tr>
49072 + *
49073 + * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
49074 + * with device address received </td></tr>
49075 + *
49076 + * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
49077 + * requested descriptor</td></tr>
49078 + *
49079 + * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
49080 + * not implemented by any of the existing Gadget Drivers.</td></tr>
49081 + *
49082 + * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
49083 + * all EPs and enable EPs for new configuration.</td></tr>
49084 + *
49085 + * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
49086 + * the current configuration</td></tr>
49087 + *
49088 + * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
49089 + * EPs and enable EPs for new configuration.</td></tr>
49090 + *
49091 + * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
49092 + * current interface.</td></tr>
49093 + *
49094 + * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
49095 + * message.</td></tr>
49096 + * </table>
49097 + *
49098 + * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
49099 + * processed by pcd_setup. Calling the Function Driver's setup function from
49100 + * pcd_setup processes the gadget SETUP commands.
49101 + */
49102 +static inline void pcd_setup(dwc_otg_pcd_t * pcd)
49103 +{
49104 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
49105 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49106 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
49107 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
49108 +
49109 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
49110 +
49111 +#ifdef DWC_UTE_CFI
49112 +       int retval = 0;
49113 +       struct cfi_usb_ctrlrequest cfi_req;
49114 +#endif
49115 +
49116 +       doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz);
49117 +
49118 +       /** In BDMA more then 1 setup packet is not supported till 3.00a */
49119 +       if (core_if->dma_enable && core_if->dma_desc_enable == 0
49120 +           && (doeptsize0.b.supcnt < 2)
49121 +           && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
49122 +               DWC_ERROR
49123 +                   ("\n\n-----------    CANNOT handle > 1 setup packet in DMA mode\n\n");
49124 +       }
49125 +       if ((core_if->snpsid >= OTG_CORE_REV_3_00a)
49126 +           && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) {
49127 +               ctrl =
49128 +                   (pcd->setup_pkt +
49129 +                    (3 - doeptsize0.b.supcnt - 1 +
49130 +                     ep0->dwc_ep.stp_rollover))->req;
49131 +       }
49132 +#ifdef DEBUG_EP0
49133 +       DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
49134 +                   ctrl.bmRequestType, ctrl.bRequest,
49135 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
49136 +                   UGETW(ctrl.wLength));
49137 +#endif
49138 +
49139 +       /* Clean up the request queue */
49140 +       dwc_otg_request_nuke(ep0);
49141 +       ep0->stopped = 0;
49142 +
49143 +       if (ctrl.bmRequestType & UE_DIR_IN) {
49144 +               ep0->dwc_ep.is_in = 1;
49145 +               pcd->ep0state = EP0_IN_DATA_PHASE;
49146 +       } else {
49147 +               ep0->dwc_ep.is_in = 0;
49148 +               pcd->ep0state = EP0_OUT_DATA_PHASE;
49149 +       }
49150 +
49151 +       if (UGETW(ctrl.wLength) == 0) {
49152 +               ep0->dwc_ep.is_in = 1;
49153 +               pcd->ep0state = EP0_IN_STATUS_PHASE;
49154 +       }
49155 +
49156 +       if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
49157 +
49158 +#ifdef DWC_UTE_CFI
49159 +               DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
49160 +
49161 +               //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", 
49162 +                               ctrl.bRequestType, ctrl.bRequest);
49163 +               if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
49164 +                       if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
49165 +                               retval = cfi_setup(pcd, &cfi_req);
49166 +                               if (retval < 0) {
49167 +                                       ep0_do_stall(pcd, retval);
49168 +                                       pcd->ep0_pending = 0;
49169 +                                       return;
49170 +                               }
49171 +
49172 +                               /* if need gadget setup then call it and check the retval */
49173 +                               if (pcd->cfi->need_gadget_att) {
49174 +                                       retval =
49175 +                                           cfi_gadget_setup(pcd,
49176 +                                                            &pcd->
49177 +                                                            cfi->ctrl_req);
49178 +                                       if (retval < 0) {
49179 +                                               pcd->ep0_pending = 0;
49180 +                                               return;
49181 +                                       }
49182 +                               }
49183 +
49184 +                               if (pcd->cfi->need_status_in_complete) {
49185 +                                       do_setup_in_status_phase(pcd);
49186 +                               }
49187 +                               return;
49188 +                       }
49189 +               }
49190 +#endif
49191 +
49192 +               /* handle non-standard (class/vendor) requests in the gadget driver */
49193 +               do_gadget_setup(pcd, &ctrl);
49194 +               return;
49195 +       }
49196 +
49197 +       /** @todo NGS: Handle bad setup packet? */
49198 +
49199 +///////////////////////////////////////////
49200 +//// --- Standard Request handling --- ////
49201 +
49202 +       switch (ctrl.bRequest) {
49203 +       case UR_GET_STATUS:
49204 +               do_get_status(pcd);
49205 +               break;
49206 +
49207 +       case UR_CLEAR_FEATURE:
49208 +               do_clear_feature(pcd);
49209 +               break;
49210 +
49211 +       case UR_SET_FEATURE:
49212 +               do_set_feature(pcd);
49213 +               break;
49214 +
49215 +       case UR_SET_ADDRESS:
49216 +               do_set_address(pcd);
49217 +               break;
49218 +
49219 +       case UR_SET_INTERFACE:
49220 +       case UR_SET_CONFIG:
49221 +//              _pcd->request_config = 1;       /* Configuration changed */
49222 +               do_gadget_setup(pcd, &ctrl);
49223 +               break;
49224 +
49225 +       case UR_SYNCH_FRAME:
49226 +               do_gadget_setup(pcd, &ctrl);
49227 +               break;
49228 +
49229 +       default:
49230 +               /* Call the Gadget Driver's setup functions */
49231 +               do_gadget_setup(pcd, &ctrl);
49232 +               break;
49233 +       }
49234 +}
49235 +
49236 +/**
49237 + * This function completes the ep0 control transfer.
49238 + */
49239 +static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
49240 +{
49241 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49242 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49243 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49244 +           dev_if->in_ep_regs[ep->dwc_ep.num];
49245 +#ifdef DEBUG_EP0
49246 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49247 +           dev_if->out_ep_regs[ep->dwc_ep.num];
49248 +#endif
49249 +       deptsiz0_data_t deptsiz;
49250 +       dev_dma_desc_sts_t desc_sts;
49251 +       dwc_otg_pcd_request_t *req;
49252 +       int is_last = 0;
49253 +       dwc_otg_pcd_t *pcd = ep->pcd;
49254 +
49255 +#ifdef DWC_UTE_CFI
49256 +       struct cfi_usb_ctrlrequest *ctrlreq;
49257 +       int retval = -DWC_E_NOT_SUPPORTED;
49258 +#endif
49259 +
49260 +        desc_sts.b.bytes = 0;
49261 +        
49262 +       if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49263 +               if (ep->dwc_ep.is_in) {
49264 +#ifdef DEBUG_EP0
49265 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
49266 +#endif
49267 +                       do_setup_out_status_phase(pcd);
49268 +               } else {
49269 +#ifdef DEBUG_EP0
49270 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
49271 +#endif
49272 +
49273 +#ifdef DWC_UTE_CFI
49274 +                       ctrlreq = &pcd->cfi->ctrl_req;
49275 +
49276 +                       if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
49277 +                               if (ctrlreq->bRequest > 0xB0
49278 +                                   && ctrlreq->bRequest < 0xBF) {
49279 +
49280 +                                       /* Return if the PCD failed to handle the request */
49281 +                                       if ((retval =
49282 +                                            pcd->cfi->ops.
49283 +                                            ctrl_write_complete(pcd->cfi,
49284 +                                                                pcd)) < 0) {
49285 +                                               CFI_INFO
49286 +                                                   ("ERROR setting a new value in the PCD(%d)\n",
49287 +                                                    retval);
49288 +                                               ep0_do_stall(pcd, retval);
49289 +                                               pcd->ep0_pending = 0;
49290 +                                               return 0;
49291 +                                       }
49292 +
49293 +                                       /* If the gadget needs to be notified on the request */
49294 +                                       if (pcd->cfi->need_gadget_att == 1) {
49295 +                                               //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
49296 +                                               retval =
49297 +                                                   cfi_gadget_setup(pcd,
49298 +                                                                    &pcd->cfi->
49299 +                                                                    ctrl_req);
49300 +
49301 +                                               /* Return from the function if the gadget failed to process
49302 +                                                * the request properly - this should never happen !!!
49303 +                                                */
49304 +                                               if (retval < 0) {
49305 +                                                       CFI_INFO
49306 +                                                           ("ERROR setting a new value in the gadget(%d)\n",
49307 +                                                            retval);
49308 +                                                       pcd->ep0_pending = 0;
49309 +                                                       return 0;
49310 +                                               }
49311 +                                       }
49312 +
49313 +                                       CFI_INFO("%s: RETVAL=%d\n", __func__,
49314 +                                                retval);
49315 +                                       /* If we hit here then the PCD and the gadget has properly
49316 +                                        * handled the request - so send the ZLP IN to the host.
49317 +                                        */
49318 +                                       /* @todo: MAS - decide whether we need to start the setup
49319 +                                        * stage based on the need_setup value of the cfi object
49320 +                                        */
49321 +                                       do_setup_in_status_phase(pcd);
49322 +                                       pcd->ep0_pending = 0;
49323 +                                       return 1;
49324 +                               }
49325 +                       }
49326 +#endif
49327 +
49328 +                       do_setup_in_status_phase(pcd);
49329 +               }
49330 +               pcd->ep0_pending = 0;
49331 +               return 1;
49332 +       }
49333 +
49334 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49335 +               return 0;
49336 +       }
49337 +       req = DWC_CIRCLEQ_FIRST(&ep->queue);
49338 +
49339 +       if (pcd->ep0state == EP0_OUT_STATUS_PHASE
49340 +           || pcd->ep0state == EP0_IN_STATUS_PHASE) {
49341 +               is_last = 1;
49342 +       } else if (ep->dwc_ep.is_in) {
49343 +               deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49344 +               if (core_if->dma_desc_enable != 0)
49345 +                       desc_sts = dev_if->in_desc_addr->status;
49346 +#ifdef DEBUG_EP0
49347 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d  xfersize=%d pktcnt=%d\n",
49348 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49349 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49350 +#endif
49351 +
49352 +               if (((core_if->dma_desc_enable == 0)
49353 +                    && (deptsiz.b.xfersize == 0))
49354 +                   || ((core_if->dma_desc_enable != 0)
49355 +                       && (desc_sts.b.bytes == 0))) {
49356 +                       req->actual = ep->dwc_ep.xfer_count;
49357 +                       /* Is a Zero Len Packet needed? */
49358 +                       if (req->sent_zlp) {
49359 +#ifdef DEBUG_EP0
49360 +                               DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
49361 +#endif
49362 +                               req->sent_zlp = 0;
49363 +                       }
49364 +                       do_setup_out_status_phase(pcd);
49365 +               }
49366 +       } else {
49367 +               /* ep0-OUT */
49368 +#ifdef DEBUG_EP0
49369 +               deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
49370 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
49371 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49372 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49373 +#endif
49374 +               req->actual = ep->dwc_ep.xfer_count;
49375 +
49376 +               /* Is a Zero Len Packet needed? */
49377 +               if (req->sent_zlp) {
49378 +#ifdef DEBUG_EP0
49379 +                       DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
49380 +#endif
49381 +                       req->sent_zlp = 0;
49382 +               }
49383 +               /* For older cores do setup in status phase in Slave/BDMA modes,
49384 +                * starting from 3.00 do that only in slave, and for DMA modes
49385 +                * just re-enable ep 0 OUT here*/
49386 +               if (core_if->dma_enable == 0
49387 +                   || (core_if->dma_desc_enable == 0
49388 +                       && core_if->snpsid <= OTG_CORE_REV_2_94a)) {
49389 +                       do_setup_in_status_phase(pcd);
49390 +               } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
49391 +                       DWC_DEBUGPL(DBG_PCDV,
49392 +                                   "Enable out ep before in status phase\n");
49393 +                       ep0_out_start(core_if, pcd);
49394 +               }
49395 +       }
49396 +
49397 +       /* Complete the request */
49398 +       if (is_last) {
49399 +               dwc_otg_request_done(ep, req, 0);
49400 +               ep->dwc_ep.start_xfer_buff = 0;
49401 +               ep->dwc_ep.xfer_buff = 0;
49402 +               ep->dwc_ep.xfer_len = 0;
49403 +               return 1;
49404 +       }
49405 +       return 0;
49406 +}
49407 +
49408 +#ifdef DWC_UTE_CFI
49409 +/**
49410 + * This function calculates traverses all the CFI DMA descriptors and
49411 + * and accumulates the bytes that are left to be transfered.
49412 + *
49413 + * @return The total bytes left to transfered, or a negative value as failure
49414 + */
49415 +static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
49416 +{
49417 +       int32_t ret = 0;
49418 +       int i;
49419 +       struct dwc_otg_dma_desc *ddesc = NULL;
49420 +       struct cfi_ep *cfiep;
49421 +
49422 +       /* See if the pcd_ep has its respective cfi_ep mapped */
49423 +       cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
49424 +       if (!cfiep) {
49425 +               CFI_INFO("%s: Failed to find ep\n", __func__);
49426 +               return -1;
49427 +       }
49428 +
49429 +       ddesc = ep->dwc_ep.descs;
49430 +
49431 +       for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
49432 +
49433 +#if defined(PRINT_CFI_DMA_DESCS)
49434 +               print_desc(ddesc, ep->ep.name, i);
49435 +#endif
49436 +               ret += ddesc->status.b.bytes;
49437 +               ddesc++;
49438 +       }
49439 +
49440 +       if (ret)
49441 +               CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
49442 +                        ret);
49443 +
49444 +       return ret;
49445 +}
49446 +#endif
49447 +
49448 +/**
49449 + * This function completes the request for the EP. If there are
49450 + * additional requests for the EP in the queue they will be started.
49451 + */
49452 +static void complete_ep(dwc_otg_pcd_ep_t * ep)
49453 +{
49454 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49455 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49456 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49457 +           dev_if->in_ep_regs[ep->dwc_ep.num];
49458 +       deptsiz_data_t deptsiz;
49459 +       dev_dma_desc_sts_t desc_sts;
49460 +       dwc_otg_pcd_request_t *req = 0;
49461 +       dwc_otg_dev_dma_desc_t *dma_desc;
49462 +       uint32_t byte_count = 0;
49463 +       int is_last = 0;
49464 +       int i;
49465 +
49466 +       DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
49467 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"));
49468 +
49469 +       /* Get any pending requests */
49470 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49471 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
49472 +               if (!req) {
49473 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
49474 +                       return;
49475 +               }
49476 +       } else {
49477 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
49478 +               return;
49479 +       }
49480 +
49481 +       DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
49482 +
49483 +       if (ep->dwc_ep.is_in) {
49484 +               deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49485 +
49486 +               if (core_if->dma_enable) {
49487 +                       if (core_if->dma_desc_enable == 0) {
49488 +                               if (deptsiz.b.xfersize == 0
49489 +                                   && deptsiz.b.pktcnt == 0) {
49490 +                                       byte_count =
49491 +                                           ep->dwc_ep.xfer_len -
49492 +                                           ep->dwc_ep.xfer_count;
49493 +
49494 +                                       ep->dwc_ep.xfer_buff += byte_count;
49495 +                                       ep->dwc_ep.dma_addr += byte_count;
49496 +                                       ep->dwc_ep.xfer_count += byte_count;
49497 +
49498 +                                       DWC_DEBUGPL(DBG_PCDV,
49499 +                                                   "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
49500 +                                                   ep->dwc_ep.num,
49501 +                                                   (ep->dwc_ep.
49502 +                                                    is_in ? "IN" : "OUT"),
49503 +                                                   ep->dwc_ep.xfer_len,
49504 +                                                   deptsiz.b.xfersize,
49505 +                                                   deptsiz.b.pktcnt);
49506 +
49507 +                                       if (ep->dwc_ep.xfer_len <
49508 +                                           ep->dwc_ep.total_len) {
49509 +                                               dwc_otg_ep_start_transfer
49510 +                                                   (core_if, &ep->dwc_ep);
49511 +                                       } else if (ep->dwc_ep.sent_zlp) {
49512 +                                               /*     
49513 +                                                * This fragment of code should initiate 0
49514 +                                                * length transfer in case if it is queued
49515 +                                                * a transfer with size divisible to EPs max
49516 +                                                * packet size and with usb_request zero field
49517 +                                                * is set, which means that after data is transfered,
49518 +                                                * it is also should be transfered
49519 +                                                * a 0 length packet at the end. For Slave and
49520 +                                                * Buffer DMA modes in this case SW has
49521 +                                                * to initiate 2 transfers one with transfer size,
49522 +                                                * and the second with 0 size. For Descriptor
49523 +                                                * DMA mode SW is able to initiate a transfer,
49524 +                                                * which will handle all the packets including
49525 +                                                * the last  0 length.
49526 +                                                */
49527 +                                               ep->dwc_ep.sent_zlp = 0;
49528 +                                               dwc_otg_ep_start_zl_transfer
49529 +                                                   (core_if, &ep->dwc_ep);
49530 +                                       } else {
49531 +                                               is_last = 1;
49532 +                                       }
49533 +                               } else {
49534 +                                       if (ep->dwc_ep.type ==
49535 +                                           DWC_OTG_EP_TYPE_ISOC) {
49536 +                                               req->actual = 0;
49537 +                                               dwc_otg_request_done(ep, req, 0);
49538 +
49539 +                                               ep->dwc_ep.start_xfer_buff = 0;
49540 +                                               ep->dwc_ep.xfer_buff = 0;
49541 +                                               ep->dwc_ep.xfer_len = 0;
49542 +
49543 +                                               /* If there is a request in the queue start it. */
49544 +                                               start_next_request(ep);
49545 +                                       } else
49546 +                                               DWC_WARN
49547 +                                               ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
49548 +                                               ep->dwc_ep.num,
49549 +                                               (ep->dwc_ep.is_in ? "IN" : "OUT"),
49550 +                                               deptsiz.b.xfersize,
49551 +                                               deptsiz.b.pktcnt);
49552 +                               }
49553 +                       } else {
49554 +                               dma_desc = ep->dwc_ep.desc_addr;
49555 +                               byte_count = 0;
49556 +                               ep->dwc_ep.sent_zlp = 0;
49557 +
49558 +#ifdef DWC_UTE_CFI
49559 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49560 +                                        ep->dwc_ep.buff_mode);
49561 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49562 +                                       int residue;
49563 +
49564 +                                       residue = cfi_calc_desc_residue(ep);
49565 +                                       if (residue < 0)
49566 +                                               return;
49567 +
49568 +                                       byte_count = residue;
49569 +                               } else {
49570 +#endif
49571 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
49572 +                                            ++i) {
49573 +                                       desc_sts = dma_desc->status;
49574 +                                       byte_count += desc_sts.b.bytes;
49575 +                                       dma_desc++;
49576 +                               }
49577 +#ifdef DWC_UTE_CFI
49578 +                               }
49579 +#endif
49580 +                               if (byte_count == 0) {
49581 +                                       ep->dwc_ep.xfer_count =
49582 +                                           ep->dwc_ep.total_len;
49583 +                                       is_last = 1;
49584 +                               } else {
49585 +                                       DWC_WARN("Incomplete transfer\n");
49586 +                               }
49587 +                       }
49588 +               } else {
49589 +                       if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
49590 +                               DWC_DEBUGPL(DBG_PCDV,
49591 +                                           "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
49592 +                                           ep->dwc_ep.num,
49593 +                                           ep->dwc_ep.is_in ? "IN" : "OUT",
49594 +                                           ep->dwc_ep.xfer_len,
49595 +                                           deptsiz.b.xfersize,
49596 +                                           deptsiz.b.pktcnt);
49597 +
49598 +                               /*      Check if the whole transfer was completed, 
49599 +                                *      if no, setup transfer for next portion of data
49600 +                                */
49601 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49602 +                                       dwc_otg_ep_start_transfer(core_if,
49603 +                                                                 &ep->dwc_ep);
49604 +                               } else if (ep->dwc_ep.sent_zlp) {
49605 +                                       /*     
49606 +                                        * This fragment of code should initiate 0
49607 +                                        * length trasfer in case if it is queued
49608 +                                        * a trasfer with size divisible to EPs max
49609 +                                        * packet size and with usb_request zero field
49610 +                                        * is set, which means that after data is transfered,
49611 +                                        * it is also should be transfered
49612 +                                        * a 0 length packet at the end. For Slave and
49613 +                                        * Buffer DMA modes in this case SW has
49614 +                                        * to initiate 2 transfers one with transfer size,
49615 +                                        * and the second with 0 size. For Desriptor
49616 +                                        * DMA mode SW is able to initiate a transfer,
49617 +                                        * which will handle all the packets including
49618 +                                        * the last  0 legth.
49619 +                                        */
49620 +                                       ep->dwc_ep.sent_zlp = 0;
49621 +                                       dwc_otg_ep_start_zl_transfer(core_if,
49622 +                                                                    &ep->dwc_ep);
49623 +                               } else {
49624 +                                       is_last = 1;
49625 +                               }
49626 +                       } else {
49627 +                               DWC_WARN
49628 +                                   ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
49629 +                                    ep->dwc_ep.num,
49630 +                                    (ep->dwc_ep.is_in ? "IN" : "OUT"),
49631 +                                    deptsiz.b.xfersize, deptsiz.b.pktcnt);
49632 +                       }
49633 +               }
49634 +       } else {
49635 +               dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49636 +                   dev_if->out_ep_regs[ep->dwc_ep.num];
49637 +               desc_sts.d32 = 0;
49638 +               if (core_if->dma_enable) {
49639 +                       if (core_if->dma_desc_enable) {
49640 +                               dma_desc = ep->dwc_ep.desc_addr;
49641 +                               byte_count = 0;
49642 +                               ep->dwc_ep.sent_zlp = 0;
49643 +
49644 +#ifdef DWC_UTE_CFI
49645 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49646 +                                        ep->dwc_ep.buff_mode);
49647 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49648 +                                       int residue;
49649 +                                       residue = cfi_calc_desc_residue(ep);
49650 +                                       if (residue < 0)
49651 +                                               return;
49652 +                                       byte_count = residue;
49653 +                               } else {
49654 +#endif
49655 +
49656 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
49657 +                                            ++i) {
49658 +                                               desc_sts = dma_desc->status;
49659 +                                               byte_count += desc_sts.b.bytes;
49660 +                                               dma_desc++;
49661 +                                       }
49662 +
49663 +#ifdef DWC_UTE_CFI
49664 +                               }
49665 +#endif
49666 +                               /* Checking for interrupt Out transfers with not 
49667 +                                * dword aligned mps sizes 
49668 +                                */
49669 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&
49670 +                                                       (ep->dwc_ep.maxpacket%4)) {
49671 +                                       ep->dwc_ep.xfer_count =
49672 +                                           ep->dwc_ep.total_len - byte_count;
49673 +                                       if ((ep->dwc_ep.xfer_len %
49674 +                                            ep->dwc_ep.maxpacket)
49675 +                                           && (ep->dwc_ep.xfer_len /
49676 +                                               ep->dwc_ep.maxpacket <
49677 +                                               MAX_DMA_DESC_CNT))
49678 +                                               ep->dwc_ep.xfer_len -=
49679 +                                                   (ep->dwc_ep.desc_cnt -
49680 +                                                    1) * ep->dwc_ep.maxpacket +
49681 +                                                   ep->dwc_ep.xfer_len %
49682 +                                                   ep->dwc_ep.maxpacket;
49683 +                                       else                                            
49684 +                                               ep->dwc_ep.xfer_len -=
49685 +                                                   ep->dwc_ep.desc_cnt *
49686 +                                                   ep->dwc_ep.maxpacket;
49687 +                                       if (ep->dwc_ep.xfer_len > 0) {
49688 +                                               dwc_otg_ep_start_transfer
49689 +                                                   (core_if, &ep->dwc_ep);
49690 +                                       } else {
49691 +                                               is_last = 1;
49692 +                                       }
49693 +                               } else {
49694 +                                       ep->dwc_ep.xfer_count =
49695 +                                           ep->dwc_ep.total_len - byte_count +
49696 +                                           ((4 -
49697 +                                             (ep->dwc_ep.
49698 +                                              total_len & 0x3)) & 0x3);
49699 +                                       is_last = 1;
49700 +                               }       
49701 +                       } else {
49702 +                               deptsiz.d32 = 0;
49703 +                               deptsiz.d32 =
49704 +                                   DWC_READ_REG32(&out_ep_regs->doeptsiz);
49705 +
49706 +                               byte_count = (ep->dwc_ep.xfer_len -
49707 +                                             ep->dwc_ep.xfer_count -
49708 +                                             deptsiz.b.xfersize);
49709 +                               ep->dwc_ep.xfer_buff += byte_count;
49710 +                               ep->dwc_ep.dma_addr += byte_count;
49711 +                               ep->dwc_ep.xfer_count += byte_count;
49712 +
49713 +                               /*      Check if the whole transfer was completed, 
49714 +                                *      if no, setup transfer for next portion of data
49715 +                                */
49716 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49717 +                                       dwc_otg_ep_start_transfer(core_if,
49718 +                                                                 &ep->dwc_ep);
49719 +                               } else if (ep->dwc_ep.sent_zlp) {
49720 +                                       /*     
49721 +                                        * This fragment of code should initiate 0
49722 +                                        * length trasfer in case if it is queued
49723 +                                        * a trasfer with size divisible to EPs max
49724 +                                        * packet size and with usb_request zero field
49725 +                                        * is set, which means that after data is transfered,
49726 +                                        * it is also should be transfered
49727 +                                        * a 0 length packet at the end. For Slave and
49728 +                                        * Buffer DMA modes in this case SW has
49729 +                                        * to initiate 2 transfers one with transfer size,
49730 +                                        * and the second with 0 size. For Desriptor
49731 +                                        * DMA mode SW is able to initiate a transfer,
49732 +                                        * which will handle all the packets including
49733 +                                        * the last  0 legth.
49734 +                                        */
49735 +                                       ep->dwc_ep.sent_zlp = 0;
49736 +                                       dwc_otg_ep_start_zl_transfer(core_if,
49737 +                                                                    &ep->dwc_ep);
49738 +                               } else {
49739 +                                       is_last = 1;
49740 +                               }
49741 +                       }
49742 +               } else {
49743 +                       /*      Check if the whole transfer was completed, 
49744 +                        *      if no, setup transfer for next portion of data
49745 +                        */
49746 +                       if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49747 +                               dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
49748 +                       } else if (ep->dwc_ep.sent_zlp) {
49749 +                               /*     
49750 +                                * This fragment of code should initiate 0
49751 +                                * length transfer in case if it is queued
49752 +                                * a transfer with size divisible to EPs max
49753 +                                * packet size and with usb_request zero field
49754 +                                * is set, which means that after data is transfered,
49755 +                                * it is also should be transfered
49756 +                                * a 0 length packet at the end. For Slave and
49757 +                                * Buffer DMA modes in this case SW has
49758 +                                * to initiate 2 transfers one with transfer size,
49759 +                                * and the second with 0 size. For Descriptor
49760 +                                * DMA mode SW is able to initiate a transfer,
49761 +                                * which will handle all the packets including
49762 +                                * the last  0 length.
49763 +                                */
49764 +                               ep->dwc_ep.sent_zlp = 0;
49765 +                               dwc_otg_ep_start_zl_transfer(core_if,
49766 +                                                            &ep->dwc_ep);
49767 +                       } else {
49768 +                               is_last = 1;
49769 +                       }
49770 +               }
49771 +
49772 +               DWC_DEBUGPL(DBG_PCDV,
49773 +                           "addr %p,    %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
49774 +                           &out_ep_regs->doeptsiz, ep->dwc_ep.num,
49775 +                           ep->dwc_ep.is_in ? "IN" : "OUT",
49776 +                           ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
49777 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49778 +       }
49779 +
49780 +       /* Complete the request */
49781 +       if (is_last) {
49782 +#ifdef DWC_UTE_CFI
49783 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49784 +                       req->actual = ep->dwc_ep.cfi_req_len - byte_count;
49785 +               } else {
49786 +#endif
49787 +                       req->actual = ep->dwc_ep.xfer_count;
49788 +#ifdef DWC_UTE_CFI
49789 +               }
49790 +#endif
49791 +               if (req->dw_align_buf) {
49792 +                       if (!ep->dwc_ep.is_in) {
49793 +                               dwc_memcpy(req->buf, req->dw_align_buf, req->length); 
49794 +                       }
49795 +                       DWC_DMA_FREE(req->length, req->dw_align_buf,
49796 +                                    req->dw_align_buf_dma);
49797 +               }
49798 +
49799 +               dwc_otg_request_done(ep, req, 0);
49800 +
49801 +               ep->dwc_ep.start_xfer_buff = 0;
49802 +               ep->dwc_ep.xfer_buff = 0;
49803 +               ep->dwc_ep.xfer_len = 0;
49804 +
49805 +               /* If there is a request in the queue start it. */
49806 +               start_next_request(ep);
49807 +       }
49808 +}
49809 +
49810 +#ifdef DWC_EN_ISOC
49811 +
49812 +/**
49813 + * This function BNA interrupt for Isochronous EPs
49814 + *
49815 + */
49816 +static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
49817 +{
49818 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
49819 +       volatile uint32_t *addr;
49820 +       depctl_data_t depctl = {.d32 = 0 };
49821 +       dwc_otg_pcd_t *pcd = ep->pcd;
49822 +       dwc_otg_dev_dma_desc_t *dma_desc;
49823 +       int i;
49824 +
49825 +       dma_desc =
49826 +           dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
49827 +
49828 +       if (dwc_ep->is_in) {
49829 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
49830 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49831 +                       sts.d32 = dma_desc->status.d32;
49832 +                       sts.b_iso_in.bs = BS_HOST_READY;
49833 +                       dma_desc->status.d32 = sts.d32;
49834 +               }
49835 +       } else {
49836 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
49837 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49838 +                       sts.d32 = dma_desc->status.d32;
49839 +                       sts.b_iso_out.bs = BS_HOST_READY;
49840 +                       dma_desc->status.d32 = sts.d32;
49841 +               }
49842 +       }
49843 +
49844 +       if (dwc_ep->is_in == 0) {
49845 +               addr =
49846 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->
49847 +                                                          num]->doepctl;
49848 +       } else {
49849 +               addr =
49850 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
49851 +       }
49852 +       depctl.b.epena = 1;
49853 +       DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
49854 +}
49855 +
49856 +/**
49857 + * This function sets latest iso packet information(non-PTI mode)
49858 + *
49859 + * @param core_if Programming view of DWC_otg controller.
49860 + * @param ep The EP to start the transfer on.
49861 + *
49862 + */
49863 +void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
49864 +{
49865 +       deptsiz_data_t deptsiz = {.d32 = 0 };
49866 +       dma_addr_t dma_addr;
49867 +       uint32_t offset;
49868 +
49869 +       if (ep->proc_buf_num)
49870 +               dma_addr = ep->dma_addr1;
49871 +       else
49872 +               dma_addr = ep->dma_addr0;
49873 +
49874 +       if (ep->is_in) {
49875 +               deptsiz.d32 =
49876 +                   DWC_READ_REG32(&core_if->dev_if->
49877 +                                  in_ep_regs[ep->num]->dieptsiz);
49878 +               offset = ep->data_per_frame;
49879 +       } else {
49880 +               deptsiz.d32 =
49881 +                   DWC_READ_REG32(&core_if->dev_if->
49882 +                                  out_ep_regs[ep->num]->doeptsiz);
49883 +               offset =
49884 +                   ep->data_per_frame +
49885 +                   (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
49886 +       }
49887 +
49888 +       if (!deptsiz.b.xfersize) {
49889 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
49890 +               ep->pkt_info[ep->cur_pkt].offset =
49891 +                   ep->cur_pkt_dma_addr - dma_addr;
49892 +               ep->pkt_info[ep->cur_pkt].status = 0;
49893 +       } else {
49894 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
49895 +               ep->pkt_info[ep->cur_pkt].offset =
49896 +                   ep->cur_pkt_dma_addr - dma_addr;
49897 +               ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
49898 +       }
49899 +       ep->cur_pkt_addr += offset;
49900 +       ep->cur_pkt_dma_addr += offset;
49901 +       ep->cur_pkt++;
49902 +}
49903 +
49904 +/**
49905 + * This function sets latest iso packet information(DDMA mode)
49906 + *
49907 + * @param core_if Programming view of DWC_otg controller.
49908 + * @param dwc_ep The EP to start the transfer on.
49909 + *
49910 + */
49911 +static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
49912 +                                  dwc_ep_t * dwc_ep)
49913 +{
49914 +       dwc_otg_dev_dma_desc_t *dma_desc;
49915 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
49916 +       iso_pkt_info_t *iso_packet;
49917 +       uint32_t data_per_desc;
49918 +       uint32_t offset;
49919 +       int i, j;
49920 +
49921 +       iso_packet = dwc_ep->pkt_info;
49922 +
49923 +       /** Reinit closed DMA Descriptors*/
49924 +       /** ISO OUT EP */
49925 +       if (dwc_ep->is_in == 0) {
49926 +               dma_desc =
49927 +                   dwc_ep->iso_desc_addr +
49928 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49929 +               offset = 0;
49930 +
49931 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
49932 +                    i += dwc_ep->pkt_per_frm) {
49933 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
49934 +                               data_per_desc =
49935 +                                   ((j + 1) * dwc_ep->maxpacket >
49936 +                                    dwc_ep->
49937 +                                    data_per_frame) ? dwc_ep->data_per_frame -
49938 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49939 +                               data_per_desc +=
49940 +                                   (data_per_desc % 4) ? (4 -
49941 +                                                          data_per_desc %
49942 +                                                          4) : 0;
49943 +
49944 +                               sts.d32 = dma_desc->status.d32;
49945 +
49946 +                               /* Write status in iso_packet_decsriptor  */
49947 +                               iso_packet->status =
49948 +                                   sts.b_iso_out.rxsts +
49949 +                                   (sts.b_iso_out.bs ^ BS_DMA_DONE);
49950 +                               if (iso_packet->status) {
49951 +                                       iso_packet->status = -DWC_E_NO_DATA;
49952 +                               }
49953 +
49954 +                               /* Received data length */
49955 +                               if (!sts.b_iso_out.rxbytes) {
49956 +                                       iso_packet->length =
49957 +                                           data_per_desc -
49958 +                                           sts.b_iso_out.rxbytes;
49959 +                               } else {
49960 +                                       iso_packet->length =
49961 +                                           data_per_desc -
49962 +                                           sts.b_iso_out.rxbytes + (4 -
49963 +                                                                    dwc_ep->data_per_frame
49964 +                                                                    % 4);
49965 +                               }
49966 +
49967 +                               iso_packet->offset = offset;
49968 +
49969 +                               offset += data_per_desc;
49970 +                               dma_desc++;
49971 +                               iso_packet++;
49972 +                       }
49973 +               }
49974 +
49975 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
49976 +                       data_per_desc =
49977 +                           ((j + 1) * dwc_ep->maxpacket >
49978 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
49979 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49980 +                       data_per_desc +=
49981 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
49982 +
49983 +                       sts.d32 = dma_desc->status.d32;
49984 +
49985 +                       /* Write status in iso_packet_decsriptor  */
49986 +                       iso_packet->status =
49987 +                           sts.b_iso_out.rxsts +
49988 +                           (sts.b_iso_out.bs ^ BS_DMA_DONE);
49989 +                       if (iso_packet->status) {
49990 +                               iso_packet->status = -DWC_E_NO_DATA;
49991 +                       }
49992 +
49993 +                       /* Received data length */
49994 +                       iso_packet->length =
49995 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
49996 +
49997 +                       iso_packet->offset = offset;
49998 +
49999 +                       offset += data_per_desc;
50000 +                       iso_packet++;
50001 +                       dma_desc++;
50002 +               }
50003 +
50004 +               sts.d32 = dma_desc->status.d32;
50005 +
50006 +               /* Write status in iso_packet_decsriptor  */
50007 +               iso_packet->status =
50008 +                   sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
50009 +               if (iso_packet->status) {
50010 +                       iso_packet->status = -DWC_E_NO_DATA;
50011 +               }
50012 +               /* Received data length */
50013 +               if (!sts.b_iso_out.rxbytes) {
50014 +                       iso_packet->length =
50015 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
50016 +               } else {
50017 +                       iso_packet->length =
50018 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
50019 +                           (4 - dwc_ep->data_per_frame % 4);
50020 +               }
50021 +
50022 +               iso_packet->offset = offset;
50023 +       } else {
50024 +/** ISO IN EP */
50025 +
50026 +               dma_desc =
50027 +                   dwc_ep->iso_desc_addr +
50028 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50029 +
50030 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
50031 +                       sts.d32 = dma_desc->status.d32;
50032 +
50033 +                       /* Write status in iso packet descriptor */
50034 +                       iso_packet->status =
50035 +                           sts.b_iso_in.txsts +
50036 +                           (sts.b_iso_in.bs ^ BS_DMA_DONE);
50037 +                       if (iso_packet->status != 0) {
50038 +                               iso_packet->status = -DWC_E_NO_DATA;
50039 +
50040 +                       }
50041 +                       /* Bytes has been transfered */
50042 +                       iso_packet->length =
50043 +                           dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
50044 +
50045 +                       dma_desc++;
50046 +                       iso_packet++;
50047 +               }
50048 +
50049 +               sts.d32 = dma_desc->status.d32;
50050 +               while (sts.b_iso_in.bs == BS_DMA_BUSY) {
50051 +                       sts.d32 = dma_desc->status.d32;
50052 +               }
50053 +
50054 +               /* Write status in iso packet descriptor ??? do be done with ERROR codes */
50055 +               iso_packet->status =
50056 +                   sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
50057 +               if (iso_packet->status != 0) {
50058 +                       iso_packet->status = -DWC_E_NO_DATA;
50059 +               }
50060 +
50061 +               /* Bytes has been transfered */
50062 +               iso_packet->length =
50063 +                   dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
50064 +       }
50065 +}
50066 +
50067 +/**
50068 + * This function reinitialize DMA Descriptors for Isochronous transfer
50069 + *
50070 + * @param core_if Programming view of DWC_otg controller.
50071 + * @param dwc_ep The EP to start the transfer on.
50072 + *
50073 + */
50074 +static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
50075 +{
50076 +       int i, j;
50077 +       dwc_otg_dev_dma_desc_t *dma_desc;
50078 +       dma_addr_t dma_ad;
50079 +       volatile uint32_t *addr;
50080 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
50081 +       uint32_t data_per_desc;
50082 +
50083 +       if (dwc_ep->is_in == 0) {
50084 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
50085 +       } else {
50086 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50087 +       }
50088 +
50089 +       if (dwc_ep->proc_buf_num == 0) {
50090 +               /** Buffer 0 descriptors setup */
50091 +               dma_ad = dwc_ep->dma_addr0;
50092 +       } else {
50093 +               /** Buffer 1 descriptors setup */
50094 +               dma_ad = dwc_ep->dma_addr1;
50095 +       }
50096 +
50097 +       /** Reinit closed DMA Descriptors*/
50098 +       /** ISO OUT EP */
50099 +       if (dwc_ep->is_in == 0) {
50100 +               dma_desc =
50101 +                   dwc_ep->iso_desc_addr +
50102 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50103 +
50104 +               sts.b_iso_out.bs = BS_HOST_READY;
50105 +               sts.b_iso_out.rxsts = 0;
50106 +               sts.b_iso_out.l = 0;
50107 +               sts.b_iso_out.sp = 0;
50108 +               sts.b_iso_out.ioc = 0;
50109 +               sts.b_iso_out.pid = 0;
50110 +               sts.b_iso_out.framenum = 0;
50111 +
50112 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
50113 +                    i += dwc_ep->pkt_per_frm) {
50114 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
50115 +                               data_per_desc =
50116 +                                   ((j + 1) * dwc_ep->maxpacket >
50117 +                                    dwc_ep->
50118 +                                    data_per_frame) ? dwc_ep->data_per_frame -
50119 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50120 +                               data_per_desc +=
50121 +                                   (data_per_desc % 4) ? (4 -
50122 +                                                          data_per_desc %
50123 +                                                          4) : 0;
50124 +                               sts.b_iso_out.rxbytes = data_per_desc;
50125 +                               dma_desc->buf = dma_ad;
50126 +                               dma_desc->status.d32 = sts.d32;
50127 +
50128 +                               dma_ad += data_per_desc;
50129 +                               dma_desc++;
50130 +                       }
50131 +               }
50132 +
50133 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
50134 +
50135 +                       data_per_desc =
50136 +                           ((j + 1) * dwc_ep->maxpacket >
50137 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
50138 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50139 +                       data_per_desc +=
50140 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
50141 +                       sts.b_iso_out.rxbytes = data_per_desc;
50142 +
50143 +                       dma_desc->buf = dma_ad;
50144 +                       dma_desc->status.d32 = sts.d32;
50145 +
50146 +                       dma_desc++;
50147 +                       dma_ad += data_per_desc;
50148 +               }
50149 +
50150 +               sts.b_iso_out.ioc = 1;
50151 +               sts.b_iso_out.l = dwc_ep->proc_buf_num;
50152 +
50153 +               data_per_desc =
50154 +                   ((j + 1) * dwc_ep->maxpacket >
50155 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
50156 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50157 +               data_per_desc +=
50158 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
50159 +               sts.b_iso_out.rxbytes = data_per_desc;
50160 +
50161 +               dma_desc->buf = dma_ad;
50162 +               dma_desc->status.d32 = sts.d32;
50163 +       } else {
50164 +/** ISO IN EP */
50165 +
50166 +               dma_desc =
50167 +                   dwc_ep->iso_desc_addr +
50168 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50169 +
50170 +               sts.b_iso_in.bs = BS_HOST_READY;
50171 +               sts.b_iso_in.txsts = 0;
50172 +               sts.b_iso_in.sp = 0;
50173 +               sts.b_iso_in.ioc = 0;
50174 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
50175 +               sts.b_iso_in.framenum = dwc_ep->next_frame;
50176 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
50177 +               sts.b_iso_in.l = 0;
50178 +
50179 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
50180 +                       dma_desc->buf = dma_ad;
50181 +                       dma_desc->status.d32 = sts.d32;
50182 +
50183 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
50184 +                       dma_ad += dwc_ep->data_per_frame;
50185 +                       dma_desc++;
50186 +               }
50187 +
50188 +               sts.b_iso_in.ioc = 1;
50189 +               sts.b_iso_in.l = dwc_ep->proc_buf_num;
50190 +
50191 +               dma_desc->buf = dma_ad;
50192 +               dma_desc->status.d32 = sts.d32;
50193 +
50194 +               dwc_ep->next_frame =
50195 +                   sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
50196 +       }
50197 +       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50198 +}
50199 +
50200 +/**
50201 + * This function is to handle Iso EP transfer complete interrupt
50202 + * in case Iso out packet was dropped
50203 + *
50204 + * @param core_if Programming view of DWC_otg controller.
50205 + * @param dwc_ep The EP for wihich transfer complete was asserted
50206 + *
50207 + */
50208 +static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
50209 +                                          dwc_ep_t * dwc_ep)
50210 +{
50211 +       uint32_t dma_addr;
50212 +       uint32_t drp_pkt;
50213 +       uint32_t drp_pkt_cnt;
50214 +       deptsiz_data_t deptsiz = {.d32 = 0 };
50215 +       depctl_data_t depctl = {.d32 = 0 };
50216 +       int i;
50217 +
50218 +       deptsiz.d32 =
50219 +           DWC_READ_REG32(&core_if->dev_if->
50220 +                          out_ep_regs[dwc_ep->num]->doeptsiz);
50221 +
50222 +       drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
50223 +       drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
50224 +
50225 +       /* Setting dropped packets status */
50226 +       for (i = 0; i < drp_pkt_cnt; ++i) {
50227 +               dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
50228 +               drp_pkt++;
50229 +               deptsiz.b.pktcnt--;
50230 +       }
50231 +
50232 +       if (deptsiz.b.pktcnt > 0) {
50233 +               deptsiz.b.xfersize =
50234 +                   dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
50235 +                                       deptsiz.b.pktcnt) * dwc_ep->maxpacket;
50236 +       } else {
50237 +               deptsiz.b.xfersize = 0;
50238 +               deptsiz.b.pktcnt = 0;
50239 +       }
50240 +
50241 +       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
50242 +                       deptsiz.d32);
50243 +
50244 +       if (deptsiz.b.pktcnt > 0) {
50245 +               if (dwc_ep->proc_buf_num) {
50246 +                       dma_addr =
50247 +                           dwc_ep->dma_addr1 + dwc_ep->xfer_len -
50248 +                           deptsiz.b.xfersize;
50249 +               } else {
50250 +                       dma_addr =
50251 +                           dwc_ep->dma_addr0 + dwc_ep->xfer_len -
50252 +                           deptsiz.b.xfersize;;
50253 +               }
50254 +
50255 +               DWC_WRITE_REG32(&core_if->dev_if->
50256 +                               out_ep_regs[dwc_ep->num]->doepdma, dma_addr);
50257 +
50258 +               /** Re-enable endpoint, clear nak  */
50259 +               depctl.d32 = 0;
50260 +               depctl.b.epena = 1;
50261 +               depctl.b.cnak = 1;
50262 +
50263 +               DWC_MODIFY_REG32(&core_if->dev_if->
50264 +                                out_ep_regs[dwc_ep->num]->doepctl, depctl.d32,
50265 +                                depctl.d32);
50266 +               return 0;
50267 +       } else {
50268 +               return 1;
50269 +       }
50270 +}
50271 +
50272 +/**
50273 + * This function sets iso packets information(PTI mode)
50274 + *
50275 + * @param core_if Programming view of DWC_otg controller.
50276 + * @param ep The EP to start the transfer on.
50277 + *
50278 + */
50279 +static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
50280 +{
50281 +       int i, j;
50282 +       dma_addr_t dma_ad;
50283 +       iso_pkt_info_t *packet_info = ep->pkt_info;
50284 +       uint32_t offset;
50285 +       uint32_t frame_data;
50286 +       deptsiz_data_t deptsiz;
50287 +
50288 +       if (ep->proc_buf_num == 0) {
50289 +               /** Buffer 0 descriptors setup */
50290 +               dma_ad = ep->dma_addr0;
50291 +       } else {
50292 +               /** Buffer 1 descriptors setup */
50293 +               dma_ad = ep->dma_addr1;
50294 +       }
50295 +
50296 +       if (ep->is_in) {
50297 +               deptsiz.d32 =
50298 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
50299 +                                  dieptsiz);
50300 +       } else {
50301 +               deptsiz.d32 =
50302 +                   DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
50303 +                                  doeptsiz);
50304 +       }
50305 +
50306 +       if (!deptsiz.b.xfersize) {
50307 +               offset = 0;
50308 +               for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
50309 +                       frame_data = ep->data_per_frame;
50310 +                       for (j = 0; j < ep->pkt_per_frm; ++j) {
50311 +
50312 +                               /* Packet status - is not set as initially
50313 +                                * it is set to 0 and if packet was sent
50314 +                                successfully, status field will remain 0*/
50315 +
50316 +                               /* Bytes has been transfered */
50317 +                               packet_info->length =
50318 +                                   (ep->maxpacket <
50319 +                                    frame_data) ? ep->maxpacket : frame_data;
50320 +
50321 +                               /* Received packet offset */
50322 +                               packet_info->offset = offset;
50323 +                               offset += packet_info->length;
50324 +                               frame_data -= packet_info->length;
50325 +
50326 +                               packet_info++;
50327 +                       }
50328 +               }
50329 +               return 1;
50330 +       } else {
50331 +               /* This is a workaround for in case of Transfer Complete with
50332 +                * PktDrpSts interrupts merging - in this case Transfer complete
50333 +                * interrupt for Isoc Out Endpoint is asserted without PktDrpSts
50334 +                * set and with DOEPTSIZ register non zero. Investigations showed,
50335 +                * that this happens when Out packet is dropped, but because of
50336 +                * interrupts merging during first interrupt handling PktDrpSts
50337 +                * bit is cleared and for next merged interrupts it is not reset.
50338 +                * In this case SW hadles the interrupt as if PktDrpSts bit is set.
50339 +                */
50340 +               if (ep->is_in) {
50341 +                       return 1;
50342 +               } else {
50343 +                       return handle_iso_out_pkt_dropped(core_if, ep);
50344 +               }
50345 +       }
50346 +}
50347 +
50348 +/**
50349 + * This function is to handle Iso EP transfer complete interrupt
50350 + *
50351 + * @param pcd The PCD
50352 + * @param ep The EP for which transfer complete was asserted
50353 + *
50354 + */
50355 +static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
50356 +{
50357 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
50358 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
50359 +       uint8_t is_last = 0;
50360 +
50361 +       if (ep->dwc_ep.next_frame == 0xffffffff) {
50362 +               DWC_WARN("Next frame is not set!\n");
50363 +               return;
50364 +       }
50365 +
50366 +       if (core_if->dma_enable) {
50367 +               if (core_if->dma_desc_enable) {
50368 +                       set_ddma_iso_pkts_info(core_if, dwc_ep);
50369 +                       reinit_ddma_iso_xfer(core_if, dwc_ep);
50370 +                       is_last = 1;
50371 +               } else {
50372 +                       if (core_if->pti_enh_enable) {
50373 +                               if (set_iso_pkts_info(core_if, dwc_ep)) {
50374 +                                       dwc_ep->proc_buf_num =
50375 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
50376 +                                       dwc_otg_iso_ep_start_buf_transfer
50377 +                                           (core_if, dwc_ep);
50378 +                                       is_last = 1;
50379 +                               }
50380 +                       } else {
50381 +                               set_current_pkt_info(core_if, dwc_ep);
50382 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50383 +                                       is_last = 1;
50384 +                                       dwc_ep->cur_pkt = 0;
50385 +                                       dwc_ep->proc_buf_num =
50386 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
50387 +                                       if (dwc_ep->proc_buf_num) {
50388 +                                               dwc_ep->cur_pkt_addr =
50389 +                                                   dwc_ep->xfer_buff1;
50390 +                                               dwc_ep->cur_pkt_dma_addr =
50391 +                                                   dwc_ep->dma_addr1;
50392 +                                       } else {
50393 +                                               dwc_ep->cur_pkt_addr =
50394 +                                                   dwc_ep->xfer_buff0;
50395 +                                               dwc_ep->cur_pkt_dma_addr =
50396 +                                                   dwc_ep->dma_addr0;
50397 +                                       }
50398 +
50399 +                               }
50400 +                               dwc_otg_iso_ep_start_frm_transfer(core_if,
50401 +                                                                 dwc_ep);
50402 +                       }
50403 +               }
50404 +       } else {
50405 +               set_current_pkt_info(core_if, dwc_ep);
50406 +               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50407 +                       is_last = 1;
50408 +                       dwc_ep->cur_pkt = 0;
50409 +                       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50410 +                       if (dwc_ep->proc_buf_num) {
50411 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
50412 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
50413 +                       } else {
50414 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
50415 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
50416 +                       }
50417 +
50418 +               }
50419 +               dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
50420 +       }
50421 +       if (is_last)
50422 +               dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
50423 +}
50424 +#endif /* DWC_EN_ISOC */
50425 +
50426 +/**
50427 + * This function handle BNA interrupt for Non Isochronous EPs
50428 + *
50429 + */
50430 +static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep)
50431 +{
50432 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
50433 +       volatile uint32_t *addr;
50434 +       depctl_data_t depctl = {.d32 = 0 };
50435 +       dwc_otg_pcd_t *pcd = ep->pcd;
50436 +       dwc_otg_dev_dma_desc_t *dma_desc;
50437 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
50438 +       dwc_otg_core_if_t *core_if = ep->pcd->core_if;
50439 +       int i, start;
50440 +
50441 +       if (!dwc_ep->desc_cnt)
50442 +               DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num,
50443 +                        (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt);
50444 +
50445 +       if (core_if->core_params->cont_on_bna && !dwc_ep->is_in
50446 +                                                       && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {
50447 +               uint32_t doepdma;
50448 +               dwc_otg_dev_out_ep_regs_t *out_regs =
50449 +                       core_if->dev_if->out_ep_regs[dwc_ep->num];
50450 +               doepdma = DWC_READ_REG32(&(out_regs->doepdma));
50451 +               start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);
50452 +               dma_desc = &(dwc_ep->desc_addr[start]);
50453 +       } else {
50454 +               start = 0;
50455 +               dma_desc = dwc_ep->desc_addr;
50456 +       }
50457 +       
50458 +
50459 +       for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
50460 +               sts.d32 = dma_desc->status.d32;
50461 +               sts.b.bs = BS_HOST_READY;
50462 +               dma_desc->status.d32 = sts.d32;
50463 +       }
50464 +
50465 +       if (dwc_ep->is_in == 0) {
50466 +               addr =
50467 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
50468 +                   doepctl;
50469 +       } else {
50470 +               addr =
50471 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50472 +       }
50473 +       depctl.b.epena = 1;
50474 +       depctl.b.cnak = 1;
50475 +       DWC_MODIFY_REG32(addr, 0, depctl.d32);
50476 +}
50477 +
50478 +/**
50479 + * This function handles EP0 Control transfers.
50480 + *
50481 + * The state of the control transfers are tracked in
50482 + * <code>ep0state</code>.
50483 + */
50484 +static void handle_ep0(dwc_otg_pcd_t * pcd)
50485 +{
50486 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50487 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
50488 +       dev_dma_desc_sts_t desc_sts;
50489 +       deptsiz0_data_t deptsiz;
50490 +       uint32_t byte_count;
50491 +
50492 +#ifdef DEBUG_EP0
50493 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
50494 +       print_ep0_state(pcd);
50495 +#endif
50496 +
50497 +//      DWC_PRINTF("HANDLE EP0\n");
50498 +
50499 +       switch (pcd->ep0state) {
50500 +       case EP0_DISCONNECT:
50501 +               break;
50502 +
50503 +       case EP0_IDLE:
50504 +               pcd->request_config = 0;
50505 +
50506 +               pcd_setup(pcd);
50507 +               break;
50508 +
50509 +       case EP0_IN_DATA_PHASE:
50510 +#ifdef DEBUG_EP0
50511 +               DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
50512 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50513 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50514 +#endif
50515 +
50516 +               if (core_if->dma_enable != 0) {
50517 +                       /*
50518 +                        * For EP0 we can only program 1 packet at a time so we
50519 +                        * need to do the make calculations after each complete.
50520 +                        * Call write_packet to make the calculations, as in
50521 +                        * slave mode, and use those values to determine if we
50522 +                        * can complete.
50523 +                        */
50524 +                       if (core_if->dma_desc_enable == 0) {
50525 +                               deptsiz.d32 =
50526 +                                   DWC_READ_REG32(&core_if->
50527 +                                                  dev_if->in_ep_regs[0]->
50528 +                                                  dieptsiz);
50529 +                               byte_count =
50530 +                                   ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
50531 +                       } else {
50532 +                               desc_sts =
50533 +                                   core_if->dev_if->in_desc_addr->status;
50534 +                               byte_count =
50535 +                                   ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
50536 +                       }
50537 +                       ep0->dwc_ep.xfer_count += byte_count;
50538 +                       ep0->dwc_ep.xfer_buff += byte_count;
50539 +                       ep0->dwc_ep.dma_addr += byte_count;
50540 +               }
50541 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50542 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50543 +                                                     &ep0->dwc_ep);
50544 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50545 +               } else if (ep0->dwc_ep.sent_zlp) {
50546 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50547 +                                                     &ep0->dwc_ep);
50548 +                       ep0->dwc_ep.sent_zlp = 0;
50549 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50550 +               } else {
50551 +                       ep0_complete_request(ep0);
50552 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50553 +               }
50554 +               break;
50555 +       case EP0_OUT_DATA_PHASE:
50556 +#ifdef DEBUG_EP0
50557 +               DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
50558 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50559 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50560 +#endif
50561 +               if (core_if->dma_enable != 0) {
50562 +                       if (core_if->dma_desc_enable == 0) {
50563 +                               deptsiz.d32 =
50564 +                                   DWC_READ_REG32(&core_if->
50565 +                                                  dev_if->out_ep_regs[0]->
50566 +                                                  doeptsiz);
50567 +                               byte_count =
50568 +                                   ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
50569 +                       } else {
50570 +                               desc_sts =
50571 +                                   core_if->dev_if->out_desc_addr->status;
50572 +                               byte_count =
50573 +                                   ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
50574 +                       }
50575 +                       ep0->dwc_ep.xfer_count += byte_count;
50576 +                       ep0->dwc_ep.xfer_buff += byte_count;
50577 +                       ep0->dwc_ep.dma_addr += byte_count;
50578 +               }
50579 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50580 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50581 +                                                     &ep0->dwc_ep);
50582 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50583 +               } else if (ep0->dwc_ep.sent_zlp) {
50584 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50585 +                                                     &ep0->dwc_ep);
50586 +                       ep0->dwc_ep.sent_zlp = 0;
50587 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50588 +               } else {
50589 +                       ep0_complete_request(ep0);
50590 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50591 +               }
50592 +               break;
50593 +
50594 +       case EP0_IN_STATUS_PHASE:
50595 +       case EP0_OUT_STATUS_PHASE:
50596 +               DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
50597 +               ep0_complete_request(ep0);
50598 +               pcd->ep0state = EP0_IDLE;
50599 +               ep0->stopped = 1;
50600 +               ep0->dwc_ep.is_in = 0;  /* OUT for next SETUP */
50601 +
50602 +               /* Prepare for more SETUP Packets */
50603 +               if (core_if->dma_enable) {
50604 +                       ep0_out_start(core_if, pcd);
50605 +               }
50606 +               break;
50607 +
50608 +       case EP0_STALL:
50609 +               DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
50610 +               break;
50611 +       }
50612 +#ifdef DEBUG_EP0
50613 +       print_ep0_state(pcd);
50614 +#endif
50615 +}
50616 +
50617 +/**
50618 + * Restart transfer
50619 + */
50620 +static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
50621 +{
50622 +       dwc_otg_core_if_t *core_if;
50623 +       dwc_otg_dev_if_t *dev_if;
50624 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50625 +       dwc_otg_pcd_ep_t *ep;
50626 +
50627 +       ep = get_in_ep(pcd, epnum);
50628 +
50629 +#ifdef DWC_EN_ISOC
50630 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
50631 +               return;
50632 +       }
50633 +#endif /* DWC_EN_ISOC  */
50634 +
50635 +       core_if = GET_CORE_IF(pcd);
50636 +       dev_if = core_if->dev_if;
50637 +
50638 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50639 +
50640 +       DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
50641 +                   " stopped=%d\n", ep->dwc_ep.xfer_buff,
50642 +                   ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
50643 +       /*
50644 +        * If xfersize is 0 and pktcnt in not 0, resend the last packet.
50645 +        */
50646 +       if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
50647 +           ep->dwc_ep.start_xfer_buff != 0) {
50648 +               if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
50649 +                       ep->dwc_ep.xfer_count = 0;
50650 +                       ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
50651 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50652 +               } else {
50653 +                       ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
50654 +                       /* convert packet size to dwords. */
50655 +                       ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
50656 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50657 +               }
50658 +               ep->stopped = 0;
50659 +               DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
50660 +                           "xfer_len=%0x stopped=%d\n",
50661 +                           ep->dwc_ep.xfer_buff,
50662 +                           ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
50663 +                           ep->stopped);
50664 +               if (epnum == 0) {
50665 +                       dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
50666 +               } else {
50667 +                       dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
50668 +               }
50669 +       }
50670 +}
50671 +
50672 +/*
50673 + * This function create new nextep sequnce based on Learn Queue.
50674 + *
50675 + * @param core_if Programming view of DWC_otg controller
50676 + */
50677 +void predict_nextep_seq( dwc_otg_core_if_t * core_if)
50678 +{
50679 +       dwc_otg_device_global_regs_t *dev_global_regs =
50680 +           core_if->dev_if->dev_global_regs;
50681 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
50682 +       /* Number of Token Queue Registers */
50683 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
50684 +       dtknq1_data_t dtknqr1;
50685 +       uint32_t in_tkn_epnums[4];
50686 +       uint8_t seqnum[MAX_EPS_CHANNELS];
50687 +       uint8_t intkn_seq[TOKEN_Q_DEPTH];
50688 +       grstctl_t resetctl = {.d32 = 0 };
50689 +       uint8_t temp;
50690 +       int ndx = 0;
50691 +       int start = 0;
50692 +       int end = 0;
50693 +       int sort_done = 0;
50694 +       int i = 0;
50695 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
50696 +
50697 +
50698 +       DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
50699 +
50700 +       /* Read the DTKNQ Registers */
50701 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
50702 +               in_tkn_epnums[i] = DWC_READ_REG32(addr);
50703 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
50704 +                           in_tkn_epnums[i]);
50705 +               if (addr == &dev_global_regs->dvbusdis) {
50706 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
50707 +               } else {
50708 +                       ++addr;
50709 +               }
50710 +
50711 +       }
50712 +
50713 +       /* Copy the DTKNQR1 data to the bit field. */
50714 +       dtknqr1.d32 = in_tkn_epnums[0];
50715 +       if (dtknqr1.b.wrap_bit) {
50716 +               ndx = dtknqr1.b.intknwptr;
50717 +               end = ndx -1;
50718 +               if (end < 0) 
50719 +                       end = TOKEN_Q_DEPTH -1;
50720 +       } else {
50721 +               ndx = 0;
50722 +               end = dtknqr1.b.intknwptr -1;
50723 +               if (end < 0) 
50724 +                       end = 0;
50725 +       }
50726 +       start = ndx;
50727 +       
50728 +       /* Fill seqnum[] by initial values: EP number + 31 */
50729 +       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50730 +               seqnum[i] = i +31;
50731 +       }
50732 +       
50733 +       /* Fill intkn_seq[] from in_tkn_epnums[0] */
50734 +       for (i=0; i < 6; i++) 
50735 +               intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf;
50736 +       
50737 +       if (TOKEN_Q_DEPTH > 6) {
50738 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50739 +               for (i=6; i < 14; i++) 
50740 +                       intkn_seq[i] =
50741 +                           (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf;
50742 +       }
50743 +       
50744 +       if (TOKEN_Q_DEPTH > 14) {
50745 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50746 +               for (i=14; i < 22; i++) 
50747 +                       intkn_seq[i] =
50748 +                           (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf;
50749 +       }
50750 +
50751 +       if (TOKEN_Q_DEPTH > 22) {
50752 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50753 +               for (i=22; i < 30; i++) 
50754 +                       intkn_seq[i] =
50755 +                           (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf;
50756 +       }
50757 +
50758 +       DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__,
50759 +                   start, end);
50760 +       for (i=0; i<TOKEN_Q_DEPTH; i++) 
50761 +               DWC_DEBUGPL(DBG_PCDV,"%d\n", intkn_seq[i]);
50762 +
50763 +       /* Update seqnum based on intkn_seq[] */
50764 +       i = 0;
50765 +       do {
50766 +               seqnum[intkn_seq[ndx]] = i;
50767 +               ndx++;
50768 +               i++;
50769 +               if (ndx == TOKEN_Q_DEPTH) 
50770 +                       ndx = 0;
50771 +       } while ( i < TOKEN_Q_DEPTH );
50772 +       
50773 +       /* Mark non active EP's in seqnum[] by 0xff */
50774 +       for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50775 +               if (core_if->nextep_seq[i] == 0xff )
50776 +                       seqnum[i] = 0xff;
50777 +       }
50778 +       
50779 +       /* Sort seqnum[] */
50780 +       sort_done = 0;
50781 +       while (!sort_done) {
50782 +               sort_done = 1;
50783 +               for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50784 +                       if (seqnum[i] > seqnum[i+1]) {
50785 +                               temp = seqnum[i];
50786 +                               seqnum[i] = seqnum[i+1];
50787 +                               seqnum[i+1] = temp;
50788 +                               sort_done = 0;
50789 +                       }
50790 +               }
50791 +       }
50792 +
50793 +       ndx = start + seqnum[0];
50794 +       if (ndx >= TOKEN_Q_DEPTH) 
50795 +               ndx = ndx % TOKEN_Q_DEPTH;
50796 +       core_if->first_in_nextep_seq = intkn_seq[ndx];
50797 +       
50798 +       /* Update seqnum[] by EP numbers  */
50799 +       for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50800 +               ndx = start + i;
50801 +               if (seqnum[i] < 31) {
50802 +                       ndx = start + seqnum[i];
50803 +                       if (ndx >= TOKEN_Q_DEPTH) 
50804 +                               ndx = ndx % TOKEN_Q_DEPTH;
50805 +                       seqnum[i] = intkn_seq[ndx];
50806 +               } else {
50807 +                       if (seqnum[i] < 0xff) {
50808 +                               seqnum[i] = seqnum[i] - 31;
50809 +                       } else {
50810 +                               break;
50811 +                       }
50812 +               }
50813 +       }
50814 +
50815 +       /* Update nextep_seq[] based on seqnum[] */
50816 +       for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50817 +               if (seqnum[i] != 0xff) {
50818 +                       if (seqnum[i+1] != 0xff) {
50819 +                               core_if->nextep_seq[seqnum[i]] = seqnum[i+1];
50820 +                       } else {
50821 +                               core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq;
50822 +                               break;
50823 +                       }
50824 +               } else {
50825 +                       break;
50826 +               }
50827 +       }
50828 +       
50829 +       DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", 
50830 +               __func__, core_if->first_in_nextep_seq);
50831 +       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50832 +               DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]);
50833 +       }
50834 +
50835 +       /* Flush the Learning Queue */
50836 +       resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl);
50837 +       resetctl.b.intknqflsh = 1;
50838 +       DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
50839 +       
50840 +
50841 +}
50842 +
50843 +/**
50844 + * handle the IN EP disable interrupt.
50845 + */
50846 +static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
50847 +                                            const uint32_t epnum)
50848 +{
50849 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50850 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50851 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50852 +       dctl_data_t dctl = {.d32 = 0 };
50853 +       dwc_otg_pcd_ep_t *ep;
50854 +       dwc_ep_t *dwc_ep;
50855 +       gintmsk_data_t gintmsk_data;
50856 +       depctl_data_t depctl;
50857 +       uint32_t diepdma;
50858 +       uint32_t remain_to_transfer = 0;
50859 +       uint8_t i;
50860 +       uint32_t xfer_size;
50861 +       
50862 +       ep = get_in_ep(pcd, epnum);
50863 +       dwc_ep = &ep->dwc_ep;
50864 +
50865 +       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
50866 +               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
50867 +               complete_ep(ep);
50868 +               return;
50869 +       }
50870 +
50871 +       DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
50872 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl));
50873 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50874 +       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
50875 +
50876 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
50877 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
50878 +       
50879 +       if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) { 
50880 +               if (ep->stopped) {
50881 +                       if (core_if->en_multiple_tx_fifo)
50882 +                               /* Flush the Tx FIFO */
50883 +                               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
50884 +                       /* Clear the Global IN NP NAK */
50885 +                       dctl.d32 = 0;
50886 +                       dctl.b.cgnpinnak = 1;
50887 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); 
50888 +                       /* Restart the transaction */
50889 +                       if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
50890 +                               restart_transfer(pcd, epnum);
50891 +                       }
50892 +               } else {
50893 +                       /* Restart the transaction */
50894 +                       if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
50895 +                               restart_transfer(pcd, epnum);
50896 +                       }
50897 +                       DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
50898 +               }
50899 +               return;
50900 +       }
50901 +
50902 +       if (core_if->start_predict > 2) {       // NP IN EP
50903 +               core_if->start_predict--;
50904 +               return;
50905 +       }
50906 +
50907 +       core_if->start_predict--;
50908 +       
50909 +       if (core_if->start_predict == 1) {      // All NP IN Ep's disabled now
50910 +
50911 +               predict_nextep_seq(core_if);
50912 +                       
50913 +               /* Update all active IN EP's NextEP field based of nextep_seq[] */
50914 +               for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) {
50915 +                       depctl.d32 =
50916 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50917 +                       if (core_if->nextep_seq[i] != 0xff) {   // Active NP IN EP
50918 +                               depctl.b.nextep = core_if->nextep_seq[i];
50919 +                               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
50920 +                       }
50921 +               }
50922 +               /* Flush Shared NP TxFIFO */
50923 +               dwc_otg_flush_tx_fifo(core_if, 0);
50924 +               /* Rewind buffers */
50925 +               if (!core_if->dma_desc_enable) {                
50926 +                       i = core_if->first_in_nextep_seq;
50927 +                       do {
50928 +                               ep = get_in_ep(pcd, i);
50929 +                               dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
50930 +                               xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count;
50931 +                               if (xfer_size > ep->dwc_ep.maxxfer) 
50932 +                                       xfer_size = ep->dwc_ep.maxxfer;
50933 +                               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50934 +                               if (dieptsiz.b.pktcnt != 0) {
50935 +                                       if (xfer_size == 0) {
50936 +                                               remain_to_transfer = 0;
50937 +                                       } else {
50938 +                                               if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {
50939 +                                                       remain_to_transfer = 
50940 +                                                               dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
50941 +                                               } else {
50942 +                                                       remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket) 
50943 +                                                               + (xfer_size % ep->dwc_ep.maxpacket);
50944 +                                               }
50945 +                                       }
50946 +                                       diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma);
50947 +                                       dieptsiz.b.xfersize = remain_to_transfer;
50948 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32);
50949 +                                       diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer);
50950 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma);
50951 +                               }
50952 +                               i = core_if->nextep_seq[i];
50953 +                       } while (i != core_if->first_in_nextep_seq);
50954 +               } else { // dma_desc_enable
50955 +                               DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__);
50956 +               }
50957 +                               
50958 +               /* Restart transfers in predicted sequences */
50959 +               i = core_if->first_in_nextep_seq;
50960 +               do {
50961 +                       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
50962 +                       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50963 +                       if (dieptsiz.b.pktcnt != 0) {
50964 +                               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50965 +                               depctl.b.epena = 1;
50966 +                               depctl.b.cnak = 1;
50967 +                               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
50968 +                       }
50969 +                       i = core_if->nextep_seq[i];
50970 +               } while (i != core_if->first_in_nextep_seq);
50971 +
50972 +               /* Clear the global non-periodic IN NAK handshake */
50973 +               dctl.d32 = 0;
50974 +               dctl.b.cgnpinnak = 1;
50975 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); 
50976 +                       
50977 +               /* Unmask EP Mismatch interrupt */
50978 +               gintmsk_data.d32 = 0;
50979 +               gintmsk_data.b.epmismatch = 1;
50980 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32);
50981 +               
50982 +               core_if->start_predict = 0;
50983 +
50984 +       } 
50985 +}
50986 +
50987 +/**
50988 + * Handler for the IN EP timeout handshake interrupt.
50989 + */
50990 +static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
50991 +                                            const uint32_t epnum)
50992 +{
50993 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50994 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50995 +
50996 +#ifdef DEBUG
50997 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50998 +       uint32_t num = 0;
50999 +#endif
51000 +       dctl_data_t dctl = {.d32 = 0 };
51001 +       dwc_otg_pcd_ep_t *ep;
51002 +
51003 +       gintmsk_data_t intr_mask = {.d32 = 0 };
51004 +
51005 +       ep = get_in_ep(pcd, epnum);
51006 +
51007 +       /* Disable the NP Tx Fifo Empty Interrrupt */
51008 +       if (!core_if->dma_enable) {
51009 +               intr_mask.b.nptxfempty = 1;
51010 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
51011 +                                intr_mask.d32, 0);
51012 +       }
51013 +       /** @todo NGS Check EP type.
51014 +        * Implement for Periodic EPs */
51015 +       /*
51016 +        * Non-periodic EP
51017 +        */
51018 +       /* Enable the Global IN NAK Effective Interrupt */
51019 +       intr_mask.b.ginnakeff = 1;
51020 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
51021 +
51022 +       /* Set Global IN NAK */
51023 +       dctl.b.sgnpinnak = 1;
51024 +       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
51025 +
51026 +       ep->stopped = 1;
51027 +
51028 +#ifdef DEBUG
51029 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz);
51030 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
51031 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
51032 +#endif
51033 +
51034 +#ifdef DISABLE_PERIODIC_EP
51035 +       /*
51036 +        * Set the NAK bit for this EP to
51037 +        * start the disable process.
51038 +        */
51039 +       diepctl.d32 = 0;
51040 +       diepctl.b.snak = 1;
51041 +       DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
51042 +                        diepctl.d32);
51043 +       ep->disabling = 1;
51044 +       ep->stopped = 1;
51045 +#endif
51046 +}
51047 +
51048 +/**
51049 + * Handler for the IN EP NAK interrupt.
51050 + */
51051 +static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
51052 +                                           const uint32_t epnum)
51053 +{
51054 +       /** @todo implement ISR */
51055 +       dwc_otg_core_if_t *core_if;
51056 +       diepmsk_data_t intr_mask = {.d32 = 0 };
51057 +
51058 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
51059 +       core_if = GET_CORE_IF(pcd);
51060 +       intr_mask.b.nak = 1;
51061 +
51062 +       if (core_if->multiproc_int_enable) {
51063 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51064 +                                diepeachintmsk[epnum], intr_mask.d32, 0);
51065 +       } else {
51066 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk,
51067 +                                intr_mask.d32, 0);
51068 +       }
51069 +
51070 +       return 1;
51071 +}
51072 +
51073 +/**
51074 + * Handler for the OUT EP Babble interrupt.
51075 + */
51076 +static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
51077 +                                               const uint32_t epnum)
51078 +{
51079 +       /** @todo implement ISR */
51080 +       dwc_otg_core_if_t *core_if;
51081 +       doepmsk_data_t intr_mask = {.d32 = 0 };
51082 +
51083 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
51084 +                  "OUT EP Babble");
51085 +       core_if = GET_CORE_IF(pcd);
51086 +       intr_mask.b.babble = 1;
51087 +
51088 +       if (core_if->multiproc_int_enable) {
51089 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51090 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
51091 +       } else {
51092 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51093 +                                intr_mask.d32, 0);
51094 +       }
51095 +
51096 +       return 1;
51097 +}
51098 +
51099 +/**
51100 + * Handler for the OUT EP NAK interrupt.
51101 + */
51102 +static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
51103 +                                            const uint32_t epnum)
51104 +{
51105 +       /** @todo implement ISR */
51106 +       dwc_otg_core_if_t *core_if;
51107 +       doepmsk_data_t intr_mask = {.d32 = 0 };
51108 +
51109 +       DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
51110 +       core_if = GET_CORE_IF(pcd);
51111 +       intr_mask.b.nak = 1;
51112 +
51113 +       if (core_if->multiproc_int_enable) {
51114 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51115 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
51116 +       } else {
51117 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51118 +                                intr_mask.d32, 0);
51119 +       }
51120 +
51121 +       return 1;
51122 +}
51123 +
51124 +/**
51125 + * Handler for the OUT EP NYET interrupt.
51126 + */
51127 +static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
51128 +                                             const uint32_t epnum)
51129 +{
51130 +       /** @todo implement ISR */
51131 +       dwc_otg_core_if_t *core_if;
51132 +       doepmsk_data_t intr_mask = {.d32 = 0 };
51133 +
51134 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
51135 +       core_if = GET_CORE_IF(pcd);
51136 +       intr_mask.b.nyet = 1;
51137 +
51138 +       if (core_if->multiproc_int_enable) {
51139 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51140 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
51141 +       } else {
51142 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51143 +                                intr_mask.d32, 0);
51144 +       }
51145 +
51146 +       return 1;
51147 +}
51148 +
51149 +/**
51150 + * This interrupt indicates that an IN EP has a pending Interrupt.
51151 + * The sequence for handling the IN EP interrupt is shown below:
51152 + * -#  Read the Device All Endpoint Interrupt register
51153 + * -#  Repeat the following for each IN EP interrupt bit set (from
51154 + *             LSB to MSB).
51155 + * -#  Read the Device Endpoint Interrupt (DIEPINTn) register
51156 + * -#  If "Transfer Complete" call the request complete function
51157 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
51158 + * -#  If "AHB Error Interrupt" log error
51159 + * -#  If "Time-out Handshake" log error
51160 + * -#  If "IN Token Received when TxFIFO Empty" write packet to Tx
51161 + *             FIFO.
51162 + * -#  If "IN Token EP Mismatch" (disable, this is handled by EP
51163 + *             Mismatch Interrupt)
51164 + */
51165 +static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
51166 +{
51167 +#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
51168 +do { \
51169 +               diepint_data_t diepint = {.d32=0}; \
51170 +               diepint.b.__intr = 1; \
51171 +               DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
51172 +               diepint.d32); \
51173 +} while (0)
51174 +
51175 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51176 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
51177 +       diepint_data_t diepint = {.d32 = 0 };
51178 +       depctl_data_t depctl = {.d32 = 0 };
51179 +       uint32_t ep_intr;
51180 +       uint32_t epnum = 0;
51181 +       dwc_otg_pcd_ep_t *ep;
51182 +       dwc_ep_t *dwc_ep;
51183 +       gintmsk_data_t intr_mask = {.d32 = 0 };
51184 +
51185 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
51186 +
51187 +       /* Read in the device interrupt bits */
51188 +       ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
51189 +
51190 +       /* Service the Device IN interrupts for each endpoint */
51191 +       while (ep_intr) {
51192 +               if (ep_intr & 0x1) {
51193 +                       uint32_t empty_msk;
51194 +                       /* Get EP pointer */
51195 +                       ep = get_in_ep(pcd, epnum);
51196 +                       dwc_ep = &ep->dwc_ep;
51197 +
51198 +                       depctl.d32 =
51199 +                           DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51200 +                       empty_msk =
51201 +                           DWC_READ_REG32(&dev_if->
51202 +                                          dev_global_regs->dtknqr4_fifoemptymsk);
51203 +
51204 +                       DWC_DEBUGPL(DBG_PCDV,
51205 +                                   "IN EP INTERRUPT - %d\nepmty_msk - %8x  diepctl - %8x\n",
51206 +                                   epnum, empty_msk, depctl.d32);
51207 +
51208 +                       DWC_DEBUGPL(DBG_PCD,
51209 +                                   "EP%d-%s: type=%d, mps=%d\n",
51210 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51211 +                                   dwc_ep->type, dwc_ep->maxpacket);
51212 +
51213 +                       diepint.d32 =
51214 +                           dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
51215 +
51216 +                       DWC_DEBUGPL(DBG_PCDV,
51217 +                                   "EP %d Interrupt Register - 0x%x\n", epnum,
51218 +                                   diepint.d32);
51219 +                       /* Transfer complete */
51220 +                       if (diepint.b.xfercompl) {
51221 +                               /* Disable the NP Tx FIFO Empty
51222 +                                * Interrupt */
51223 +                               if (core_if->en_multiple_tx_fifo == 0) {
51224 +                                       intr_mask.b.nptxfempty = 1;
51225 +                                       DWC_MODIFY_REG32
51226 +                                           (&core_if->core_global_regs->gintmsk,
51227 +                                            intr_mask.d32, 0);
51228 +                               } else {
51229 +                                       /* Disable the Tx FIFO Empty Interrupt for this EP */
51230 +                                       uint32_t fifoemptymsk =
51231 +                                           0x1 << dwc_ep->num;
51232 +                                       DWC_MODIFY_REG32(&core_if->
51233 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
51234 +                                                        fifoemptymsk, 0);
51235 +                               }
51236 +                               /* Clear the bit in DIEPINTn for this interrupt */
51237 +                               CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
51238 +
51239 +                               /* Complete the transfer */
51240 +                               if (epnum == 0) {
51241 +                                       handle_ep0(pcd);
51242 +                               }
51243 +#ifdef DWC_EN_ISOC
51244 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51245 +                                       if (!ep->stopped)
51246 +                                               complete_iso_ep(pcd, ep);
51247 +                               }
51248 +#endif /* DWC_EN_ISOC */
51249 +#ifdef DWC_UTE_PER_IO
51250 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51251 +                                       if (!ep->stopped)
51252 +                                               complete_xiso_ep(ep);
51253 +                               }
51254 +#endif /* DWC_UTE_PER_IO */
51255 +                               else {
51256 +                                       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC && 
51257 +                                                       dwc_ep->bInterval > 1) {
51258 +                                               dwc_ep->frame_num += dwc_ep->bInterval;
51259 +                                               if (dwc_ep->frame_num > 0x3FFF)
51260 +                                               {
51261 +                                                       dwc_ep->frm_overrun = 1;
51262 +                                                       dwc_ep->frame_num &= 0x3FFF;
51263 +                                               } else 
51264 +                                                       dwc_ep->frm_overrun = 0;
51265 +                                       }
51266 +                                       complete_ep(ep);
51267 +                                       if(diepint.b.nak)
51268 +                                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
51269 +                               }
51270 +                       }
51271 +                       /* Endpoint disable      */
51272 +                       if (diepint.b.epdisabled) {
51273 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
51274 +                                           epnum);
51275 +                               handle_in_ep_disable_intr(pcd, epnum);
51276 +
51277 +                               /* Clear the bit in DIEPINTn for this interrupt */
51278 +                               CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
51279 +                       }
51280 +                       /* AHB Error */
51281 +                       if (diepint.b.ahberr) {
51282 +                               DWC_ERROR("EP%d IN AHB Error\n", epnum);
51283 +                               /* Clear the bit in DIEPINTn for this interrupt */
51284 +                               CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
51285 +                       }
51286 +                       /* TimeOUT Handshake (non-ISOC IN EPs) */
51287 +                       if (diepint.b.timeout) {
51288 +                               DWC_ERROR("EP%d IN Time-out\n", epnum);
51289 +                               handle_in_ep_timeout_intr(pcd, epnum);
51290 +
51291 +                               CLEAR_IN_EP_INTR(core_if, epnum, timeout);
51292 +                       }
51293 +                       /** IN Token received with TxF Empty */
51294 +                       if (diepint.b.intktxfemp) {
51295 +                               DWC_DEBUGPL(DBG_ANY,
51296 +                                           "EP%d IN TKN TxFifo Empty\n",
51297 +                                           epnum);
51298 +                               if (!ep->stopped && epnum != 0) {
51299 +
51300 +                                       diepmsk_data_t diepmsk = {.d32 = 0 };
51301 +                                       diepmsk.b.intktxfemp = 1;
51302 +
51303 +                                       if (core_if->multiproc_int_enable) {
51304 +                                               DWC_MODIFY_REG32
51305 +                                                   (&dev_if->dev_global_regs->diepeachintmsk
51306 +                                                    [epnum], diepmsk.d32, 0);
51307 +                                       } else {
51308 +                                               DWC_MODIFY_REG32
51309 +                                                   (&dev_if->dev_global_regs->diepmsk,
51310 +                                                    diepmsk.d32, 0);
51311 +                                       }
51312 +                               } else if (core_if->dma_desc_enable
51313 +                                          && epnum == 0
51314 +                                          && pcd->ep0state ==
51315 +                                          EP0_OUT_STATUS_PHASE) {
51316 +                                       // EP0 IN set STALL
51317 +                                       depctl.d32 =
51318 +                                           DWC_READ_REG32(&dev_if->in_ep_regs
51319 +                                                          [epnum]->diepctl);
51320 +
51321 +                                       /* set the disable and stall bits */
51322 +                                       if (depctl.b.epena) {
51323 +                                               depctl.b.epdis = 1;
51324 +                                       }
51325 +                                       depctl.b.stall = 1;
51326 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs
51327 +                                                       [epnum]->diepctl,
51328 +                                                       depctl.d32);
51329 +                               }
51330 +                               CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
51331 +                       }
51332 +                       /** IN Token Received with EP mismatch */
51333 +                       if (diepint.b.intknepmis) {
51334 +                               DWC_DEBUGPL(DBG_ANY,
51335 +                                           "EP%d IN TKN EP Mismatch\n", epnum);
51336 +                               CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);                           
51337 +                       }
51338 +                       /** IN Endpoint NAK Effective */
51339 +                       if (diepint.b.inepnakeff) {
51340 +                               DWC_DEBUGPL(DBG_ANY,
51341 +                                           "EP%d IN EP NAK Effective\n",
51342 +                                           epnum);
51343 +                               /* Periodic EP */
51344 +                               if (ep->disabling) {
51345 +                                       depctl.d32 = 0;
51346 +                                       depctl.b.snak = 1;
51347 +                                       depctl.b.epdis = 1;
51348 +                                       DWC_MODIFY_REG32(&dev_if->in_ep_regs
51349 +                                                        [epnum]->diepctl,
51350 +                                                        depctl.d32,
51351 +                                                        depctl.d32);
51352 +                               }
51353 +                               CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
51354 +
51355 +                       }
51356 +
51357 +                       /** IN EP Tx FIFO Empty Intr */
51358 +                       if (diepint.b.emptyintr) {
51359 +                               DWC_DEBUGPL(DBG_ANY,
51360 +                                           "EP%d Tx FIFO Empty Intr \n",
51361 +                                           epnum);
51362 +                               write_empty_tx_fifo(pcd, epnum);
51363 +
51364 +                               CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
51365 +
51366 +                       }
51367 +
51368 +                       /** IN EP BNA Intr */
51369 +                       if (diepint.b.bna) {
51370 +                               CLEAR_IN_EP_INTR(core_if, epnum, bna);
51371 +                               if (core_if->dma_desc_enable) {
51372 +#ifdef DWC_EN_ISOC
51373 +                                       if (dwc_ep->type ==
51374 +                                           DWC_OTG_EP_TYPE_ISOC) {
51375 +                                               /*
51376 +                                                * This checking is performed to prevent first "false" BNA
51377 +                                                * handling occuring right after reconnect
51378 +                                                */
51379 +                                               if (dwc_ep->next_frame !=
51380 +                                                   0xffffffff)
51381 +                                                       dwc_otg_pcd_handle_iso_bna(ep);
51382 +                                       } else
51383 +#endif                         /* DWC_EN_ISOC */
51384 +                                       {
51385 +                                               dwc_otg_pcd_handle_noniso_bna(ep);
51386 +                                       }
51387 +                               }
51388 +                       }
51389 +                       /* NAK Interrutp */
51390 +                       if (diepint.b.nak) {
51391 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
51392 +                                           epnum);
51393 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51394 +                                       depctl_data_t depctl;
51395 +                                       if (ep->dwc_ep.frame_num == 0xFFFFFFFF) {
51396 +                                               ep->dwc_ep.frame_num = core_if->frame_num;
51397 +                                               if (ep->dwc_ep.bInterval > 1) {
51398 +                                                       depctl.d32 = 0;
51399 +                                                       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51400 +                                                       if (ep->dwc_ep.frame_num & 0x1) {
51401 +                                                               depctl.b.setd1pid = 1;
51402 +                                                               depctl.b.setd0pid = 0;
51403 +                                                       } else {
51404 +                                                               depctl.b.setd0pid = 1;
51405 +                                                               depctl.b.setd1pid = 0;
51406 +                                                       }
51407 +                                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);
51408 +                                               }
51409 +                                               start_next_request(ep);
51410 +                                       }
51411 +                                       ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;
51412 +                                       if (dwc_ep->frame_num > 0x3FFF) {
51413 +                                               dwc_ep->frm_overrun = 1;
51414 +                                               dwc_ep->frame_num &= 0x3FFF;
51415 +                                       } else 
51416 +                                               dwc_ep->frm_overrun = 0;
51417 +                               }
51418 +
51419 +                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
51420 +                       }
51421 +               }
51422 +               epnum++;
51423 +               ep_intr >>= 1;
51424 +       }
51425 +
51426 +       return 1;
51427 +#undef CLEAR_IN_EP_INTR
51428 +}
51429 +
51430 +/**
51431 + * This interrupt indicates that an OUT EP has a pending Interrupt.
51432 + * The sequence for handling the OUT EP interrupt is shown below:
51433 + * -#  Read the Device All Endpoint Interrupt register
51434 + * -#  Repeat the following for each OUT EP interrupt bit set (from
51435 + *             LSB to MSB).
51436 + * -#  Read the Device Endpoint Interrupt (DOEPINTn) register
51437 + * -#  If "Transfer Complete" call the request complete function
51438 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
51439 + * -#  If "AHB Error Interrupt" log error
51440 + * -#  If "Setup Phase Done" process Setup Packet (See Standard USB
51441 + *             Command Processing)
51442 + */
51443 +static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
51444 +{
51445 +#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
51446 +do { \
51447 +               doepint_data_t doepint = {.d32=0}; \
51448 +               doepint.b.__intr = 1; \
51449 +               DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
51450 +               doepint.d32); \
51451 +} while (0)
51452 +
51453 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51454 +       uint32_t ep_intr;
51455 +       doepint_data_t doepint = {.d32 = 0 };
51456 +       uint32_t epnum = 0;
51457 +       dwc_otg_pcd_ep_t *ep;
51458 +       dwc_ep_t *dwc_ep;
51459 +       dctl_data_t dctl = {.d32 = 0 };
51460 +       gintmsk_data_t gintmsk = {.d32 = 0 };
51461 +
51462 +
51463 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
51464 +
51465 +       /* Read in the device interrupt bits */
51466 +       ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
51467 +
51468 +       while (ep_intr) {
51469 +               if (ep_intr & 0x1) {
51470 +                       /* Get EP pointer */
51471 +                       ep = get_out_ep(pcd, epnum);
51472 +                       dwc_ep = &ep->dwc_ep;
51473 +
51474 +#ifdef VERBOSE
51475 +                       DWC_DEBUGPL(DBG_PCDV,
51476 +                                   "EP%d-%s: type=%d, mps=%d\n",
51477 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51478 +                                   dwc_ep->type, dwc_ep->maxpacket);
51479 +#endif
51480 +                       doepint.d32 =
51481 +                           dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
51482 +                       /* Moved this interrupt upper due to core deffect of asserting
51483 +                        * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */
51484 +                       if (doepint.b.stsphsercvd) {
51485 +                               deptsiz0_data_t deptsiz;
51486 +                               CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
51487 +                               deptsiz.d32 =
51488 +                                   DWC_READ_REG32(&core_if->dev_if->
51489 +                                                  out_ep_regs[0]->doeptsiz);
51490 +                               if (core_if->snpsid >= OTG_CORE_REV_3_00a
51491 +                                   && core_if->dma_enable
51492 +                                   && core_if->dma_desc_enable == 0
51493 +                                   && doepint.b.xfercompl
51494 +                                   && deptsiz.b.xfersize == 24) {
51495 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
51496 +                                                         xfercompl);
51497 +                                       doepint.b.xfercompl = 0;
51498 +                                       ep0_out_start(core_if, pcd);
51499 +                               }
51500 +                               if ((core_if->dma_desc_enable) ||
51501 +                                   (core_if->dma_enable
51502 +                                    && core_if->snpsid >=
51503 +                                    OTG_CORE_REV_3_00a)) {
51504 +                                       do_setup_in_status_phase(pcd);
51505 +                               }
51506 +                       }
51507 +                       /* Transfer complete */
51508 +                       if (doepint.b.xfercompl) {
51509 +
51510 +                               if (epnum == 0) {
51511 +                                       /* Clear the bit in DOEPINTn for this interrupt */
51512 +                                       CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51513 +                                       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
51514 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51515 +                                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint),
51516 +                                                       doepint.d32);
51517 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n",
51518 +                                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl));
51519 +
51520 +                                               if (core_if->snpsid >= OTG_CORE_REV_3_00a
51521 +                                                       && core_if->dma_enable == 0) {
51522 +                                                       doepint_data_t doepint;
51523 +                                                       doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51524 +                                                                                                               out_ep_regs[0]->doepint);
51525 +                                                       if (pcd->ep0state == EP0_IDLE && doepint.b.sr) {
51526 +                                                               CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51527 +                                                               goto exit_xfercompl;
51528 +                                                       }
51529 +                                               }
51530 +                                               /* In case of DDMA  look at SR bit to go to the Data Stage */
51531 +                                               if (core_if->dma_desc_enable) {
51532 +                                                       dev_dma_desc_sts_t status = {.d32 = 0};
51533 +                                                       if (pcd->ep0state == EP0_IDLE) {
51534 +                                                               status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51535 +                                                                                       dev_if->setup_desc_index]->status.d32;
51536 +                                                               if(pcd->data_terminated) {
51537 +                                                                        pcd->data_terminated = 0;
51538 +                                                                        status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51539 +                                                                        dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8);
51540 +                                                               }
51541 +                                                               if (status.b.sr) {
51542 +                                                                       if (doepint.b.setup) {
51543 +                                                                               DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n");
51544 +                                                                               /* Already started data stage, clear setup */
51545 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51546 +                                                                               doepint.b.setup = 0;
51547 +                                                                               handle_ep0(pcd);
51548 +                                                                               /* Prepare for more setup packets */
51549 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51550 +                                                                                       pcd->ep0state == EP0_IN_DATA_PHASE) {
51551 +                                                                                       ep0_out_start(core_if, pcd);
51552 +                                                                               }
51553 +
51554 +                                                                               goto exit_xfercompl;
51555 +                                                                       } else {
51556 +                                                                               /* Prepare for more setup packets */
51557 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51558 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes\n");
51559 +                                                                               ep0_out_start(core_if, pcd);
51560 +                                                                       }
51561 +                                                               }
51562 +                                                       } else {
51563 +                                                               dwc_otg_pcd_request_t *req;
51564 +                                                               dev_dma_desc_sts_t status = {.d32 = 0};
51565 +                                                               diepint_data_t diepint0;
51566 +                                                               diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51567 +                                                                                                                       in_ep_regs[0]->diepint);
51568 +
51569 +                                                               if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) {
51570 +                                                                       DWC_ERROR("EP0 is stalled/disconnected\n");
51571 +                                                               }
51572 +
51573 +                                                               /* Clear IN xfercompl if set */
51574 +                                                               if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE
51575 +                                                                       || pcd->ep0state == EP0_IN_DATA_PHASE)) {
51576 +                                                                       DWC_WRITE_REG32(&core_if->dev_if->
51577 +                                                                               in_ep_regs[0]->diepint, diepint0.d32);
51578 +                                                               }
51579 +
51580 +                                                               status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51581 +                                                                       dev_if->setup_desc_index]->status.d32;
51582 +
51583 +                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len
51584 +                                                                       && (pcd->ep0state == EP0_OUT_DATA_PHASE))
51585 +                                                                       status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51586 +                                                               if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
51587 +                                                                       status.d32 = status.d32 = core_if->dev_if->
51588 +                                                                       out_desc_addr->status.d32;
51589 +
51590 +                                                               if (status.b.sr) {
51591 +                                                                       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51592 +                                                                               DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51593 +                                                                       } else {
51594 +                                                                               DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51595 +                                                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51596 +                                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51597 +                                                                                       pcd->ep0state == EP0_OUT_DATA_PHASE) {
51598 +                                                                                               /* Read arrived setup packet from req->buf */
51599 +                                                                                               dwc_memcpy(&pcd->setup_pkt->req,
51600 +                                                                                                       req->buf + ep->dwc_ep.xfer_count, 8);
51601 +                                                                               }
51602 +                                                                               req->actual = ep->dwc_ep.xfer_count;
51603 +                                                                               dwc_otg_request_done(ep, req, -ECONNRESET);
51604 +                                                                               ep->dwc_ep.start_xfer_buff = 0;
51605 +                                                                               ep->dwc_ep.xfer_buff = 0;
51606 +                                                                               ep->dwc_ep.xfer_len = 0;
51607 +                                                                       }
51608 +                                                                       pcd->ep0state = EP0_IDLE;
51609 +                                                                       if (doepint.b.setup) {
51610 +                                                                               DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51611 +                                                                               /* Data stage started, clear setup */
51612 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51613 +                                                                               doepint.b.setup = 0;
51614 +                                                                               handle_ep0(pcd);
51615 +                                                                               /* Prepare for setup packets if ep0in was enabled*/
51616 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51617 +                                                                                       ep0_out_start(core_if, pcd);
51618 +                                                                               }
51619 +
51620 +                                                                               goto exit_xfercompl;
51621 +                                                                       } else {
51622 +                                                                               /* Prepare for more setup packets */
51623 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51624 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51625 +                                                                               ep0_out_start(core_if, pcd);
51626 +                                                                       }
51627 +                                                               }
51628 +                                                       }
51629 +                                               }
51630 +                                               if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable
51631 +                                                       && core_if->dma_desc_enable == 0) {
51632 +                                                       doepint_data_t doepint_temp = {.d32 = 0};
51633 +                                                       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
51634 +                                                       doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51635 +                                                                                                                       out_ep_regs[ep->dwc_ep.num]->doepint);
51636 +                                                       doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if->
51637 +                                                                                                                       out_ep_regs[ep->dwc_ep.num]->doeptsiz);
51638 +                                                       if (pcd->ep0state == EP0_IDLE) {
51639 +                                                               if (doepint_temp.b.sr) {
51640 +                                                                       CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51641 +                                                               }
51642 +                                                                       doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51643 +                                                                                                                                       out_ep_regs[0]->doepint);
51644 +                                                                       if (doeptsize0.b.supcnt == 3) {
51645 +                                                                               DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n");
51646 +                                                                               ep->dwc_ep.stp_rollover = 1;
51647 +                                                                       }
51648 +                                                                       if (doepint.b.setup) {
51649 +retry:
51650 +                                                                               /* Already started data stage, clear setup */
51651 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51652 +                                                                               doepint.b.setup = 0;
51653 +                                                                               handle_ep0(pcd);
51654 +                                                                               ep->dwc_ep.stp_rollover = 0;
51655 +                                                                               /* Prepare for more setup packets */
51656 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51657 +                                                                                       pcd->ep0state == EP0_IN_DATA_PHASE) {
51658 +                                                                                       ep0_out_start(core_if, pcd);
51659 +                                                                               }
51660 +                                                                               goto exit_xfercompl;
51661 +                                                                       } else {
51662 +                                                                               /* Prepare for more setup packets */
51663 +                                                                               DWC_DEBUGPL(DBG_ANY,
51664 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes\n");
51665 +                                                                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51666 +                                                                                                                                       out_ep_regs[0]->doepint);
51667 +                                                                               if(doepint.b.setup)
51668 +                                                                                       goto retry;
51669 +                                                                               ep0_out_start(core_if, pcd);
51670 +                                                                       }
51671 +                                                       } else {
51672 +                                                               dwc_otg_pcd_request_t *req;
51673 +                                                               diepint_data_t diepint0 = {.d32 = 0};
51674 +                                                               doepint_data_t doepint_temp = {.d32 = 0};
51675 +                                                               depctl_data_t diepctl0;
51676 +                                                               diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51677 +                                                                                                                               in_ep_regs[0]->diepint);
51678 +                                                               diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if->
51679 +                                                                                                                               in_ep_regs[0]->diepctl);
51680 +
51681 +                                                               if (pcd->ep0state == EP0_IN_DATA_PHASE
51682 +                                                                       || pcd->ep0state == EP0_IN_STATUS_PHASE) {
51683 +                                                                       if (diepint0.b.xfercompl) {
51684 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51685 +                                                                                       in_ep_regs[0]->diepint, diepint0.d32);
51686 +                                                                       }
51687 +                                                                       if (diepctl0.b.epena) {
51688 +                                                                               diepint_data_t diepint = {.d32 = 0};
51689 +                                                                               diepctl0.b.snak = 1;
51690 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51691 +                                                                                                               in_ep_regs[0]->diepctl, diepctl0.d32);
51692 +                                                                               do {
51693 +                                                                                       dwc_udelay(10);
51694 +                                                                                       diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51695 +                                                                                               in_ep_regs[0]->diepint);
51696 +                                                                               } while (!diepint.b.inepnakeff);
51697 +                                                                               diepint.b.inepnakeff = 1;
51698 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51699 +                                                                                       in_ep_regs[0]->diepint, diepint.d32);
51700 +                                                                               diepctl0.d32 = 0;
51701 +                                                                               diepctl0.b.epdis = 1;
51702 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl,
51703 +                                                                                                               diepctl0.d32);
51704 +                                                                               do {
51705 +                                                                                       dwc_udelay(10);
51706 +                                                                                       diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51707 +                                                                                               in_ep_regs[0]->diepint);
51708 +                                                                               } while (!diepint.b.epdisabled);
51709 +                                                                               diepint.b.epdisabled = 1;
51710 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint,
51711 +                                                                                                                       diepint.d32);
51712 +                                                                       }
51713 +                                                               }
51714 +                                                               doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51715 +                                                                                                                               out_ep_regs[ep->dwc_ep.num]->doepint);
51716 +                                                               if (doepint_temp.b.sr) {
51717 +                                                                       CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51718 +                                                                       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51719 +                                                                               DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51720 +                                                                       } else {
51721 +                                                                               DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51722 +                                                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51723 +                                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51724 +                                                                                       pcd->ep0state == EP0_OUT_DATA_PHASE) {
51725 +                                                                                               /* Read arrived setup packet from req->buf */
51726 +                                                                                               dwc_memcpy(&pcd->setup_pkt->req,
51727 +                                                                                                       req->buf + ep->dwc_ep.xfer_count, 8);
51728 +                                                                               }
51729 +                                                                               req->actual = ep->dwc_ep.xfer_count;
51730 +                                                                               dwc_otg_request_done(ep, req, -ECONNRESET);
51731 +                                                                               ep->dwc_ep.start_xfer_buff = 0;
51732 +                                                                               ep->dwc_ep.xfer_buff = 0;
51733 +                                                                               ep->dwc_ep.xfer_len = 0;
51734 +                                                                       }
51735 +                                                                       pcd->ep0state = EP0_IDLE;
51736 +                                                                       if (doepint.b.setup) {
51737 +                                                                               DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51738 +                                                                               /* Data stage started, clear setup */
51739 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51740 +                                                                               doepint.b.setup = 0;
51741 +                                                                               handle_ep0(pcd);
51742 +                                                                               /* Prepare for setup packets if ep0in was enabled*/
51743 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51744 +                                                                                       ep0_out_start(core_if, pcd);
51745 +                                                                               }
51746 +                                                                               goto exit_xfercompl;
51747 +                                                                       } else {
51748 +                                                                               /* Prepare for more setup packets */
51749 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51750 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51751 +                                                                               ep0_out_start(core_if, pcd);
51752 +                                                                       }
51753 +                                                               }
51754 +                                                       }
51755 +                                               }
51756 +                                               if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE)
51757 +                                                       handle_ep0(pcd);
51758 +exit_xfercompl:
51759 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51760 +                                                       dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32);
51761 +                                       } else {
51762 +                                       if (core_if->dma_desc_enable == 0
51763 +                                           || pcd->ep0state != EP0_IDLE)
51764 +                                               handle_ep0(pcd);
51765 +                                       }
51766 +#ifdef DWC_EN_ISOC
51767 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51768 +                                       if (doepint.b.pktdrpsts == 0) {
51769 +                                               /* Clear the bit in DOEPINTn for this interrupt */
51770 +                                               CLEAR_OUT_EP_INTR(core_if,
51771 +                                                                 epnum,
51772 +                                                                 xfercompl);
51773 +                                               complete_iso_ep(pcd, ep);
51774 +                                       } else {
51775 +
51776 +                                               doepint_data_t doepint = {.d32 = 0 };
51777 +                                               doepint.b.xfercompl = 1;
51778 +                                               doepint.b.pktdrpsts = 1;
51779 +                                               DWC_WRITE_REG32
51780 +                                                   (&core_if->dev_if->out_ep_regs
51781 +                                                    [epnum]->doepint,
51782 +                                                    doepint.d32);
51783 +                                               if (handle_iso_out_pkt_dropped
51784 +                                                   (core_if, dwc_ep)) {
51785 +                                                       complete_iso_ep(pcd,
51786 +                                                                       ep);
51787 +                                               }
51788 +                                       }
51789 +#endif /* DWC_EN_ISOC */
51790 +#ifdef DWC_UTE_PER_IO
51791 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51792 +                                       CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51793 +                                       if (!ep->stopped)
51794 +                                               complete_xiso_ep(ep);
51795 +#endif /* DWC_UTE_PER_IO */
51796 +                               } else {
51797 +                                       /* Clear the bit in DOEPINTn for this interrupt */
51798 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
51799 +                                                         xfercompl);
51800 +
51801 +                                       if (core_if->core_params->dev_out_nak) {
51802 +                                               DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]);
51803 +                                               pcd->core_if->ep_xfer_info[epnum].state = 0;
51804 +#ifdef DEBUG
51805 +                                               print_memory_payload(pcd, dwc_ep);
51806 +#endif
51807 +                                       }
51808 +                                       complete_ep(ep);                                                
51809 +                               }
51810 +
51811 +                       }
51812 +
51813 +                       /* Endpoint disable      */
51814 +                       if (doepint.b.epdisabled) {
51815 +
51816 +                               /* Clear the bit in DOEPINTn for this interrupt */
51817 +                               CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
51818 +                               if (core_if->core_params->dev_out_nak) {
51819 +#ifdef DEBUG
51820 +                                       print_memory_payload(pcd, dwc_ep);
51821 +#endif
51822 +                                       /* In case of timeout condition */
51823 +                                       if (core_if->ep_xfer_info[epnum].state == 2) {
51824 +                                               dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51825 +                                                                               dev_global_regs->dctl);
51826 +                                               dctl.b.cgoutnak = 1;
51827 +                                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51828 +                                                                                                                               dctl.d32);
51829 +                                               /* Unmask goutnakeff interrupt which was masked
51830 +                                                * during handle nak out interrupt */
51831 +                                               gintmsk.b.goutnakeff = 1;
51832 +                                               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
51833 +                                                                                                                               0, gintmsk.d32);
51834 +                                       
51835 +                                               complete_ep(ep);
51836 +                                       }
51837 +                               }
51838 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
51839 +                               {
51840 +                                       dctl_data_t dctl;
51841 +                                       gintmsk_data_t intr_mask = {.d32 = 0};
51842 +                                       dwc_otg_pcd_request_t *req = 0;
51843 +
51844 +                                       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51845 +                                               dev_global_regs->dctl);
51846 +                                       dctl.b.cgoutnak = 1;
51847 +                                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51848 +                                               dctl.d32);
51849 +
51850 +                                       intr_mask.d32 = 0;
51851 +                                       intr_mask.b.incomplisoout = 1;     
51852 +
51853 +                                       /* Get any pending requests */
51854 +                                       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51855 +                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51856 +                                               if (!req) {
51857 +                                                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
51858 +                                               } else {
51859 +                                                       dwc_otg_request_done(ep, req, 0);
51860 +                                                       start_next_request(ep);
51861 +                                               }
51862 +                                       } else {
51863 +                                               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
51864 +                                       }
51865 +                               }
51866 +                       }
51867 +                       /* AHB Error */
51868 +                       if (doepint.b.ahberr) {
51869 +                               DWC_ERROR("EP%d OUT AHB Error\n", epnum);
51870 +                               DWC_ERROR("EP%d DEPDMA=0x%08x \n",
51871 +                                         epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma);
51872 +                               CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
51873 +                       }
51874 +                       /* Setup Phase Done (contorl EPs) */
51875 +                       if (doepint.b.setup) {
51876 +#ifdef DEBUG_EP0
51877 +                               DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum);
51878 +#endif
51879 +                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51880 +
51881 +                               handle_ep0(pcd);
51882 +                       }
51883 +
51884 +                       /** OUT EP BNA Intr */
51885 +                       if (doepint.b.bna) {
51886 +                               CLEAR_OUT_EP_INTR(core_if, epnum, bna);
51887 +                               if (core_if->dma_desc_enable) {
51888 +#ifdef DWC_EN_ISOC
51889 +                                       if (dwc_ep->type ==
51890 +                                           DWC_OTG_EP_TYPE_ISOC) {
51891 +                                               /*
51892 +                                                * This checking is performed to prevent first "false" BNA
51893 +                                                * handling occuring right after reconnect
51894 +                                                */
51895 +                                               if (dwc_ep->next_frame !=
51896 +                                                   0xffffffff)
51897 +                                                       dwc_otg_pcd_handle_iso_bna(ep);
51898 +                                       } else
51899 +#endif                         /* DWC_EN_ISOC */
51900 +                                       {
51901 +                                               dwc_otg_pcd_handle_noniso_bna(ep);
51902 +                                       }
51903 +                               }
51904 +                       }
51905 +                       /* Babble Interrupt */
51906 +                       if (doepint.b.babble) {
51907 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
51908 +                                           epnum);
51909 +                               handle_out_ep_babble_intr(pcd, epnum);
51910 +
51911 +                               CLEAR_OUT_EP_INTR(core_if, epnum, babble);
51912 +                       }
51913 +                       if (doepint.b.outtknepdis) {
51914 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \
51915 +                                       disabled\n",epnum);
51916 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51917 +                                       doepmsk_data_t doepmsk = {.d32 = 0};
51918 +                                       ep->dwc_ep.frame_num = core_if->frame_num;
51919 +                                       if (ep->dwc_ep.bInterval > 1) {
51920 +                                               depctl_data_t depctl;
51921 +                                               depctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51922 +                                                                                                       out_ep_regs[epnum]->doepctl);
51923 +                                               if (ep->dwc_ep.frame_num & 0x1) {
51924 +                                                       depctl.b.setd1pid = 1;
51925 +                                                       depctl.b.setd0pid = 0;
51926 +                                               } else {
51927 +                                                       depctl.b.setd0pid = 1;
51928 +                                                       depctl.b.setd1pid = 0;
51929 +                                               }
51930 +                                               DWC_WRITE_REG32(&core_if->dev_if->
51931 +                                                                               out_ep_regs[epnum]->doepctl, depctl.d32);
51932 +                                       }
51933 +                                       start_next_request(ep);
51934 +                                       doepmsk.b.outtknepdis = 1;
51935 +                                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 
51936 +                                                                doepmsk.d32, 0);
51937 +                               }
51938 +                               CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
51939 +                       }
51940 +                       
51941 +                       /* NAK Interrutp */
51942 +                       if (doepint.b.nak) {
51943 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
51944 +                               handle_out_ep_nak_intr(pcd, epnum);
51945 +
51946 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nak);
51947 +                       }
51948 +                       /* NYET Interrutp */
51949 +                       if (doepint.b.nyet) {
51950 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
51951 +                               handle_out_ep_nyet_intr(pcd, epnum);
51952 +
51953 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
51954 +                       }
51955 +               }
51956 +
51957 +               epnum++;
51958 +               ep_intr >>= 1;
51959 +       }
51960 +
51961 +       return 1;
51962 +
51963 +#undef CLEAR_OUT_EP_INTR
51964 +}
51965 +static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)
51966 +{
51967 +       int retval = 0;
51968 +       if(!frm_overrun && curr_fr >= trgt_fr) 
51969 +               retval = 1;
51970 +       else if (frm_overrun
51971 +                && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2)))
51972 +               retval = 1;
51973 +       return retval;
51974 +}
51975 +/**
51976 + * Incomplete ISO IN Transfer Interrupt.
51977 + * This interrupt indicates one of the following conditions occurred
51978 + * while transmitting an ISOC transaction.
51979 + * - Corrupted IN Token for ISOC EP.
51980 + * - Packet not complete in FIFO.
51981 + * The follow actions will be taken:
51982 + *     -#      Determine the EP
51983 + *     -#      Set incomplete flag in dwc_ep structure
51984 + *     -#      Disable EP; when "Endpoint Disabled" interrupt is received
51985 + *             Flush FIFO
51986 + */
51987 +int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
51988 +{
51989 +       gintsts_data_t gintsts;
51990 +
51991 +#ifdef DWC_EN_ISOC
51992 +       dwc_otg_dev_if_t *dev_if;
51993 +       deptsiz_data_t deptsiz = {.d32 = 0 };
51994 +       depctl_data_t depctl = {.d32 = 0 };
51995 +       dsts_data_t dsts = {.d32 = 0 };
51996 +       dwc_ep_t *dwc_ep;
51997 +       int i;
51998 +
51999 +       dev_if = GET_CORE_IF(pcd)->dev_if;
52000 +
52001 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
52002 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
52003 +               if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
52004 +                       deptsiz.d32 =
52005 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
52006 +                       depctl.d32 =
52007 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52008 +
52009 +                       if (depctl.b.epdis && deptsiz.d32) {
52010 +                               set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
52011 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
52012 +                                       dwc_ep->cur_pkt = 0;
52013 +                                       dwc_ep->proc_buf_num =
52014 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
52015 +
52016 +                                       if (dwc_ep->proc_buf_num) {
52017 +                                               dwc_ep->cur_pkt_addr =
52018 +                                                   dwc_ep->xfer_buff1;
52019 +                                               dwc_ep->cur_pkt_dma_addr =
52020 +                                                   dwc_ep->dma_addr1;
52021 +                                       } else {
52022 +                                               dwc_ep->cur_pkt_addr =
52023 +                                                   dwc_ep->xfer_buff0;
52024 +                                               dwc_ep->cur_pkt_dma_addr =
52025 +                                                   dwc_ep->dma_addr0;
52026 +                                       }
52027 +
52028 +                               }
52029 +
52030 +                               dsts.d32 =
52031 +                                   DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
52032 +                                                  dev_global_regs->dsts);
52033 +                               dwc_ep->next_frame = dsts.b.soffn;
52034 +
52035 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
52036 +                                                                 (pcd),
52037 +                                                                 dwc_ep);
52038 +                       }
52039 +               }
52040 +       }
52041 +
52042 +#else
52043 +       depctl_data_t depctl = {.d32 = 0 };
52044 +       dwc_ep_t *dwc_ep;
52045 +       dwc_otg_dev_if_t *dev_if;
52046 +       int i;
52047 +       dev_if = GET_CORE_IF(pcd)->dev_if;
52048 +
52049 +       DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");
52050 +       
52051 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
52052 +               dwc_ep = &pcd->in_ep[i-1].dwc_ep;
52053 +               depctl.d32 =
52054 +                       DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52055 +               if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
52056 +                       if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num, 
52057 +                                                       dwc_ep->frm_overrun))
52058 +                       {
52059 +                               depctl.d32 =
52060 +                                       DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52061 +                               depctl.b.snak = 1;
52062 +                               depctl.b.epdis = 1;
52063 +                               DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);
52064 +                       }
52065 +               }
52066 +       }
52067 +
52068 +       /*intr_mask.b.incomplisoin = 1;
52069 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52070 +                        intr_mask.d32, 0);      */
52071 +#endif                         //DWC_EN_ISOC
52072 +
52073 +       /* Clear interrupt */
52074 +       gintsts.d32 = 0;
52075 +       gintsts.b.incomplisoin = 1;
52076 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52077 +                       gintsts.d32);
52078 +
52079 +       return 1;
52080 +}
52081 +
52082 +/**
52083 + * Incomplete ISO OUT Transfer Interrupt.
52084 + *
52085 + * This interrupt indicates that the core has dropped an ISO OUT
52086 + * packet. The following conditions can be the cause:
52087 + * - FIFO Full, the entire packet would not fit in the FIFO.
52088 + * - CRC Error
52089 + * - Corrupted Token
52090 + * The follow actions will be taken:
52091 + *     -#      Determine the EP
52092 + *     -#      Set incomplete flag in dwc_ep structure
52093 + *     -#      Read any data from the FIFO
52094 + *     -#      Disable EP. When "Endpoint Disabled" interrupt is received
52095 + *             re-enable EP.
52096 + */
52097 +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
52098 +{
52099 +
52100 +       gintsts_data_t gintsts;
52101 +
52102 +#ifdef DWC_EN_ISOC
52103 +       dwc_otg_dev_if_t *dev_if;
52104 +       deptsiz_data_t deptsiz = {.d32 = 0 };
52105 +       depctl_data_t depctl = {.d32 = 0 };
52106 +       dsts_data_t dsts = {.d32 = 0 };
52107 +       dwc_ep_t *dwc_ep;
52108 +       int i;
52109 +
52110 +       dev_if = GET_CORE_IF(pcd)->dev_if;
52111 +
52112 +       for (i = 1; i <= dev_if->num_out_eps; ++i) {
52113 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
52114 +               if (pcd->out_ep[i].dwc_ep.active &&
52115 +                   pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
52116 +                       deptsiz.d32 =
52117 +                           DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz);
52118 +                       depctl.d32 =
52119 +                           DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
52120 +
52121 +                       if (depctl.b.epdis && deptsiz.d32) {
52122 +                               set_current_pkt_info(GET_CORE_IF(pcd),
52123 +                                                    &pcd->out_ep[i].dwc_ep);
52124 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
52125 +                                       dwc_ep->cur_pkt = 0;
52126 +                                       dwc_ep->proc_buf_num =
52127 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
52128 +
52129 +                                       if (dwc_ep->proc_buf_num) {
52130 +                                               dwc_ep->cur_pkt_addr =
52131 +                                                   dwc_ep->xfer_buff1;
52132 +                                               dwc_ep->cur_pkt_dma_addr =
52133 +                                                   dwc_ep->dma_addr1;
52134 +                                       } else {
52135 +                                               dwc_ep->cur_pkt_addr =
52136 +                                                   dwc_ep->xfer_buff0;
52137 +                                               dwc_ep->cur_pkt_dma_addr =
52138 +                                                   dwc_ep->dma_addr0;
52139 +                                       }
52140 +
52141 +                               }
52142 +
52143 +                               dsts.d32 =
52144 +                                   DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
52145 +                                                  dev_global_regs->dsts);
52146 +                               dwc_ep->next_frame = dsts.b.soffn;
52147 +
52148 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
52149 +                                                                 (pcd),
52150 +                                                                 dwc_ep);
52151 +                       }
52152 +               }
52153 +       }
52154 +#else
52155 +       /** @todo implement ISR */
52156 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52157 +       dwc_otg_core_if_t *core_if;
52158 +       deptsiz_data_t deptsiz = {.d32 = 0 };
52159 +       depctl_data_t depctl = {.d32 = 0 };
52160 +       dctl_data_t dctl = {.d32 = 0 };
52161 +       dwc_ep_t *dwc_ep = NULL;
52162 +       int i;
52163 +       core_if = GET_CORE_IF(pcd);
52164 +
52165 +       for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
52166 +               dwc_ep = &pcd->out_ep[i].dwc_ep;
52167 +               depctl.d32 =
52168 +                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
52169 +               if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {
52170 +                       core_if->dev_if->isoc_ep = dwc_ep;      
52171 +                       deptsiz.d32 =
52172 +                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);
52173 +                               break;
52174 +               }
52175 +       }
52176 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
52177 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
52178 +       intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
52179 +
52180 +       if (!intr_mask.b.goutnakeff) {
52181 +               /* Unmask it */
52182 +               intr_mask.b.goutnakeff = 1;
52183 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);
52184 +       }
52185 +       if (!gintsts.b.goutnakeff) {
52186 +               dctl.b.sgoutnak = 1;
52187 +       }
52188 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
52189 +
52190 +       depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
52191 +       if (depctl.b.epena) {
52192 +               depctl.b.epdis = 1;
52193 +               depctl.b.snak = 1;
52194 +       }
52195 +       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);
52196 +
52197 +       intr_mask.d32 = 0;
52198 +       intr_mask.b.incomplisoout = 1;
52199 +               
52200 +#endif /* DWC_EN_ISOC */
52201 +
52202 +       /* Clear interrupt */
52203 +       gintsts.d32 = 0;
52204 +       gintsts.b.incomplisoout = 1;
52205 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52206 +                       gintsts.d32);
52207 +
52208 +       return 1;
52209 +}
52210 +
52211 +/**
52212 + * This function handles the Global IN NAK Effective interrupt.
52213 + *
52214 + */
52215 +int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
52216 +{
52217 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52218 +       depctl_data_t diepctl = {.d32 = 0 };
52219 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52220 +       gintsts_data_t gintsts;
52221 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52222 +       int i;
52223 +
52224 +       DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
52225 +
52226 +       /* Disable all active IN EPs */
52227 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
52228 +               diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52229 +               if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {
52230 +                       if (core_if->start_predict > 0)
52231 +                               core_if->start_predict++;
52232 +                       diepctl.b.epdis = 1;
52233 +                       diepctl.b.snak = 1;
52234 +                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32);
52235 +               }                                               
52236 +       }
52237 +       
52238 +
52239 +       /* Disable the Global IN NAK Effective Interrupt */
52240 +       intr_mask.b.ginnakeff = 1;
52241 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52242 +                        intr_mask.d32, 0);
52243 +
52244 +       /* Clear interrupt */
52245 +       gintsts.d32 = 0;
52246 +       gintsts.b.ginnakeff = 1;
52247 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52248 +                       gintsts.d32);
52249 +
52250 +       return 1;
52251 +}
52252 +
52253 +/**
52254 + * OUT NAK Effective.
52255 + *
52256 + */
52257 +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
52258 +{
52259 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52260 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52261 +       gintsts_data_t gintsts;
52262 +       depctl_data_t doepctl;
52263 +       int i;
52264 +
52265 +       /* Disable the Global OUT NAK Effective Interrupt */
52266 +       intr_mask.b.goutnakeff = 1;
52267 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52268 +               intr_mask.d32, 0);
52269 +       
52270 +       /* If DEV OUT NAK enabled*/
52271 +       if (pcd->core_if->core_params->dev_out_nak) {
52272 +               /* Run over all out endpoints to determine the ep number on
52273 +                * which the timeout has happened 
52274 +                */
52275 +               for (i = 0; i <= dev_if->num_out_eps; i++) {
52276 +                       if ( pcd->core_if->ep_xfer_info[i].state == 2 )
52277 +                               break;
52278 +               }
52279 +               if (i > dev_if->num_out_eps) {
52280 +                       dctl_data_t dctl;
52281 +                       dctl.d32 =
52282 +                           DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
52283 +                       dctl.b.cgoutnak = 1;
52284 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,
52285 +                               dctl.d32);
52286 +                       goto out;
52287 +               }
52288 +
52289 +               /* Disable the endpoint */
52290 +               doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
52291 +               if (doepctl.b.epena) {
52292 +                       doepctl.b.epdis = 1;
52293 +                       doepctl.b.snak = 1;
52294 +               }
52295 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
52296 +               return 1;
52297 +       }
52298 +       /* We come here from Incomplete ISO OUT handler */
52299 +       if (dev_if->isoc_ep) {
52300 +               dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;
52301 +               uint32_t epnum = dwc_ep->num;
52302 +               doepint_data_t doepint;
52303 +               doepint.d32 =
52304 +                   DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);
52305 +               dev_if->isoc_ep = NULL;
52306 +               doepctl.d32 =
52307 +                   DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);
52308 +               DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);
52309 +               if (doepctl.b.epena) {
52310 +                       doepctl.b.epdis = 1;
52311 +                       doepctl.b.snak = 1;
52312 +               }
52313 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl,
52314 +                               doepctl.d32);
52315 +               return 1;
52316 +       } else
52317 +               DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
52318 +                          "Global OUT NAK Effective\n");
52319 +       
52320 +out:
52321 +       /* Clear interrupt */
52322 +       gintsts.d32 = 0;
52323 +       gintsts.b.goutnakeff = 1;
52324 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52325 +                       gintsts.d32);
52326 +
52327 +       return 1;
52328 +}
52329 +
52330 +/**
52331 + * PCD interrupt handler.
52332 + *
52333 + * The PCD handles the device interrupts.  Many conditions can cause a
52334 + * device interrupt. When an interrupt occurs, the device interrupt
52335 + * service routine determines the cause of the interrupt and
52336 + * dispatches handling to the appropriate function. These interrupt
52337 + * handling functions are described below.
52338 + *
52339 + * All interrupt registers are processed from LSB to MSB.
52340 + *
52341 + */
52342 +int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
52343 +{
52344 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52345 +#ifdef VERBOSE
52346 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
52347 +#endif
52348 +       gintsts_data_t gintr_status;
52349 +       int32_t retval = 0;
52350 +
52351 +       /* Exit from ISR if core is hibernated */
52352 +       if (core_if->hibernation_suspend == 1) {
52353 +               return retval;
52354 +       }
52355 +#ifdef VERBOSE
52356 +       DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x  gintmsk=%08x\n",
52357 +                   __func__,
52358 +                   DWC_READ_REG32(&global_regs->gintsts),
52359 +                   DWC_READ_REG32(&global_regs->gintmsk));
52360 +#endif
52361 +
52362 +       if (dwc_otg_is_device_mode(core_if)) {
52363 +               DWC_SPINLOCK(pcd->lock);
52364 +#ifdef VERBOSE
52365 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x  gintmsk=%08x\n",
52366 +                           __func__,
52367 +                           DWC_READ_REG32(&global_regs->gintsts),
52368 +                           DWC_READ_REG32(&global_regs->gintmsk));
52369 +#endif
52370 +
52371 +               gintr_status.d32 = dwc_otg_read_core_intr(core_if);
52372 +
52373 +               DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
52374 +                           __func__, gintr_status.d32);
52375 +
52376 +               if (gintr_status.b.sofintr) {
52377 +                       retval |= dwc_otg_pcd_handle_sof_intr(pcd);
52378 +               }
52379 +               if (gintr_status.b.rxstsqlvl) {
52380 +                       retval |=
52381 +                           dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
52382 +               }
52383 +               if (gintr_status.b.nptxfempty) {
52384 +                       retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
52385 +               }
52386 +               if (gintr_status.b.goutnakeff) {
52387 +                       retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
52388 +               }
52389 +               if (gintr_status.b.i2cintr) {
52390 +                       retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
52391 +               }
52392 +               if (gintr_status.b.erlysuspend) {
52393 +                       retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
52394 +               }
52395 +               if (gintr_status.b.usbreset) {
52396 +                       retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
52397 +               }
52398 +               if (gintr_status.b.enumdone) {
52399 +                       retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
52400 +               }
52401 +               if (gintr_status.b.isooutdrop) {
52402 +                       retval |=
52403 +                           dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
52404 +                           (pcd);
52405 +               }
52406 +               if (gintr_status.b.eopframe) {
52407 +                       retval |=
52408 +                           dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
52409 +               }
52410 +               if (gintr_status.b.inepint) {
52411 +                       if (!core_if->multiproc_int_enable) {
52412 +                               retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52413 +                       }
52414 +               }
52415 +               if (gintr_status.b.outepintr) {
52416 +                       if (!core_if->multiproc_int_enable) {
52417 +                               retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52418 +                       }
52419 +               }
52420 +               if (gintr_status.b.epmismatch) {
52421 +                       retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd);
52422 +               }
52423 +               if (gintr_status.b.fetsusp) {
52424 +                       retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd);
52425 +               }
52426 +               if (gintr_status.b.ginnakeff) {
52427 +                       retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
52428 +               }
52429 +               if (gintr_status.b.incomplisoin) {
52430 +                       retval |=
52431 +                           dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
52432 +               }
52433 +               if (gintr_status.b.incomplisoout) {
52434 +                       retval |=
52435 +                           dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
52436 +               }
52437 +
52438 +               /* In MPI mode Device Endpoints interrupts are asserted
52439 +                * without setting outepintr and inepint bits set, so these
52440 +                * Interrupt handlers are called without checking these bit-fields
52441 +                */
52442 +               if (core_if->multiproc_int_enable) {
52443 +                       retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52444 +                       retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52445 +               }
52446 +#ifdef VERBOSE
52447 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
52448 +                           DWC_READ_REG32(&global_regs->gintsts));
52449 +#endif
52450 +               DWC_SPINUNLOCK(pcd->lock);
52451 +       }
52452 +       return retval;
52453 +}
52454 +
52455 +#endif /* DWC_HOST_ONLY */
52456 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
52457 new file mode 100644
52458 index 0000000..a591d89
52459 --- /dev/null
52460 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
52461 @@ -0,0 +1,1358 @@
52462 + /* ==========================================================================
52463 +  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
52464 +  * $Revision: #21 $
52465 +  * $Date: 2012/08/10 $
52466 +  * $Change: 2047372 $
52467 +  *
52468 +  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
52469 +  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
52470 +  * otherwise expressly agreed to in writing between Synopsys and you.
52471 +  *
52472 +  * The Software IS NOT an item of Licensed Software or Licensed Product under
52473 +  * any End User Software License Agreement or Agreement for Licensed Product
52474 +  * with Synopsys or any supplement thereto. You are permitted to use and
52475 +  * redistribute this Software in source and binary forms, with or without
52476 +  * modification, provided that redistributions of source code must retain this
52477 +  * notice. You may not view, use, disclose, copy or distribute this file or
52478 +  * any information contained herein except pursuant to this license grant from
52479 +  * Synopsys. If you do not agree with this notice, including the disclaimer
52480 +  * below, then you are not authorized to use the Software.
52481 +  *
52482 +  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
52483 +  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52484 +  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52485 +  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
52486 +  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52487 +  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
52488 +  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
52489 +  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52490 +  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52491 +  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
52492 +  * DAMAGE.
52493 +  * ========================================================================== */
52494 +#ifndef DWC_HOST_ONLY
52495 +
52496 +/** @file
52497 + * This file implements the Peripheral Controller Driver.
52498 + *
52499 + * The Peripheral Controller Driver (PCD) is responsible for
52500 + * translating requests from the Function Driver into the appropriate
52501 + * actions on the DWC_otg controller. It isolates the Function Driver
52502 + * from the specifics of the controller by providing an API to the
52503 + * Function Driver.
52504 + *
52505 + * The Peripheral Controller Driver for Linux will implement the
52506 + * Gadget API, so that the existing Gadget drivers can be used.
52507 + * (Gadget Driver is the Linux terminology for a Function Driver.)
52508 + *
52509 + * The Linux Gadget API is defined in the header file
52510 + * <code><linux/usb_gadget.h></code>.  The USB EP operations API is
52511 + * defined in the structure <code>usb_ep_ops</code> and the USB
52512 + * Controller API is defined in the structure
52513 + * <code>usb_gadget_ops</code>.
52514 + *
52515 + */
52516 +
52517 +#include "dwc_otg_os_dep.h"
52518 +#include "dwc_otg_pcd_if.h"
52519 +#include "dwc_otg_pcd.h"
52520 +#include "dwc_otg_driver.h"
52521 +#include "dwc_otg_dbg.h"
52522 +
52523 +static struct gadget_wrapper {
52524 +       dwc_otg_pcd_t *pcd;
52525 +
52526 +       struct usb_gadget gadget;
52527 +       struct usb_gadget_driver *driver;
52528 +
52529 +       struct usb_ep ep0;
52530 +       struct usb_ep in_ep[16];
52531 +       struct usb_ep out_ep[16];
52532 +
52533 +} *gadget_wrapper;
52534 +
52535 +/* Display the contents of the buffer */
52536 +extern void dump_msg(const u8 * buf, unsigned int length);
52537 +/**
52538 + * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case
52539 + * if the endpoint is not found
52540 + */
52541 +static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
52542 +{
52543 +       int i;
52544 +       if (pcd->ep0.priv == handle) {
52545 +               return &pcd->ep0;
52546 +       }
52547 +
52548 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
52549 +               if (pcd->in_ep[i].priv == handle)
52550 +                       return &pcd->in_ep[i];
52551 +               if (pcd->out_ep[i].priv == handle)
52552 +                       return &pcd->out_ep[i];
52553 +       }
52554 +
52555 +       return NULL;
52556 +}
52557 +
52558 +/* USB Endpoint Operations */
52559 +/*
52560 + * The following sections briefly describe the behavior of the Gadget
52561 + * API endpoint operations implemented in the DWC_otg driver
52562 + * software. Detailed descriptions of the generic behavior of each of
52563 + * these functions can be found in the Linux header file
52564 + * include/linux/usb_gadget.h.
52565 + *
52566 + * The Gadget API provides wrapper functions for each of the function
52567 + * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
52568 + * function, which then calls the underlying PCD function. The
52569 + * following sections are named according to the wrapper
52570 + * functions. Within each section, the corresponding DWC_otg PCD
52571 + * function name is specified.
52572 + *
52573 + */
52574 +
52575 +/**
52576 + * This function is called by the Gadget Driver for each EP to be
52577 + * configured for the current configuration (SET_CONFIGURATION).
52578 + *
52579 + * This function initializes the dwc_otg_ep_t data structure, and then
52580 + * calls dwc_otg_ep_activate.
52581 + */
52582 +static int ep_enable(struct usb_ep *usb_ep,
52583 +                    const struct usb_endpoint_descriptor *ep_desc)
52584 +{
52585 +       int retval;
52586 +
52587 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
52588 +
52589 +       if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
52590 +               DWC_WARN("%s, bad ep or descriptor\n", __func__);
52591 +               return -EINVAL;
52592 +       }
52593 +       if (usb_ep == &gadget_wrapper->ep0) {
52594 +               DWC_WARN("%s, bad ep(0)\n", __func__);
52595 +               return -EINVAL;
52596 +       }
52597 +
52598 +       /* Check FIFO size? */
52599 +       if (!ep_desc->wMaxPacketSize) {
52600 +               DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
52601 +               return -ERANGE;
52602 +       }
52603 +
52604 +       if (!gadget_wrapper->driver ||
52605 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52606 +               DWC_WARN("%s, bogus device state\n", __func__);
52607 +               return -ESHUTDOWN;
52608 +       }
52609 +
52610 +       /* Delete after check - MAS */
52611 +#if 0
52612 +       nat = (uint32_t) ep_desc->wMaxPacketSize;
52613 +       printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);
52614 +       nat = (nat >> 11) & 0x03;
52615 +       printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);
52616 +#endif
52617 +       retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
52618 +                                      (const uint8_t *)ep_desc,
52619 +                                      (void *)usb_ep);
52620 +       if (retval) {
52621 +               DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
52622 +               return -EINVAL;
52623 +       }
52624 +
52625 +       usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
52626 +
52627 +       return 0;
52628 +}
52629 +
52630 +/**
52631 + * This function is called when an EP is disabled due to disconnect or
52632 + * change in configuration. Any pending requests will terminate with a
52633 + * status of -ESHUTDOWN.
52634 + *
52635 + * This function modifies the dwc_otg_ep_t data structure for this EP,
52636 + * and then calls dwc_otg_ep_deactivate.
52637 + */
52638 +static int ep_disable(struct usb_ep *usb_ep)
52639 +{
52640 +       int retval;
52641 +
52642 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
52643 +       if (!usb_ep) {
52644 +               DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
52645 +                           usb_ep ? usb_ep->name : NULL);
52646 +               return -EINVAL;
52647 +       }
52648 +
52649 +       retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
52650 +       if (retval) {
52651 +               retval = -EINVAL;
52652 +       }
52653 +
52654 +       return retval;
52655 +}
52656 +
52657 +/**
52658 + * This function allocates a request object to use with the specified
52659 + * endpoint.
52660 + *
52661 + * @param ep The endpoint to be used with with the request
52662 + * @param gfp_flags the GFP_* flags to use.
52663 + */
52664 +static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
52665 +                                                    gfp_t gfp_flags)
52666 +{
52667 +       struct usb_request *usb_req;
52668 +
52669 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
52670 +       if (0 == ep) {
52671 +               DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
52672 +               return 0;
52673 +       }
52674 +       usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
52675 +       if (0 == usb_req) {
52676 +               DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
52677 +               return 0;
52678 +       }
52679 +       memset(usb_req, 0, sizeof(*usb_req));
52680 +       usb_req->dma = DWC_DMA_ADDR_INVALID;
52681 +
52682 +       return usb_req;
52683 +}
52684 +
52685 +/**
52686 + * This function frees a request object.
52687 + *
52688 + * @param ep The endpoint associated with the request
52689 + * @param req The request being freed
52690 + */
52691 +static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
52692 +{
52693 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
52694 +
52695 +       if (0 == ep || 0 == req) {
52696 +               DWC_WARN("%s() %s\n", __func__,
52697 +                        "Invalid ep or req argument!\n");
52698 +               return;
52699 +       }
52700 +
52701 +       kfree(req);
52702 +}
52703 +
52704 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52705 +/**
52706 + * This function allocates an I/O buffer to be used for a transfer
52707 + * to/from the specified endpoint.
52708 + *
52709 + * @param usb_ep The endpoint to be used with with the request
52710 + * @param bytes The desired number of bytes for the buffer
52711 + * @param dma Pointer to the buffer's DMA address; must be valid
52712 + * @param gfp_flags the GFP_* flags to use.
52713 + * @return address of a new buffer or null is buffer could not be allocated.
52714 + */
52715 +static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
52716 +                                     dma_addr_t * dma, gfp_t gfp_flags)
52717 +{
52718 +       void *buf;
52719 +       dwc_otg_pcd_t *pcd = 0;
52720 +
52721 +       pcd = gadget_wrapper->pcd;
52722 +
52723 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
52724 +                   dma, gfp_flags);
52725 +
52726 +       /* Check dword alignment */
52727 +       if ((bytes & 0x3UL) != 0) {
52728 +               DWC_WARN("%s() Buffer size is not a multiple of"
52729 +                        "DWORD size (%d)", __func__, bytes);
52730 +       }
52731 +
52732 +       buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
52733 +
52734 +       /* Check dword alignment */
52735 +       if (((int)buf & 0x3UL) != 0) {
52736 +               DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
52737 +                        __func__, buf);
52738 +       }
52739 +
52740 +       return buf;
52741 +}
52742 +
52743 +/**
52744 + * This function frees an I/O buffer that was allocated by alloc_buffer.
52745 + *
52746 + * @param usb_ep the endpoint associated with the buffer
52747 + * @param buf address of the buffer
52748 + * @param dma The buffer's DMA address
52749 + * @param bytes The number of bytes of the buffer
52750 + */
52751 +static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
52752 +                                   dma_addr_t dma, unsigned bytes)
52753 +{
52754 +       dwc_otg_pcd_t *pcd = 0;
52755 +
52756 +       pcd = gadget_wrapper->pcd;
52757 +
52758 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
52759 +
52760 +       dma_free_coherent(NULL, bytes, buf, dma);
52761 +}
52762 +#endif
52763 +
52764 +/**
52765 + * This function is used to submit an I/O Request to an EP.
52766 + *
52767 + *     - When the request completes the request's completion callback
52768 + *       is called to return the request to the driver.
52769 + *     - An EP, except control EPs, may have multiple requests
52770 + *       pending.
52771 + *     - Once submitted the request cannot be examined or modified.
52772 + *     - Each request is turned into one or more packets.
52773 + *     - A BULK EP can queue any amount of data; the transfer is
52774 + *       packetized.
52775 + *     - Zero length Packets are specified with the request 'zero'
52776 + *       flag.
52777 + */
52778 +static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
52779 +                   gfp_t gfp_flags)
52780 +{
52781 +       dwc_otg_pcd_t *pcd;
52782 +       struct dwc_otg_pcd_ep *ep = NULL;
52783 +       int retval = 0, is_isoc_ep = 0;
52784 +       dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;
52785 +
52786 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
52787 +                   __func__, usb_ep, usb_req, gfp_flags);
52788 +
52789 +       if (!usb_req || !usb_req->complete || !usb_req->buf) {
52790 +               DWC_WARN("bad params\n");
52791 +               return -EINVAL;
52792 +       }
52793 +
52794 +       if (!usb_ep) {
52795 +               DWC_WARN("bad ep\n");
52796 +               return -EINVAL;
52797 +       }
52798 +
52799 +       pcd = gadget_wrapper->pcd;
52800 +       if (!gadget_wrapper->driver ||
52801 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52802 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
52803 +                           gadget_wrapper->gadget.speed);
52804 +               DWC_WARN("bogus device state\n");
52805 +               return -ESHUTDOWN;
52806 +       }
52807 +
52808 +       DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
52809 +                   usb_ep->name, usb_req, usb_req->length, usb_req->buf);
52810 +
52811 +       usb_req->status = -EINPROGRESS;
52812 +       usb_req->actual = 0;
52813 +
52814 +       ep = ep_from_handle(pcd, usb_ep);
52815 +       if (ep == NULL)
52816 +               is_isoc_ep = 0;
52817 +       else
52818 +               is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;
52819 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52820 +       dma_addr = usb_req->dma;
52821 +#else
52822 +       if (GET_CORE_IF(pcd)->dma_enable) {
52823 +                dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
52824 +                struct device *dev = NULL;
52825 +                
52826 +                if (otg_dev != NULL)
52827 +                        dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
52828 +                
52829 +               if (usb_req->length != 0 &&
52830 +                    usb_req->dma == DWC_DMA_ADDR_INVALID) {
52831 +                        dma_addr = dma_map_single(dev, usb_req->buf,
52832 +                                                  usb_req->length, 
52833 +                                                  ep->dwc_ep.is_in ?
52834 +                                                        DMA_TO_DEVICE:
52835 +                                                        DMA_FROM_DEVICE);
52836 +               }
52837 +       }
52838 +#endif
52839 +
52840 +#ifdef DWC_UTE_PER_IO
52841 +       if (is_isoc_ep == 1) {
52842 +               retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
52843 +                       usb_req->length, usb_req->zero, usb_req,
52844 +                       gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req);
52845 +               if (retval)
52846 +                       return -EINVAL;
52847 +
52848 +               return 0;
52849 +       }
52850 +#endif
52851 +       retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
52852 +                                     usb_req->length, usb_req->zero, usb_req,
52853 +                                     gfp_flags == GFP_ATOMIC ? 1 : 0);
52854 +       if (retval) {
52855 +               return -EINVAL;
52856 +       }
52857 +
52858 +       return 0;
52859 +}
52860 +
52861 +/**
52862 + * This function cancels an I/O request from an EP.
52863 + */
52864 +static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
52865 +{
52866 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
52867 +
52868 +       if (!usb_ep || !usb_req) {
52869 +               DWC_WARN("bad argument\n");
52870 +               return -EINVAL;
52871 +       }
52872 +       if (!gadget_wrapper->driver ||
52873 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52874 +               DWC_WARN("bogus device state\n");
52875 +               return -ESHUTDOWN;
52876 +       }
52877 +       if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
52878 +               return -EINVAL;
52879 +       }
52880 +
52881 +       return 0;
52882 +}
52883 +
52884 +/**
52885 + * usb_ep_set_halt stalls an endpoint.
52886 + *
52887 + * usb_ep_clear_halt clears an endpoint halt and resets its data
52888 + * toggle.
52889 + *
52890 + * Both of these functions are implemented with the same underlying
52891 + * function. The behavior depends on the value argument.
52892 + *
52893 + * @param[in] usb_ep the Endpoint to halt or clear halt.
52894 + * @param[in] value
52895 + *     - 0 means clear_halt.
52896 + *     - 1 means set_halt,
52897 + *     - 2 means clear stall lock flag.
52898 + *     - 3 means set  stall lock flag.
52899 + */
52900 +static int ep_halt(struct usb_ep *usb_ep, int value)
52901 +{
52902 +       int retval = 0;
52903 +
52904 +       DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
52905 +
52906 +       if (!usb_ep) {
52907 +               DWC_WARN("bad ep\n");
52908 +               return -EINVAL;
52909 +       }
52910 +
52911 +       retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
52912 +       if (retval == -DWC_E_AGAIN) {
52913 +               return -EAGAIN;
52914 +       } else if (retval) {
52915 +               retval = -EINVAL;
52916 +       }
52917 +
52918 +       return retval;
52919 +}
52920 +
52921 +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
52922 +#if 0
52923 +/**
52924 + * ep_wedge: sets the halt feature and ignores clear requests
52925 + *
52926 + * @usb_ep: the endpoint being wedged
52927 + *
52928 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
52929 + * requests. If the gadget driver clears the halt status, it will
52930 + * automatically unwedge the endpoint.
52931 + *
52932 + * Returns zero on success, else negative errno. *
52933 + * Check usb_ep_set_wedge() at "usb_gadget.h" for details
52934 + */
52935 +static int ep_wedge(struct usb_ep *usb_ep)
52936 +{
52937 +       int retval = 0;
52938 +
52939 +       DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
52940 +
52941 +       if (!usb_ep) {
52942 +               DWC_WARN("bad ep\n");
52943 +               return -EINVAL;
52944 +       }
52945 +
52946 +       retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep);
52947 +       if (retval == -DWC_E_AGAIN) {
52948 +               retval = -EAGAIN;
52949 +       } else if (retval) {
52950 +               retval = -EINVAL;
52951 +       }
52952 +
52953 +       return retval;
52954 +}
52955 +#endif
52956 +
52957 +#ifdef DWC_EN_ISOC
52958 +/**
52959 + * This function is used to submit an ISOC Transfer Request to an EP.
52960 + *
52961 + *     - Every time a sync period completes the request's completion callback
52962 + *       is called to provide data to the gadget driver.
52963 + *     - Once submitted the request cannot be modified.
52964 + *     - Each request is turned into periodic data packets untill ISO
52965 + *       Transfer is stopped..
52966 + */
52967 +static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
52968 +                       gfp_t gfp_flags)
52969 +{
52970 +       int retval = 0;
52971 +
52972 +       if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
52973 +               DWC_WARN("bad params\n");
52974 +               return -EINVAL;
52975 +       }
52976 +
52977 +       if (!usb_ep) {
52978 +               DWC_PRINTF("bad params\n");
52979 +               return -EINVAL;
52980 +       }
52981 +
52982 +       req->status = -EINPROGRESS;
52983 +
52984 +       retval =
52985 +           dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
52986 +                                    req->buf1, req->dma0, req->dma1,
52987 +                                    req->sync_frame, req->data_pattern_frame,
52988 +                                    req->data_per_frame,
52989 +                                    req->
52990 +                                    flags & USB_REQ_ISO_ASAP ? -1 :
52991 +                                    req->start_frame, req->buf_proc_intrvl,
52992 +                                    req, gfp_flags == GFP_ATOMIC ? 1 : 0);
52993 +
52994 +       if (retval) {
52995 +               return -EINVAL;
52996 +       }
52997 +
52998 +       return retval;
52999 +}
53000 +
53001 +/**
53002 + * This function stops ISO EP Periodic Data Transfer.
53003 + */
53004 +static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
53005 +{
53006 +       int retval = 0;
53007 +       if (!usb_ep) {
53008 +               DWC_WARN("bad ep\n");
53009 +       }
53010 +
53011 +       if (!gadget_wrapper->driver ||
53012 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
53013 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
53014 +                           gadget_wrapper->gadget.speed);
53015 +               DWC_WARN("bogus device state\n");
53016 +       }
53017 +
53018 +       dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
53019 +       if (retval) {
53020 +               retval = -EINVAL;
53021 +       }
53022 +
53023 +       return retval;
53024 +}
53025 +
53026 +static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
53027 +                                                int packets, gfp_t gfp_flags)
53028 +{
53029 +       struct usb_iso_request *pReq = NULL;
53030 +       uint32_t req_size;
53031 +
53032 +       req_size = sizeof(struct usb_iso_request);
53033 +       req_size +=
53034 +           (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
53035 +
53036 +       pReq = kmalloc(req_size, gfp_flags);
53037 +       if (!pReq) {
53038 +               DWC_WARN("Can't allocate Iso Request\n");
53039 +               return 0;
53040 +       }
53041 +       pReq->iso_packet_desc0 = (void *)(pReq + 1);
53042 +
53043 +       pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
53044 +
53045 +       return pReq;
53046 +}
53047 +
53048 +static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
53049 +{
53050 +       kfree(req);
53051 +}
53052 +
53053 +static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
53054 +       .ep_ops = {
53055 +                  .enable = ep_enable,
53056 +                  .disable = ep_disable,
53057 +
53058 +                  .alloc_request = dwc_otg_pcd_alloc_request,
53059 +                  .free_request = dwc_otg_pcd_free_request,
53060 +
53061 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
53062 +                  .alloc_buffer = dwc_otg_pcd_alloc_buffer,
53063 +                  .free_buffer = dwc_otg_pcd_free_buffer,
53064 +#endif
53065 +
53066 +                  .queue = ep_queue,
53067 +                  .dequeue = ep_dequeue,
53068 +
53069 +                  .set_halt = ep_halt,
53070 +                  .fifo_status = 0,
53071 +                  .fifo_flush = 0,
53072 +                  },
53073 +       .iso_ep_start = iso_ep_start,
53074 +       .iso_ep_stop = iso_ep_stop,
53075 +       .alloc_iso_request = alloc_iso_request,
53076 +       .free_iso_request = free_iso_request,
53077 +};
53078 +
53079 +#else
53080 +
53081 +       int (*enable) (struct usb_ep *ep,
53082 +               const struct usb_endpoint_descriptor *desc);
53083 +       int (*disable) (struct usb_ep *ep);
53084 +
53085 +       struct usb_request *(*alloc_request) (struct usb_ep *ep,
53086 +               gfp_t gfp_flags);
53087 +       void (*free_request) (struct usb_ep *ep, struct usb_request *req);
53088 +
53089 +       int (*queue) (struct usb_ep *ep, struct usb_request *req,
53090 +               gfp_t gfp_flags);
53091 +       int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
53092 +
53093 +       int (*set_halt) (struct usb_ep *ep, int value);
53094 +       int (*set_wedge) (struct usb_ep *ep);
53095 +
53096 +       int (*fifo_status) (struct usb_ep *ep);
53097 +       void (*fifo_flush) (struct usb_ep *ep);
53098 +static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
53099 +       .enable = ep_enable,
53100 +       .disable = ep_disable,
53101 +
53102 +       .alloc_request = dwc_otg_pcd_alloc_request,
53103 +       .free_request = dwc_otg_pcd_free_request,
53104 +
53105 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
53106 +       .alloc_buffer = dwc_otg_pcd_alloc_buffer,
53107 +       .free_buffer = dwc_otg_pcd_free_buffer,
53108 +#else
53109 +       /* .set_wedge = ep_wedge, */
53110 +        .set_wedge = NULL, /* uses set_halt instead */
53111 +#endif
53112 +        
53113 +       .queue = ep_queue,
53114 +       .dequeue = ep_dequeue,
53115 +
53116 +       .set_halt = ep_halt,
53117 +       .fifo_status = 0,
53118 +       .fifo_flush = 0,
53119 +
53120 +};
53121 +
53122 +#endif /* _EN_ISOC_ */
53123 +/*     Gadget Operations */
53124 +/**
53125 + * The following gadget operations will be implemented in the DWC_otg
53126 + * PCD. Functions in the API that are not described below are not
53127 + * implemented.
53128 + *
53129 + * The Gadget API provides wrapper functions for each of the function
53130 + * pointers defined in usb_gadget_ops. The Gadget Driver calls the
53131 + * wrapper function, which then calls the underlying PCD function. The
53132 + * following sections are named according to the wrapper functions
53133 + * (except for ioctl, which doesn't have a wrapper function). Within
53134 + * each section, the corresponding DWC_otg PCD function name is
53135 + * specified.
53136 + *
53137 + */
53138 +
53139 +/**
53140 + *Gets the USB Frame number of the last SOF.
53141 + */
53142 +static int get_frame_number(struct usb_gadget *gadget)
53143 +{
53144 +       struct gadget_wrapper *d;
53145 +
53146 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
53147 +
53148 +       if (gadget == 0) {
53149 +               return -ENODEV;
53150 +       }
53151 +
53152 +       d = container_of(gadget, struct gadget_wrapper, gadget);
53153 +       return dwc_otg_pcd_get_frame_number(d->pcd);
53154 +}
53155 +
53156 +#ifdef CONFIG_USB_DWC_OTG_LPM
53157 +static int test_lpm_enabled(struct usb_gadget *gadget)
53158 +{
53159 +       struct gadget_wrapper *d;
53160 +
53161 +       d = container_of(gadget, struct gadget_wrapper, gadget);
53162 +
53163 +       return dwc_otg_pcd_is_lpm_enabled(d->pcd);
53164 +}
53165 +#endif
53166 +
53167 +/**
53168 + * Initiates Session Request Protocol (SRP) to wakeup the host if no
53169 + * session is in progress. If a session is already in progress, but
53170 + * the device is suspended, remote wakeup signaling is started.
53171 + *
53172 + */
53173 +static int wakeup(struct usb_gadget *gadget)
53174 +{
53175 +       struct gadget_wrapper *d;
53176 +
53177 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
53178 +
53179 +       if (gadget == 0) {
53180 +               return -ENODEV;
53181 +       } else {
53182 +               d = container_of(gadget, struct gadget_wrapper, gadget);
53183 +       }
53184 +       dwc_otg_pcd_wakeup(d->pcd);
53185 +       return 0;
53186 +}
53187 +
53188 +static const struct usb_gadget_ops dwc_otg_pcd_ops = {
53189 +       .get_frame = get_frame_number,
53190 +       .wakeup = wakeup,
53191 +#ifdef CONFIG_USB_DWC_OTG_LPM
53192 +       .lpm_support = test_lpm_enabled,
53193 +#endif
53194 +       // current versions must always be self-powered
53195 +};
53196 +
53197 +static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
53198 +{
53199 +       int retval = -DWC_E_NOT_SUPPORTED;
53200 +       if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
53201 +               retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
53202 +                                                      (struct usb_ctrlrequest
53203 +                                                       *)bytes);
53204 +       }
53205 +
53206 +       if (retval == -ENOTSUPP) {
53207 +               retval = -DWC_E_NOT_SUPPORTED;
53208 +       } else if (retval < 0) {
53209 +               retval = -DWC_E_INVALID;
53210 +       }
53211 +
53212 +       return retval;
53213 +}
53214 +
53215 +#ifdef DWC_EN_ISOC
53216 +static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53217 +                         void *req_handle, int proc_buf_num)
53218 +{
53219 +       int i, packet_count;
53220 +       struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
53221 +       struct usb_iso_request *iso_req = req_handle;
53222 +
53223 +       if (proc_buf_num) {
53224 +               iso_packet = iso_req->iso_packet_desc1;
53225 +       } else {
53226 +               iso_packet = iso_req->iso_packet_desc0;
53227 +       }
53228 +       packet_count =
53229 +           dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
53230 +       for (i = 0; i < packet_count; ++i) {
53231 +               int status;
53232 +               int actual;
53233 +               int offset;
53234 +               dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
53235 +                                                 i, &status, &actual, &offset);
53236 +               switch (status) {
53237 +               case -DWC_E_NO_DATA:
53238 +                       status = -ENODATA;
53239 +                       break;
53240 +               default:
53241 +                       if (status) {
53242 +                               DWC_PRINTF("unknown status in isoc packet\n");
53243 +                       }
53244 +
53245 +               }
53246 +               iso_packet[i].status = status;
53247 +               iso_packet[i].offset = offset;
53248 +               iso_packet[i].actual_length = actual;
53249 +       }
53250 +
53251 +       iso_req->status = 0;
53252 +       iso_req->process_buffer(ep_handle, iso_req);
53253 +
53254 +       return 0;
53255 +}
53256 +#endif /* DWC_EN_ISOC */
53257 +
53258 +#ifdef DWC_UTE_PER_IO
53259 +/**
53260 + * Copy the contents of the extended request to the Linux usb_request's
53261 + * extended part and call the gadget's completion.
53262 + *
53263 + * @param pcd                  Pointer to the pcd structure
53264 + * @param ep_handle            Void pointer to the usb_ep structure
53265 + * @param req_handle   Void pointer to the usb_request structure
53266 + * @param status               Request status returned from the portable logic
53267 + * @param ereq_port            Void pointer to the extended request structure
53268 + *                                             created in the the portable part that contains the
53269 + *                                             results of the processed iso packets.
53270 + */
53271 +static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53272 +                          void *req_handle, int32_t status, void *ereq_port)
53273 +{
53274 +       struct dwc_ute_iso_req_ext *ereqorg = NULL;
53275 +       struct dwc_iso_xreq_port *ereqport = NULL;
53276 +       struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
53277 +       int i;
53278 +       struct usb_request *req;
53279 +       //struct dwc_ute_iso_packet_descriptor *
53280 +       //int status = 0;
53281 +
53282 +       req = (struct usb_request *)req_handle;
53283 +       ereqorg = &req->ext_req;
53284 +       ereqport = (struct dwc_iso_xreq_port *)ereq_port;
53285 +       desc_org = ereqorg->per_io_frame_descs;
53286 +
53287 +       if (req && req->complete) {
53288 +               /* Copy the request data from the portable logic to our request */
53289 +               for (i = 0; i < ereqport->pio_pkt_count; i++) {
53290 +                       desc_org[i].actual_length =
53291 +                           ereqport->per_io_frame_descs[i].actual_length;
53292 +                       desc_org[i].status =
53293 +                           ereqport->per_io_frame_descs[i].status;
53294 +               }
53295 +
53296 +               switch (status) {
53297 +               case -DWC_E_SHUTDOWN:
53298 +                       req->status = -ESHUTDOWN;
53299 +                       break;
53300 +               case -DWC_E_RESTART:
53301 +                       req->status = -ECONNRESET;
53302 +                       break;
53303 +               case -DWC_E_INVALID:
53304 +                       req->status = -EINVAL;
53305 +                       break;
53306 +               case -DWC_E_TIMEOUT:
53307 +                       req->status = -ETIMEDOUT;
53308 +                       break;
53309 +               default:
53310 +                       req->status = status;
53311 +               }
53312 +
53313 +               /* And call the gadget's completion */
53314 +               req->complete(ep_handle, req);
53315 +       }
53316 +
53317 +       return 0;
53318 +}
53319 +#endif /* DWC_UTE_PER_IO */
53320 +
53321 +static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53322 +                    void *req_handle, int32_t status, uint32_t actual)
53323 +{
53324 +       struct usb_request *req = (struct usb_request *)req_handle;
53325 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53326 +       struct dwc_otg_pcd_ep *ep = NULL;
53327 +#endif
53328 +
53329 +       if (req && req->complete) {
53330 +               switch (status) {
53331 +               case -DWC_E_SHUTDOWN:
53332 +                       req->status = -ESHUTDOWN;
53333 +                       break;
53334 +               case -DWC_E_RESTART:
53335 +                       req->status = -ECONNRESET;
53336 +                       break;
53337 +               case -DWC_E_INVALID:
53338 +                       req->status = -EINVAL;
53339 +                       break;
53340 +               case -DWC_E_TIMEOUT:
53341 +                       req->status = -ETIMEDOUT;
53342 +                       break;
53343 +               default:
53344 +                       req->status = status;
53345 +
53346 +               }
53347 +
53348 +               req->actual = actual;
53349 +               DWC_SPINUNLOCK(pcd->lock);
53350 +               req->complete(ep_handle, req);
53351 +               DWC_SPINLOCK(pcd->lock);
53352 +       }
53353 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53354 +       ep = ep_from_handle(pcd, ep_handle);
53355 +       if (GET_CORE_IF(pcd)->dma_enable) {
53356 +                if (req->length != 0) {
53357 +                        dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
53358 +                        struct device *dev = NULL;
53359 +
53360 +                        if (otg_dev != NULL)
53361 +                                  dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
53362 +
53363 +                       dma_unmap_single(dev, req->dma, req->length,
53364 +                                         ep->dwc_ep.is_in ?
53365 +                                                DMA_TO_DEVICE: DMA_FROM_DEVICE);
53366 +                }
53367 +       }
53368 +#endif
53369 +
53370 +       return 0;
53371 +}
53372 +
53373 +static int _connect(dwc_otg_pcd_t * pcd, int speed)
53374 +{
53375 +       gadget_wrapper->gadget.speed = speed;
53376 +       return 0;
53377 +}
53378 +
53379 +static int _disconnect(dwc_otg_pcd_t * pcd)
53380 +{
53381 +       if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
53382 +               gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
53383 +       }
53384 +       return 0;
53385 +}
53386 +
53387 +static int _resume(dwc_otg_pcd_t * pcd)
53388 +{
53389 +       if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
53390 +               gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
53391 +       }
53392 +
53393 +       return 0;
53394 +}
53395 +
53396 +static int _suspend(dwc_otg_pcd_t * pcd)
53397 +{
53398 +       if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
53399 +               gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
53400 +       }
53401 +       return 0;
53402 +}
53403 +
53404 +/**
53405 + * This function updates the otg values in the gadget structure.
53406 + */
53407 +static int _hnp_changed(dwc_otg_pcd_t * pcd)
53408 +{
53409 +
53410 +       if (!gadget_wrapper->gadget.is_otg)
53411 +               return 0;
53412 +
53413 +       gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
53414 +       gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
53415 +       gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
53416 +       return 0;
53417 +}
53418 +
53419 +static int _reset(dwc_otg_pcd_t * pcd)
53420 +{
53421 +       return 0;
53422 +}
53423 +
53424 +#ifdef DWC_UTE_CFI
53425 +static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
53426 +{
53427 +       int retval = -DWC_E_INVALID;
53428 +       if (gadget_wrapper->driver->cfi_feature_setup) {
53429 +               retval =
53430 +                   gadget_wrapper->driver->
53431 +                   cfi_feature_setup(&gadget_wrapper->gadget,
53432 +                                     (struct cfi_usb_ctrlrequest *)cfi_req);
53433 +       }
53434 +
53435 +       return retval;
53436 +}
53437 +#endif
53438 +
53439 +static const struct dwc_otg_pcd_function_ops fops = {
53440 +       .complete = _complete,
53441 +#ifdef DWC_EN_ISOC
53442 +       .isoc_complete = _isoc_complete,
53443 +#endif
53444 +       .setup = _setup,
53445 +       .disconnect = _disconnect,
53446 +       .connect = _connect,
53447 +       .resume = _resume,
53448 +       .suspend = _suspend,
53449 +       .hnp_changed = _hnp_changed,
53450 +       .reset = _reset,
53451 +#ifdef DWC_UTE_CFI
53452 +       .cfi_setup = _cfi_setup,
53453 +#endif
53454 +#ifdef DWC_UTE_PER_IO
53455 +       .xisoc_complete = _xisoc_complete,
53456 +#endif
53457 +};
53458 +
53459 +/**
53460 + * This function is the top level PCD interrupt handler.
53461 + */
53462 +static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
53463 +{
53464 +       dwc_otg_pcd_t *pcd = dev;
53465 +       int32_t retval = IRQ_NONE;
53466 +
53467 +       retval = dwc_otg_pcd_handle_intr(pcd);
53468 +       if (retval != 0) {
53469 +               S3C2410X_CLEAR_EINTPEND();
53470 +       }
53471 +       return IRQ_RETVAL(retval);
53472 +}
53473 +
53474 +/**
53475 + * This function initialized the usb_ep structures to there default
53476 + * state.
53477 + *
53478 + * @param d Pointer on gadget_wrapper.
53479 + */
53480 +void gadget_add_eps(struct gadget_wrapper *d)
53481 +{
53482 +       static const char *names[] = {
53483 +
53484 +               "ep0",
53485 +               "ep1in",
53486 +               "ep2in",
53487 +               "ep3in",
53488 +               "ep4in",
53489 +               "ep5in",
53490 +               "ep6in",
53491 +               "ep7in",
53492 +               "ep8in",
53493 +               "ep9in",
53494 +               "ep10in",
53495 +               "ep11in",
53496 +               "ep12in",
53497 +               "ep13in",
53498 +               "ep14in",
53499 +               "ep15in",
53500 +               "ep1out",
53501 +               "ep2out",
53502 +               "ep3out",
53503 +               "ep4out",
53504 +               "ep5out",
53505 +               "ep6out",
53506 +               "ep7out",
53507 +               "ep8out",
53508 +               "ep9out",
53509 +               "ep10out",
53510 +               "ep11out",
53511 +               "ep12out",
53512 +               "ep13out",
53513 +               "ep14out",
53514 +               "ep15out"
53515 +       };
53516 +
53517 +       int i;
53518 +       struct usb_ep *ep;
53519 +       int8_t dev_endpoints;
53520 +
53521 +       DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
53522 +
53523 +       INIT_LIST_HEAD(&d->gadget.ep_list);
53524 +       d->gadget.ep0 = &d->ep0;
53525 +       d->gadget.speed = USB_SPEED_UNKNOWN;
53526 +
53527 +       INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
53528 +
53529 +       /**
53530 +        * Initialize the EP0 structure.
53531 +        */
53532 +       ep = &d->ep0;
53533 +
53534 +       /* Init the usb_ep structure. */
53535 +       ep->name = names[0];
53536 +       ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53537 +
53538 +       /**
53539 +        * @todo NGS: What should the max packet size be set to
53540 +        * here?  Before EP type is set?
53541 +        */
53542 +       ep->maxpacket = MAX_PACKET_SIZE;
53543 +       dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
53544 +
53545 +       list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53546 +
53547 +       /**
53548 +        * Initialize the EP structures.
53549 +        */
53550 +       dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
53551 +
53552 +       for (i = 0; i < dev_endpoints; i++) {
53553 +               ep = &d->in_ep[i];
53554 +
53555 +               /* Init the usb_ep structure. */
53556 +               ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
53557 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53558 +
53559 +               /**
53560 +                * @todo NGS: What should the max packet size be set to
53561 +                * here?  Before EP type is set?
53562 +                */
53563 +               ep->maxpacket = MAX_PACKET_SIZE;
53564 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53565 +       }
53566 +
53567 +       dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
53568 +
53569 +       for (i = 0; i < dev_endpoints; i++) {
53570 +               ep = &d->out_ep[i];
53571 +
53572 +               /* Init the usb_ep structure. */
53573 +               ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
53574 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53575 +
53576 +               /**
53577 +                * @todo NGS: What should the max packet size be set to
53578 +                * here?  Before EP type is set?
53579 +                */
53580 +               ep->maxpacket = MAX_PACKET_SIZE;
53581 +
53582 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53583 +       }
53584 +
53585 +       /* remove ep0 from the list.  There is a ep0 pointer. */
53586 +       list_del_init(&d->ep0.ep_list);
53587 +
53588 +       d->ep0.maxpacket = MAX_EP0_SIZE;
53589 +}
53590 +
53591 +/**
53592 + * This function releases the Gadget device.
53593 + * required by device_unregister().
53594 + *
53595 + * @todo Should this do something?     Should it free the PCD?
53596 + */
53597 +static void dwc_otg_pcd_gadget_release(struct device *dev)
53598 +{
53599 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
53600 +}
53601 +
53602 +static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev)
53603 +{
53604 +       static char pcd_name[] = "dwc_otg_pcd";
53605 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53606 +       struct gadget_wrapper *d;
53607 +       int retval;
53608 +
53609 +       d = DWC_ALLOC(sizeof(*d));
53610 +       if (d == NULL) {
53611 +               return NULL;
53612 +       }
53613 +
53614 +       memset(d, 0, sizeof(*d));
53615 +
53616 +       d->gadget.name = pcd_name;
53617 +       d->pcd = otg_dev->pcd;
53618 +
53619 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
53620 +       strcpy(d->gadget.dev.bus_id, "gadget");
53621 +#else
53622 +       dev_set_name(&d->gadget.dev, "%s", "gadget");
53623 +#endif
53624 +
53625 +       d->gadget.dev.parent = &_dev->dev;
53626 +       d->gadget.dev.release = dwc_otg_pcd_gadget_release;
53627 +       d->gadget.ops = &dwc_otg_pcd_ops;
53628 +       d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL;
53629 +       d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
53630 +
53631 +       d->driver = 0;
53632 +       /* Register the gadget device */
53633 +       retval = device_register(&d->gadget.dev);
53634 +       if (retval != 0) {
53635 +               DWC_ERROR("device_register failed\n");
53636 +               DWC_FREE(d);
53637 +               return NULL;
53638 +       }
53639 +
53640 +       return d;
53641 +}
53642 +
53643 +static void free_wrapper(struct gadget_wrapper *d)
53644 +{
53645 +       if (d->driver) {
53646 +               /* should have been done already by driver model core */
53647 +               DWC_WARN("driver '%s' is still registered\n",
53648 +                        d->driver->driver.name);
53649 +               usb_gadget_unregister_driver(d->driver);
53650 +       }
53651 +
53652 +       device_unregister(&d->gadget.dev);
53653 +       DWC_FREE(d);
53654 +}
53655 +
53656 +/**
53657 + * This function initialized the PCD portion of the driver.
53658 + *
53659 + */
53660 +int pcd_init(dwc_bus_dev_t *_dev)
53661 +{
53662 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53663 +       int retval = 0;
53664 +
53665 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev);
53666 +
53667 +       otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
53668 +
53669 +       if (!otg_dev->pcd) {
53670 +               DWC_ERROR("dwc_otg_pcd_init failed\n");
53671 +               return -ENOMEM;
53672 +       }
53673 +
53674 +       otg_dev->pcd->otg_dev = otg_dev;
53675 +       gadget_wrapper = alloc_wrapper(_dev);
53676 +
53677 +       /*
53678 +        * Initialize EP structures
53679 +        */
53680 +       gadget_add_eps(gadget_wrapper);
53681 +       /*
53682 +        * Setup interupt handler
53683 +        */
53684 +#ifdef PLATFORM_INTERFACE
53685 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53686 +                    platform_get_irq(_dev, 0));
53687 +       retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq,
53688 +                            IRQF_SHARED, gadget_wrapper->gadget.name,
53689 +                            otg_dev->pcd);
53690 +       if (retval != 0) {
53691 +               DWC_ERROR("request of irq%d failed\n",
53692 +                          platform_get_irq(_dev, 0));
53693 +               free_wrapper(gadget_wrapper);
53694 +               return -EBUSY;
53695 +       }
53696 +#else
53697 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53698 +                    _dev->irq);
53699 +       retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
53700 +                            IRQF_SHARED | IRQF_DISABLED,
53701 +                            gadget_wrapper->gadget.name, otg_dev->pcd);
53702 +       if (retval != 0) {
53703 +               DWC_ERROR("request of irq%d failed\n", _dev->irq);
53704 +               free_wrapper(gadget_wrapper);
53705 +               return -EBUSY;
53706 +       }
53707 +#endif
53708 +
53709 +       dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
53710 +
53711 +       return retval;
53712 +}
53713 +
53714 +/**
53715 + * Cleanup the PCD.
53716 + */
53717 +void pcd_remove(dwc_bus_dev_t *_dev)
53718 +{
53719 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53720 +       dwc_otg_pcd_t *pcd = otg_dev->pcd;
53721 +
53722 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
53723 +
53724 +       /*
53725 +        * Free the IRQ
53726 +        */
53727 +#ifdef PLATFORM_INTERFACE
53728 +       free_irq(platform_get_irq(_dev, 0), pcd);
53729 +#else
53730 +       free_irq(_dev->irq, pcd);
53731 +#endif
53732 +       dwc_otg_pcd_remove(otg_dev->pcd);
53733 +       free_wrapper(gadget_wrapper);
53734 +       otg_dev->pcd = 0;
53735 +}
53736 +
53737 +/**
53738 + * This function registers a gadget driver with the PCD.
53739 + *
53740 + * When a driver is successfully registered, it will receive control
53741 + * requests including set_configuration(), which enables non-control
53742 + * requests.  then usb traffic follows until a disconnect is reported.
53743 + * then a host may connect again, or the driver might get unbound.
53744 + *
53745 + * @param driver The driver being registered
53746 + * @param bind The bind function of gadget driver
53747 + */
53748 +
53749 +int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
53750 +{
53751 +       int retval;
53752 +
53753 +       DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
53754 +                   driver->driver.name);
53755 +
53756 +       if (!driver || driver->max_speed == USB_SPEED_UNKNOWN ||
53757 +           !driver->bind ||
53758 +           !driver->unbind || !driver->disconnect || !driver->setup) {
53759 +               DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
53760 +               return -EINVAL;
53761 +       }
53762 +       if (gadget_wrapper == 0) {
53763 +               DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
53764 +               return -ENODEV;
53765 +       }
53766 +       if (gadget_wrapper->driver != 0) {
53767 +               DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
53768 +               return -EBUSY;
53769 +       }
53770 +
53771 +       /* hook up the driver */
53772 +       gadget_wrapper->driver = driver;
53773 +       gadget_wrapper->gadget.dev.driver = &driver->driver;
53774 +
53775 +       DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
53776 +       retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver);
53777 +       if (retval) {
53778 +               DWC_ERROR("bind to driver %s --> error %d\n",
53779 +                         driver->driver.name, retval);
53780 +               gadget_wrapper->driver = 0;
53781 +               gadget_wrapper->gadget.dev.driver = 0;
53782 +               return retval;
53783 +       }
53784 +       DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
53785 +                   driver->driver.name);
53786 +       return 0;
53787 +}
53788 +EXPORT_SYMBOL(usb_gadget_probe_driver);
53789 +
53790 +/**
53791 + * This function unregisters a gadget driver
53792 + *
53793 + * @param driver The driver being unregistered
53794 + */
53795 +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
53796 +{
53797 +       //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);
53798 +
53799 +       if (gadget_wrapper == 0) {
53800 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
53801 +                           -ENODEV);
53802 +               return -ENODEV;
53803 +       }
53804 +       if (driver == 0 || driver != gadget_wrapper->driver) {
53805 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
53806 +                           -EINVAL);
53807 +               return -EINVAL;
53808 +       }
53809 +
53810 +       driver->unbind(&gadget_wrapper->gadget);
53811 +       gadget_wrapper->driver = 0;
53812 +
53813 +       DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
53814 +       return 0;
53815 +}
53816 +
53817 +EXPORT_SYMBOL(usb_gadget_unregister_driver);
53818 +
53819 +#endif /* DWC_HOST_ONLY */
53820 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h
53821 new file mode 100644
53822 index 0000000..0572642
53823 --- /dev/null
53824 +++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h
53825 @@ -0,0 +1,2550 @@
53826 +/* ==========================================================================
53827 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
53828 + * $Revision: #98 $
53829 + * $Date: 2012/08/10 $
53830 + * $Change: 2047372 $
53831 + *
53832 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
53833 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
53834 + * otherwise expressly agreed to in writing between Synopsys and you.
53835 + *
53836 + * The Software IS NOT an item of Licensed Software or Licensed Product under
53837 + * any End User Software License Agreement or Agreement for Licensed Product
53838 + * with Synopsys or any supplement thereto. You are permitted to use and
53839 + * redistribute this Software in source and binary forms, with or without
53840 + * modification, provided that redistributions of source code must retain this
53841 + * notice. You may not view, use, disclose, copy or distribute this file or
53842 + * any information contained herein except pursuant to this license grant from
53843 + * Synopsys. If you do not agree with this notice, including the disclaimer
53844 + * below, then you are not authorized to use the Software.
53845 + *
53846 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
53847 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53848 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53849 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
53850 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53851 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53852 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
53853 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53854 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53855 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
53856 + * DAMAGE.
53857 + * ========================================================================== */
53858 +
53859 +#ifndef __DWC_OTG_REGS_H__
53860 +#define __DWC_OTG_REGS_H__
53861 +
53862 +#include "dwc_otg_core_if.h"
53863 +
53864 +/**
53865 + * @file
53866 + *
53867 + * This file contains the data structures for accessing the DWC_otg core registers.
53868 + *
53869 + * The application interfaces with the HS OTG core by reading from and
53870 + * writing to the Control and Status Register (CSR) space through the
53871 + * AHB Slave interface. These registers are 32 bits wide, and the
53872 + * addresses are 32-bit-block aligned.
53873 + * CSRs are classified as follows:
53874 + * - Core Global Registers
53875 + * - Device Mode Registers
53876 + * - Device Global Registers
53877 + * - Device Endpoint Specific Registers
53878 + * - Host Mode Registers
53879 + * - Host Global Registers
53880 + * - Host Port CSRs
53881 + * - Host Channel Specific Registers
53882 + *
53883 + * Only the Core Global registers can be accessed in both Device and
53884 + * Host modes. When the HS OTG core is operating in one mode, either
53885 + * Device or Host, the application must not access registers from the
53886 + * other mode. When the core switches from one mode to another, the
53887 + * registers in the new mode of operation must be reprogrammed as they
53888 + * would be after a power-on reset.
53889 + */
53890 +
53891 +/****************************************************************************/
53892 +/** DWC_otg Core registers . 
53893 + * The dwc_otg_core_global_regs structure defines the size
53894 + * and relative field offsets for the Core Global registers.
53895 + */
53896 +typedef struct dwc_otg_core_global_regs {
53897 +       /** OTG Control and Status Register.  <i>Offset: 000h</i> */
53898 +       volatile uint32_t gotgctl;
53899 +       /** OTG Interrupt Register.      <i>Offset: 004h</i> */
53900 +       volatile uint32_t gotgint;
53901 +       /**Core AHB Configuration Register.      <i>Offset: 008h</i> */
53902 +       volatile uint32_t gahbcfg;
53903 +
53904 +#define DWC_GLBINTRMASK                0x0001
53905 +#define DWC_DMAENABLE          0x0020
53906 +#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
53907 +#define DWC_NPTXEMPTYLVL_HALFEMPTY     0x0000
53908 +#define DWC_PTXEMPTYLVL_EMPTY  0x0100
53909 +#define DWC_PTXEMPTYLVL_HALFEMPTY      0x0000
53910 +
53911 +       /**Core USB Configuration Register.      <i>Offset: 00Ch</i> */
53912 +       volatile uint32_t gusbcfg;
53913 +       /**Core Reset Register.  <i>Offset: 010h</i> */
53914 +       volatile uint32_t grstctl;
53915 +       /**Core Interrupt Register.      <i>Offset: 014h</i> */
53916 +       volatile uint32_t gintsts;
53917 +       /**Core Interrupt Mask Register.  <i>Offset: 018h</i> */
53918 +       volatile uint32_t gintmsk;
53919 +       /**Receive Status Queue Read Register (Read Only).      <i>Offset: 01Ch</i> */
53920 +       volatile uint32_t grxstsr;
53921 +       /**Receive Status Queue Read & POP Register (Read Only).  <i>Offset: 020h</i>*/
53922 +       volatile uint32_t grxstsp;
53923 +       /**Receive FIFO Size Register.  <i>Offset: 024h</i> */
53924 +       volatile uint32_t grxfsiz;
53925 +       /**Non Periodic Transmit FIFO Size Register.  <i>Offset: 028h</i> */
53926 +       volatile uint32_t gnptxfsiz;
53927 +       /**Non Periodic Transmit FIFO/Queue Status Register (Read
53928 +        * Only). <i>Offset: 02Ch</i> */
53929 +       volatile uint32_t gnptxsts;
53930 +       /**I2C Access Register.  <i>Offset: 030h</i> */
53931 +       volatile uint32_t gi2cctl;
53932 +       /**PHY Vendor Control Register.  <i>Offset: 034h</i> */
53933 +       volatile uint32_t gpvndctl;
53934 +       /**General Purpose Input/Output Register.  <i>Offset: 038h</i> */
53935 +       volatile uint32_t ggpio;
53936 +       /**User ID Register.  <i>Offset: 03Ch</i> */
53937 +       volatile uint32_t guid;
53938 +       /**Synopsys ID Register (Read Only).  <i>Offset: 040h</i> */
53939 +       volatile uint32_t gsnpsid;
53940 +       /**User HW Config1 Register (Read Only).  <i>Offset: 044h</i> */
53941 +       volatile uint32_t ghwcfg1;
53942 +       /**User HW Config2 Register (Read Only).  <i>Offset: 048h</i> */
53943 +       volatile uint32_t ghwcfg2;
53944 +#define DWC_SLAVE_ONLY_ARCH 0
53945 +#define DWC_EXT_DMA_ARCH 1
53946 +#define DWC_INT_DMA_ARCH 2
53947 +
53948 +#define DWC_MODE_HNP_SRP_CAPABLE       0
53949 +#define DWC_MODE_SRP_ONLY_CAPABLE      1
53950 +#define DWC_MODE_NO_HNP_SRP_CAPABLE            2
53951 +#define DWC_MODE_SRP_CAPABLE_DEVICE            3
53952 +#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
53953 +#define DWC_MODE_SRP_CAPABLE_HOST      5
53954 +#define DWC_MODE_NO_SRP_CAPABLE_HOST   6
53955 +
53956 +       /**User HW Config3 Register (Read Only).  <i>Offset: 04Ch</i> */
53957 +       volatile uint32_t ghwcfg3;
53958 +       /**User HW Config4 Register (Read Only).  <i>Offset: 050h</i>*/
53959 +       volatile uint32_t ghwcfg4;
53960 +       /** Core LPM Configuration register <i>Offset: 054h</i>*/
53961 +       volatile uint32_t glpmcfg;
53962 +       /** Global PowerDn Register <i>Offset: 058h</i> */
53963 +       volatile uint32_t gpwrdn;
53964 +       /** Global DFIFO SW Config Register  <i>Offset: 05Ch</i> */
53965 +       volatile uint32_t gdfifocfg;
53966 +       /** ADP Control Register  <i>Offset: 060h</i> */
53967 +       volatile uint32_t adpctl;
53968 +       /** Reserved  <i>Offset: 064h-0FFh</i> */
53969 +       volatile uint32_t reserved39[39];
53970 +       /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
53971 +       volatile uint32_t hptxfsiz;
53972 +       /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
53973 +               otherwise Device Transmit FIFO#n Register.
53974 +        * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
53975 +       volatile uint32_t dtxfsiz[15];
53976 +} dwc_otg_core_global_regs_t;
53977 +
53978 +/**
53979 + * This union represents the bit fields of the Core OTG Control
53980 + * and Status Register (GOTGCTL).  Set the bits using the bit
53981 + * fields then write the <i>d32</i> value to the register.
53982 + */
53983 +typedef union gotgctl_data {
53984 +       /** raw register data */
53985 +       uint32_t d32;
53986 +       /** register bits */
53987 +       struct {
53988 +               unsigned sesreqscs:1;
53989 +               unsigned sesreq:1;
53990 +               unsigned vbvalidoven:1;
53991 +               unsigned vbvalidovval:1;
53992 +               unsigned avalidoven:1;
53993 +               unsigned avalidovval:1;
53994 +               unsigned bvalidoven:1;
53995 +               unsigned bvalidovval:1;
53996 +               unsigned hstnegscs:1;
53997 +               unsigned hnpreq:1;
53998 +               unsigned hstsethnpen:1;
53999 +               unsigned devhnpen:1;
54000 +               unsigned reserved12_15:4;
54001 +               unsigned conidsts:1;
54002 +               unsigned dbnctime:1;
54003 +               unsigned asesvld:1;
54004 +               unsigned bsesvld:1;
54005 +               unsigned otgver:1;
54006 +               unsigned reserved1:1;
54007 +               unsigned multvalidbc:5;
54008 +               unsigned chirpen:1;
54009 +               unsigned reserved28_31:4;
54010 +       } b;
54011 +} gotgctl_data_t;
54012 +
54013 +/**
54014 + * This union represents the bit fields of the Core OTG Interrupt Register
54015 + * (GOTGINT).  Set/clear the bits using the bit fields then write the <i>d32</i>
54016 + * value to the register.
54017 + */
54018 +typedef union gotgint_data {
54019 +       /** raw register data */
54020 +       uint32_t d32;
54021 +       /** register bits */
54022 +       struct {
54023 +               /** Current Mode */
54024 +               unsigned reserved0_1:2;
54025 +
54026 +               /** Session End Detected */
54027 +               unsigned sesenddet:1;
54028 +
54029 +               unsigned reserved3_7:5;
54030 +
54031 +               /** Session Request Success Status Change */
54032 +               unsigned sesreqsucstschng:1;
54033 +               /** Host Negotiation Success Status Change */
54034 +               unsigned hstnegsucstschng:1;
54035 +
54036 +               unsigned reserved10_16:7;
54037 +
54038 +               /** Host Negotiation Detected */
54039 +               unsigned hstnegdet:1;
54040 +               /** A-Device Timeout Change */
54041 +               unsigned adevtoutchng:1;
54042 +               /** Debounce Done */
54043 +               unsigned debdone:1;
54044 +               /** Multi-Valued input changed */
54045 +               unsigned mvic:1;
54046 +
54047 +               unsigned reserved31_21:11;
54048 +
54049 +       } b;
54050 +} gotgint_data_t;
54051 +
54052 +/**
54053 + * This union represents the bit fields of the Core AHB Configuration
54054 + * Register (GAHBCFG). Set/clear the bits using the bit fields then
54055 + * write the <i>d32</i> value to the register.
54056 + */
54057 +typedef union gahbcfg_data {
54058 +       /** raw register data */
54059 +       uint32_t d32;
54060 +       /** register bits */
54061 +       struct {
54062 +               unsigned glblintrmsk:1;
54063 +#define DWC_GAHBCFG_GLBINT_ENABLE              1
54064 +
54065 +               unsigned hburstlen:4;
54066 +#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE       0
54067 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR         1
54068 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR4                3
54069 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR8                5
54070 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR16       7
54071 +
54072 +               unsigned dmaenable:1;
54073 +#define DWC_GAHBCFG_DMAENABLE                  1
54074 +               unsigned reserved:1;
54075 +               unsigned nptxfemplvl_txfemplvl:1;
54076 +               unsigned ptxfemplvl:1;
54077 +#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY          1
54078 +#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY      0
54079 +               unsigned reserved9_20:12;
54080 +               unsigned remmemsupp:1;
54081 +               unsigned notialldmawrit:1;
54082 +               unsigned ahbsingle:1;
54083 +               unsigned reserved24_31:8;
54084 +       } b;
54085 +} gahbcfg_data_t;
54086 +
54087 +/**
54088 + * This union represents the bit fields of the Core USB Configuration
54089 + * Register (GUSBCFG). Set the bits using the bit fields then write
54090 + * the <i>d32</i> value to the register.
54091 + */
54092 +typedef union gusbcfg_data {
54093 +       /** raw register data */
54094 +       uint32_t d32;
54095 +       /** register bits */
54096 +       struct {
54097 +               unsigned toutcal:3;
54098 +               unsigned phyif:1;
54099 +               unsigned ulpi_utmi_sel:1;
54100 +               unsigned fsintf:1;
54101 +               unsigned physel:1;
54102 +               unsigned ddrsel:1;
54103 +               unsigned srpcap:1;
54104 +               unsigned hnpcap:1;
54105 +               unsigned usbtrdtim:4;
54106 +               unsigned reserved1:1;
54107 +               unsigned phylpwrclksel:1;
54108 +               unsigned otgutmifssel:1;
54109 +               unsigned ulpi_fsls:1;
54110 +               unsigned ulpi_auto_res:1;
54111 +               unsigned ulpi_clk_sus_m:1;
54112 +               unsigned ulpi_ext_vbus_drv:1;
54113 +               unsigned ulpi_int_vbus_indicator:1;
54114 +               unsigned term_sel_dl_pulse:1;
54115 +               unsigned indicator_complement:1;
54116 +               unsigned indicator_pass_through:1;
54117 +               unsigned ulpi_int_prot_dis:1;
54118 +               unsigned ic_usb_cap:1;
54119 +               unsigned ic_traffic_pull_remove:1;
54120 +               unsigned tx_end_delay:1;
54121 +               unsigned force_host_mode:1;
54122 +               unsigned force_dev_mode:1;
54123 +               unsigned reserved31:1;
54124 +       } b;
54125 +} gusbcfg_data_t;
54126 +
54127 +/**
54128 + * This union represents the bit fields of the Core Reset Register
54129 + * (GRSTCTL).  Set/clear the bits using the bit fields then write the
54130 + * <i>d32</i> value to the register.
54131 + */
54132 +typedef union grstctl_data {
54133 +       /** raw register data */
54134 +       uint32_t d32;
54135 +       /** register bits */
54136 +       struct {
54137 +               /** Core Soft Reset (CSftRst) (Device and Host)
54138 +                *
54139 +                * The application can flush the control logic in the
54140 +                * entire core using this bit. This bit resets the
54141 +                * pipelines in the AHB Clock domain as well as the
54142 +                * PHY Clock domain.
54143 +                *
54144 +                * The state machines are reset to an IDLE state, the
54145 +                * control bits in the CSRs are cleared, all the
54146 +                * transmit FIFOs and the receive FIFO are flushed.
54147 +                *
54148 +                * The status mask bits that control the generation of
54149 +                * the interrupt, are cleared, to clear the
54150 +                * interrupt. The interrupt status bits are not
54151 +                * cleared, so the application can get the status of
54152 +                * any events that occurred in the core after it has
54153 +                * set this bit.
54154 +                *
54155 +                * Any transactions on the AHB are terminated as soon
54156 +                * as possible following the protocol. Any
54157 +                * transactions on the USB are terminated immediately.
54158 +                *
54159 +                * The configuration settings in the CSRs are
54160 +                * unchanged, so the software doesn't have to
54161 +                * reprogram these registers (Device
54162 +                * Configuration/Host Configuration/Core System
54163 +                * Configuration/Core PHY Configuration).
54164 +                *
54165 +                * The application can write to this bit, any time it
54166 +                * wants to reset the core. This is a self clearing
54167 +                * bit and the core clears this bit after all the
54168 +                * necessary logic is reset in the core, which may
54169 +                * take several clocks, depending on the current state
54170 +                * of the core.
54171 +                */
54172 +               unsigned csftrst:1;
54173 +               /** Hclk Soft Reset
54174 +                *
54175 +                * The application uses this bit to reset the control logic in
54176 +                * the AHB clock domain. Only AHB clock domain pipelines are
54177 +                * reset.
54178 +                */
54179 +               unsigned hsftrst:1;
54180 +               /** Host Frame Counter Reset (Host Only)<br>
54181 +                *
54182 +                * The application can reset the (micro)frame number
54183 +                * counter inside the core, using this bit. When the
54184 +                * (micro)frame counter is reset, the subsequent SOF
54185 +                * sent out by the core, will have a (micro)frame
54186 +                * number of 0.
54187 +                */
54188 +               unsigned hstfrm:1;
54189 +               /** In Token Sequence Learning Queue Flush
54190 +                * (INTknQFlsh) (Device Only)
54191 +                */
54192 +               unsigned intknqflsh:1;
54193 +               /** RxFIFO Flush (RxFFlsh) (Device and Host)
54194 +                *
54195 +                * The application can flush the entire Receive FIFO
54196 +                * using this bit. The application must first
54197 +                * ensure that the core is not in the middle of a
54198 +                * transaction. The application should write into
54199 +                * this bit, only after making sure that neither the
54200 +                * DMA engine is reading from the RxFIFO nor the MAC
54201 +                * is writing the data in to the FIFO. The
54202 +                * application should wait until the bit is cleared
54203 +                * before performing any other operations. This bit
54204 +                * will takes 8 clocks (slowest of PHY or AHB clock)
54205 +                * to clear.
54206 +                */
54207 +               unsigned rxfflsh:1;
54208 +               /** TxFIFO Flush (TxFFlsh) (Device and Host). 
54209 +                *
54210 +                * This bit is used to selectively flush a single or
54211 +                * all transmit FIFOs. The application must first
54212 +                * ensure that the core is not in the middle of a
54213 +                * transaction. The application should write into
54214 +                * this bit, only after making sure that neither the
54215 +                * DMA engine is writing into the TxFIFO nor the MAC
54216 +                * is reading the data out of the FIFO. The
54217 +                * application should wait until the core clears this
54218 +                * bit, before performing any operations. This bit
54219 +                * will takes 8 clocks (slowest of PHY or AHB clock)
54220 +                * to clear.
54221 +                */
54222 +               unsigned txfflsh:1;
54223 +
54224 +               /** TxFIFO Number (TxFNum) (Device and Host).
54225 +                *
54226 +                * This is the FIFO number which needs to be flushed,
54227 +                * using the TxFIFO Flush bit. This field should not
54228 +                * be changed until the TxFIFO Flush bit is cleared by
54229 +                * the core.
54230 +                *       - 0x0 : Non Periodic TxFIFO Flush
54231 +                *       - 0x1 : Periodic TxFIFO #1 Flush in device mode
54232 +                *         or Periodic TxFIFO in host mode
54233 +                *       - 0x2 : Periodic TxFIFO #2 Flush in device mode.
54234 +                *       - ...
54235 +                *       - 0xF : Periodic TxFIFO #15 Flush in device mode
54236 +                *       - 0x10: Flush all the Transmit NonPeriodic and
54237 +                *         Transmit Periodic FIFOs in the core
54238 +                */
54239 +               unsigned txfnum:5;
54240 +               /** Reserved */
54241 +               unsigned reserved11_29:19;
54242 +               /** DMA Request Signal.  Indicated DMA request is in
54243 +                * probress. Used for debug purpose. */
54244 +               unsigned dmareq:1;
54245 +               /** AHB Master Idle.  Indicates the AHB Master State
54246 +                * Machine is in IDLE condition. */
54247 +               unsigned ahbidle:1;
54248 +       } b;
54249 +} grstctl_t;
54250 +
54251 +/**
54252 + * This union represents the bit fields of the Core Interrupt Mask
54253 + * Register (GINTMSK). Set/clear the bits using the bit fields then
54254 + * write the <i>d32</i> value to the register.
54255 + */
54256 +typedef union gintmsk_data {
54257 +       /** raw register data */
54258 +       uint32_t d32;
54259 +       /** register bits */
54260 +       struct {
54261 +               unsigned reserved0:1;
54262 +               unsigned modemismatch:1;
54263 +               unsigned otgintr:1;
54264 +               unsigned sofintr:1;
54265 +               unsigned rxstsqlvl:1;
54266 +               unsigned nptxfempty:1;
54267 +               unsigned ginnakeff:1;
54268 +               unsigned goutnakeff:1;
54269 +               unsigned ulpickint:1;
54270 +               unsigned i2cintr:1;
54271 +               unsigned erlysuspend:1;
54272 +               unsigned usbsuspend:1;
54273 +               unsigned usbreset:1;
54274 +               unsigned enumdone:1;
54275 +               unsigned isooutdrop:1;
54276 +               unsigned eopframe:1;
54277 +               unsigned restoredone:1;
54278 +               unsigned epmismatch:1;
54279 +               unsigned inepintr:1;
54280 +               unsigned outepintr:1;
54281 +               unsigned incomplisoin:1;
54282 +               unsigned incomplisoout:1;
54283 +               unsigned fetsusp:1;
54284 +               unsigned resetdet:1;
54285 +               unsigned portintr:1;
54286 +               unsigned hcintr:1;
54287 +               unsigned ptxfempty:1;
54288 +               unsigned lpmtranrcvd:1;
54289 +               unsigned conidstschng:1;
54290 +               unsigned disconnect:1;
54291 +               unsigned sessreqintr:1;
54292 +               unsigned wkupintr:1;
54293 +       } b;
54294 +} gintmsk_data_t;
54295 +/**
54296 + * This union represents the bit fields of the Core Interrupt Register
54297 + * (GINTSTS).  Set/clear the bits using the bit fields then write the
54298 + * <i>d32</i> value to the register.
54299 + */
54300 +typedef union gintsts_data {
54301 +       /** raw register data */
54302 +       uint32_t d32;
54303 +#define DWC_SOF_INTR_MASK 0x0008
54304 +       /** register bits */
54305 +       struct {
54306 +#define DWC_HOST_MODE 1
54307 +               unsigned curmode:1;
54308 +               unsigned modemismatch:1;
54309 +               unsigned otgintr:1;
54310 +               unsigned sofintr:1;
54311 +               unsigned rxstsqlvl:1;
54312 +               unsigned nptxfempty:1;
54313 +               unsigned ginnakeff:1;
54314 +               unsigned goutnakeff:1;
54315 +               unsigned ulpickint:1;
54316 +               unsigned i2cintr:1;
54317 +               unsigned erlysuspend:1;
54318 +               unsigned usbsuspend:1;
54319 +               unsigned usbreset:1;
54320 +               unsigned enumdone:1;
54321 +               unsigned isooutdrop:1;
54322 +               unsigned eopframe:1;
54323 +               unsigned restoredone:1;
54324 +               unsigned epmismatch:1;
54325 +               unsigned inepint:1;
54326 +               unsigned outepintr:1;
54327 +               unsigned incomplisoin:1;
54328 +               unsigned incomplisoout:1;
54329 +               unsigned fetsusp:1;
54330 +               unsigned resetdet:1;
54331 +               unsigned portintr:1;
54332 +               unsigned hcintr:1;
54333 +               unsigned ptxfempty:1;
54334 +               unsigned lpmtranrcvd:1;
54335 +               unsigned conidstschng:1;
54336 +               unsigned disconnect:1;
54337 +               unsigned sessreqintr:1;
54338 +               unsigned wkupintr:1;
54339 +       } b;
54340 +} gintsts_data_t;
54341 +
54342 +/**
54343 + * This union represents the bit fields in the Device Receive Status Read and
54344 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54345 + * element then read out the bits using the <i>b</i>it elements.
54346 + */
54347 +typedef union device_grxsts_data {
54348 +       /** raw register data */
54349 +       uint32_t d32;
54350 +       /** register bits */
54351 +       struct {
54352 +               unsigned epnum:4;
54353 +               unsigned bcnt:11;
54354 +               unsigned dpid:2;
54355 +
54356 +#define DWC_STS_DATA_UPDT              0x2     // OUT Data Packet
54357 +#define DWC_STS_XFER_COMP              0x3     // OUT Data Transfer Complete
54358 +
54359 +#define DWC_DSTS_GOUT_NAK              0x1     // Global OUT NAK
54360 +#define DWC_DSTS_SETUP_COMP            0x4     // Setup Phase Complete
54361 +#define DWC_DSTS_SETUP_UPDT 0x6        // SETUP Packet
54362 +               unsigned pktsts:4;
54363 +               unsigned fn:4;
54364 +               unsigned reserved25_31:7;
54365 +       } b;
54366 +} device_grxsts_data_t;
54367 +
54368 +/**
54369 + * This union represents the bit fields in the Host Receive Status Read and
54370 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54371 + * element then read out the bits using the <i>b</i>it elements.
54372 + */
54373 +typedef union host_grxsts_data {
54374 +       /** raw register data */
54375 +       uint32_t d32;
54376 +       /** register bits */
54377 +       struct {
54378 +               unsigned chnum:4;
54379 +               unsigned bcnt:11;
54380 +               unsigned dpid:2;
54381 +
54382 +               unsigned pktsts:4;
54383 +#define DWC_GRXSTS_PKTSTS_IN                     0x2
54384 +#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP   0x3
54385 +#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
54386 +#define DWC_GRXSTS_PKTSTS_CH_HALTED              0x7
54387 +
54388 +               unsigned reserved21_31:11;
54389 +       } b;
54390 +} host_grxsts_data_t;
54391 +
54392 +/**
54393 + * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
54394 + * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element 
54395 + * then read out the bits using the <i>b</i>it elements.
54396 + */
54397 +typedef union fifosize_data {
54398 +       /** raw register data */
54399 +       uint32_t d32;
54400 +       /** register bits */
54401 +       struct {
54402 +               unsigned startaddr:16;
54403 +               unsigned depth:16;
54404 +       } b;
54405 +} fifosize_data_t;
54406 +
54407 +/**
54408 + * This union represents the bit fields in the Non-Periodic Transmit
54409 + * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
54410 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54411 + * elements.
54412 + */
54413 +typedef union gnptxsts_data {
54414 +       /** raw register data */
54415 +       uint32_t d32;
54416 +       /** register bits */
54417 +       struct {
54418 +               unsigned nptxfspcavail:16;
54419 +               unsigned nptxqspcavail:8;
54420 +               /** Top of the Non-Periodic Transmit Request Queue
54421 +                *      - bit 24 - Terminate (Last entry for the selected
54422 +                *        channel/EP)
54423 +                *      - bits 26:25 - Token Type
54424 +                *        - 2'b00 - IN/OUT
54425 +                *        - 2'b01 - Zero Length OUT
54426 +                *        - 2'b10 - PING/Complete Split
54427 +                *        - 2'b11 - Channel Halt
54428 +                *      - bits 30:27 - Channel/EP Number
54429 +                */
54430 +               unsigned nptxqtop_terminate:1;
54431 +               unsigned nptxqtop_token:2;
54432 +               unsigned nptxqtop_chnep:4;
54433 +               unsigned reserved:1;
54434 +       } b;
54435 +} gnptxsts_data_t;
54436 +
54437 +/**
54438 + * This union represents the bit fields in the Transmit
54439 + * FIFO Status Register (DTXFSTS). Read the register into the
54440 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54441 + * elements.
54442 + */
54443 +typedef union dtxfsts_data {
54444 +       /** raw register data */
54445 +       uint32_t d32;
54446 +       /** register bits */
54447 +       struct {
54448 +               unsigned txfspcavail:16;
54449 +               unsigned reserved:16;
54450 +       } b;
54451 +} dtxfsts_data_t;
54452 +
54453 +/**
54454 + * This union represents the bit fields in the I2C Control Register
54455 + * (I2CCTL). Read the register into the <i>d32</i> element then read out the
54456 + * bits using the <i>b</i>it elements.
54457 + */
54458 +typedef union gi2cctl_data {
54459 +       /** raw register data */
54460 +       uint32_t d32;
54461 +       /** register bits */
54462 +       struct {
54463 +               unsigned rwdata:8;
54464 +               unsigned regaddr:8;
54465 +               unsigned addr:7;
54466 +               unsigned i2cen:1;
54467 +               unsigned ack:1;
54468 +               unsigned i2csuspctl:1;
54469 +               unsigned i2cdevaddr:2;
54470 +               unsigned i2cdatse0:1;
54471 +               unsigned reserved:1;
54472 +               unsigned rw:1;
54473 +               unsigned bsydne:1;
54474 +       } b;
54475 +} gi2cctl_data_t;
54476 +
54477 +/**
54478 + * This union represents the bit fields in the PHY Vendor Control Register
54479 + * (GPVNDCTL). Read the register into the <i>d32</i> element then read out the
54480 + * bits using the <i>b</i>it elements.
54481 + */
54482 +typedef union gpvndctl_data {
54483 +       /** raw register data */
54484 +       uint32_t d32;
54485 +       /** register bits */
54486 +       struct {
54487 +               unsigned regdata:8;
54488 +               unsigned vctrl:8;
54489 +               unsigned regaddr16_21:6;
54490 +               unsigned regwr:1;
54491 +               unsigned reserved23_24:2;
54492 +               unsigned newregreq:1;
54493 +               unsigned vstsbsy:1;
54494 +               unsigned vstsdone:1;
54495 +               unsigned reserved28_30:3;
54496 +               unsigned disulpidrvr:1;
54497 +       } b;
54498 +} gpvndctl_data_t;
54499 +
54500 +/**
54501 + * This union represents the bit fields in the General Purpose 
54502 + * Input/Output Register (GGPIO).
54503 + * Read the register into the <i>d32</i> element then read out the
54504 + * bits using the <i>b</i>it elements.
54505 + */
54506 +typedef union ggpio_data {
54507 +       /** raw register data */
54508 +       uint32_t d32;
54509 +       /** register bits */
54510 +       struct {
54511 +               unsigned gpi:16;
54512 +               unsigned gpo:16;
54513 +       } b;
54514 +} ggpio_data_t;
54515 +
54516 +/**
54517 + * This union represents the bit fields in the User ID Register
54518 + * (GUID). Read the register into the <i>d32</i> element then read out the
54519 + * bits using the <i>b</i>it elements.
54520 + */
54521 +typedef union guid_data {
54522 +       /** raw register data */
54523 +       uint32_t d32;
54524 +       /** register bits */
54525 +       struct {
54526 +               unsigned rwdata:32;
54527 +       } b;
54528 +} guid_data_t;
54529 +
54530 +/**
54531 + * This union represents the bit fields in the Synopsys ID Register
54532 + * (GSNPSID). Read the register into the <i>d32</i> element then read out the
54533 + * bits using the <i>b</i>it elements.
54534 + */
54535 +typedef union gsnpsid_data {
54536 +       /** raw register data */
54537 +       uint32_t d32;
54538 +       /** register bits */
54539 +       struct {
54540 +               unsigned rwdata:32;
54541 +       } b;
54542 +} gsnpsid_data_t;
54543 +
54544 +/**
54545 + * This union represents the bit fields in the User HW Config1
54546 + * Register.  Read the register into the <i>d32</i> element then read
54547 + * out the bits using the <i>b</i>it elements.
54548 + */
54549 +typedef union hwcfg1_data {
54550 +       /** raw register data */
54551 +       uint32_t d32;
54552 +       /** register bits */
54553 +       struct {
54554 +               unsigned ep_dir0:2;
54555 +               unsigned ep_dir1:2;
54556 +               unsigned ep_dir2:2;
54557 +               unsigned ep_dir3:2;
54558 +               unsigned ep_dir4:2;
54559 +               unsigned ep_dir5:2;
54560 +               unsigned ep_dir6:2;
54561 +               unsigned ep_dir7:2;
54562 +               unsigned ep_dir8:2;
54563 +               unsigned ep_dir9:2;
54564 +               unsigned ep_dir10:2;
54565 +               unsigned ep_dir11:2;
54566 +               unsigned ep_dir12:2;
54567 +               unsigned ep_dir13:2;
54568 +               unsigned ep_dir14:2;
54569 +               unsigned ep_dir15:2;
54570 +       } b;
54571 +} hwcfg1_data_t;
54572 +
54573 +/**
54574 + * This union represents the bit fields in the User HW Config2
54575 + * Register.  Read the register into the <i>d32</i> element then read
54576 + * out the bits using the <i>b</i>it elements.
54577 + */
54578 +typedef union hwcfg2_data {
54579 +       /** raw register data */
54580 +       uint32_t d32;
54581 +       /** register bits */
54582 +       struct {
54583 +               /* GHWCFG2 */
54584 +               unsigned op_mode:3;
54585 +#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
54586 +#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
54587 +#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
54588 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
54589 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
54590 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
54591 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
54592 +
54593 +               unsigned architecture:2;
54594 +               unsigned point2point:1;
54595 +               unsigned hs_phy_type:2;
54596 +#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
54597 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
54598 +#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
54599 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
54600 +
54601 +               unsigned fs_phy_type:2;
54602 +               unsigned num_dev_ep:4;
54603 +               unsigned num_host_chan:4;
54604 +               unsigned perio_ep_supported:1;
54605 +               unsigned dynamic_fifo:1;
54606 +               unsigned multi_proc_int:1;
54607 +               unsigned reserved21:1;
54608 +               unsigned nonperio_tx_q_depth:2;
54609 +               unsigned host_perio_tx_q_depth:2;
54610 +               unsigned dev_token_q_depth:5;
54611 +               unsigned otg_enable_ic_usb:1;
54612 +       } b;
54613 +} hwcfg2_data_t;
54614 +
54615 +/**
54616 + * This union represents the bit fields in the User HW Config3
54617 + * Register.  Read the register into the <i>d32</i> element then read
54618 + * out the bits using the <i>b</i>it elements.
54619 + */
54620 +typedef union hwcfg3_data {
54621 +       /** raw register data */
54622 +       uint32_t d32;
54623 +       /** register bits */
54624 +       struct {
54625 +               /* GHWCFG3 */
54626 +               unsigned xfer_size_cntr_width:4;
54627 +               unsigned packet_size_cntr_width:3;
54628 +               unsigned otg_func:1;
54629 +               unsigned i2c:1;
54630 +               unsigned vendor_ctrl_if:1;
54631 +               unsigned optional_features:1;
54632 +               unsigned synch_reset_type:1;
54633 +               unsigned adp_supp:1;
54634 +               unsigned otg_enable_hsic:1;
54635 +               unsigned bc_support:1;
54636 +               unsigned otg_lpm_en:1;
54637 +               unsigned dfifo_depth:16;
54638 +       } b;
54639 +} hwcfg3_data_t;
54640 +
54641 +/**
54642 + * This union represents the bit fields in the User HW Config4
54643 + * Register.  Read the register into the <i>d32</i> element then read
54644 + * out the bits using the <i>b</i>it elements.
54645 + */
54646 +typedef union hwcfg4_data {
54647 +       /** raw register data */
54648 +       uint32_t d32;
54649 +       /** register bits */
54650 +       struct {
54651 +               unsigned num_dev_perio_in_ep:4;
54652 +               unsigned power_optimiz:1;
54653 +               unsigned min_ahb_freq:1;
54654 +               unsigned hiber:1;
54655 +               unsigned xhiber:1;
54656 +               unsigned reserved:6;
54657 +               unsigned utmi_phy_data_width:2;
54658 +               unsigned num_dev_mode_ctrl_ep:4;
54659 +               unsigned iddig_filt_en:1;
54660 +               unsigned vbus_valid_filt_en:1;
54661 +               unsigned a_valid_filt_en:1;
54662 +               unsigned b_valid_filt_en:1;
54663 +               unsigned session_end_filt_en:1;
54664 +               unsigned ded_fifo_en:1;
54665 +               unsigned num_in_eps:4;
54666 +               unsigned desc_dma:1;
54667 +               unsigned desc_dma_dyn:1;
54668 +       } b;
54669 +} hwcfg4_data_t;
54670 +
54671 +/**
54672 + * This union represents the bit fields of the Core LPM Configuration
54673 + * Register (GLPMCFG). Set the bits using bit fields then write
54674 + * the <i>d32</i> value to the register.
54675 + */
54676 +typedef union glpmctl_data {
54677 +       /** raw register data */
54678 +       uint32_t d32;
54679 +       /** register bits */
54680 +       struct {
54681 +               /** LPM-Capable (LPMCap) (Device and Host)
54682 +                * The application uses this bit to control
54683 +                * the DWC_otg core LPM capabilities.
54684 +                */
54685 +               unsigned lpm_cap_en:1;
54686 +               /** LPM response programmed by application (AppL1Res) (Device)
54687 +                * Handshake response to LPM token pre-programmed
54688 +                * by device application software.
54689 +                */
54690 +               unsigned appl_resp:1;
54691 +               /** Host Initiated Resume Duration (HIRD) (Device and Host)
54692 +                * In Host mode this field indicates the value of HIRD
54693 +                * to be sent in an LPM transaction.
54694 +                * In Device mode this field is updated with the
54695 +                * Received LPM Token HIRD bmAttribute
54696 +                * when an ACK/NYET/STALL response is sent
54697 +                * to an LPM transaction.
54698 +                */
54699 +               unsigned hird:4;
54700 +               /** RemoteWakeEnable (bRemoteWake) (Device and Host)
54701 +                * In Host mode this bit indicates the value of remote
54702 +                * wake up to be sent in wIndex field of LPM transaction.
54703 +                * In Device mode this field is updated with the
54704 +                * Received LPM Token bRemoteWake bmAttribute
54705 +                * when an ACK/NYET/STALL response is sent
54706 +                * to an LPM transaction.
54707 +                */
54708 +               unsigned rem_wkup_en:1;
54709 +               /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
54710 +                * The application uses this bit to control
54711 +                * the utmi_sleep_n assertion to the PHY when in L1 state.
54712 +                */
54713 +               unsigned en_utmi_sleep:1;
54714 +               /** HIRD Threshold (HIRD_Thres) (Device and Host)
54715 +                */
54716 +               unsigned hird_thres:5;
54717 +               /** LPM Response (CoreL1Res) (Device and Host)
54718 +                * In Host mode this bit contains handsake response to
54719 +                * LPM transaction.
54720 +                * In Device mode the response of the core to
54721 +                * LPM transaction received is reflected in these two bits.
54722 +                       - 0x0 : ERROR (No handshake response)
54723 +                       - 0x1 : STALL
54724 +                       - 0x2 : NYET
54725 +                       - 0x3 : ACK                     
54726 +                */
54727 +               unsigned lpm_resp:2;
54728 +               /** Port Sleep Status (SlpSts) (Device and Host)
54729 +                * This bit is set as long as a Sleep condition
54730 +                * is present on the USB bus.
54731 +                */
54732 +               unsigned prt_sleep_sts:1;
54733 +               /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
54734 +                * Indicates that the application or host
54735 +                * can start resume from Sleep state.
54736 +                */
54737 +               unsigned sleep_state_resumeok:1;
54738 +               /** LPM channel Index (LPM_Chnl_Indx) (Host)
54739 +                * The channel number on which the LPM transaction
54740 +                * has to be applied while sending
54741 +                * an LPM transaction to the local device.
54742 +                */
54743 +               unsigned lpm_chan_index:4;
54744 +               /** LPM Retry Count (LPM_Retry_Cnt) (Host)
54745 +                * Number host retries that would be performed
54746 +                * if the device response was not valid response.
54747 +                */
54748 +               unsigned retry_count:3;
54749 +               /** Send LPM Transaction (SndLPM) (Host)
54750 +                * When set by application software,
54751 +                * an LPM transaction containing two tokens
54752 +                * is sent.
54753 +                */
54754 +               unsigned send_lpm:1;
54755 +               /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
54756 +                * Number of LPM Host Retries still remaining
54757 +                * to be transmitted for the current LPM sequence
54758 +                */
54759 +               unsigned retry_count_sts:3;
54760 +               unsigned reserved28_29:2;
54761 +               /** In host mode once this bit is set, the host
54762 +                * configures to drive the HSIC Idle state on the bus.
54763 +                * It then waits for the  device to initiate the Connect sequence.
54764 +                * In device mode once this bit is set, the device waits for
54765 +                * the HSIC Idle line state on the bus. Upon receving the Idle
54766 +                * line state, it initiates the HSIC Connect sequence.
54767 +                */
54768 +               unsigned hsic_connect:1;
54769 +               /** This bit overrides and functionally inverts
54770 +                * the if_select_hsic input port signal.
54771 +                */
54772 +               unsigned inv_sel_hsic:1;
54773 +       } b;
54774 +} glpmcfg_data_t;
54775 +
54776 +/**
54777 + * This union represents the bit fields of the Core ADP Timer, Control and
54778 + * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write
54779 + * the <i>d32</i> value to the register.
54780 + */
54781 +typedef union adpctl_data {
54782 +       /** raw register data */
54783 +       uint32_t d32;
54784 +       /** register bits */
54785 +       struct {
54786 +               /** Probe Discharge (PRB_DSCHG)
54787 +                *  These bits set the times for TADP_DSCHG. 
54788 +                *  These bits are defined as follows:
54789 +                *  2'b00 - 4 msec
54790 +                *  2'b01 - 8 msec
54791 +                *  2'b10 - 16 msec
54792 +                *  2'b11 - 32 msec
54793 +                */
54794 +               unsigned prb_dschg:2;
54795 +               /** Probe Delta (PRB_DELTA)
54796 +                *  These bits set the resolution for RTIM   value.
54797 +                *  The bits are defined in units of 32 kHz clock cycles as follows:
54798 +                *  2'b00  -  1 cycles
54799 +                *  2'b01  -  2 cycles
54800 +                *  2'b10 -  3 cycles
54801 +                *  2'b11 - 4 cycles
54802 +                *  For example if this value is chosen to 2'b01, it means that RTIM
54803 +                *  increments for every 3(three) 32Khz clock cycles.
54804 +                */
54805 +               unsigned prb_delta:2;
54806 +               /** Probe Period (PRB_PER)
54807 +                *  These bits sets the TADP_PRD as shown in Figure 4 as follows:
54808 +                *  2'b00  -  0.625 to 0.925 sec (typical 0.775 sec)
54809 +                *  2'b01  -  1.25 to 1.85 sec (typical 1.55 sec)
54810 +                *  2'b10  -  1.9 to 2.6 sec (typical 2.275 sec)
54811 +                *  2'b11  -  Reserved
54812 +                */
54813 +               unsigned prb_per:2;
54814 +               /** These bits capture the latest time it took for VBUS to ramp from 
54815 +                *  VADP_SINK to VADP_PRB. 
54816 +                *  0x000  -  1 cycles
54817 +                *  0x001  -  2 cycles
54818 +                *  0x002  -  3 cycles
54819 +                *  etc
54820 +                *  0x7FF  -  2048 cycles
54821 +                *  A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec.
54822 +               */
54823 +               unsigned rtim:11;
54824 +               /** Enable Probe (EnaPrb)
54825 +                *  When programmed to 1'b1, the core performs a probe operation.
54826 +                *  This bit is valid only if OTG_Ver = 1'b1.
54827 +                */
54828 +               unsigned enaprb:1;
54829 +               /** Enable Sense (EnaSns)
54830 +                *  When programmed to 1'b1, the core performs a Sense operation.
54831 +                *  This bit is valid only if OTG_Ver = 1'b1.
54832 +                */
54833 +               unsigned enasns:1;
54834 +               /** ADP Reset (ADPRes)
54835 +                *  When set, ADP controller is reset.
54836 +                *  This bit is valid only if OTG_Ver = 1'b1.
54837 +                */
54838 +               unsigned adpres:1;
54839 +               /** ADP Enable (ADPEn)
54840 +                *  When set, the core performs either ADP probing or sensing
54841 +                *  based on EnaPrb or EnaSns.
54842 +                *  This bit is valid only if OTG_Ver = 1'b1.
54843 +                */
54844 +               unsigned adpen:1;
54845 +               /** ADP Probe Interrupt (ADP_PRB_INT)
54846 +                *  When this bit is set, it means that the VBUS
54847 +                *  voltage is greater than VADP_PRB or VADP_PRB is reached.
54848 +                *  This bit is valid only if OTG_Ver = 1'b1.
54849 +                */
54850 +               unsigned adp_prb_int:1;
54851 +               /**
54852 +                *  ADP Sense Interrupt (ADP_SNS_INT)
54853 +                *  When this bit is set, it means that the VBUS voltage is greater than 
54854 +                *  VADP_SNS value or VADP_SNS is reached.
54855 +                *  This bit is valid only if OTG_Ver = 1'b1.
54856 +                */
54857 +               unsigned adp_sns_int:1;
54858 +               /** ADP Tomeout Interrupt (ADP_TMOUT_INT)
54859 +                *  This bit is relevant only for an ADP probe.
54860 +                *  When this bit is set, it means that the ramp time has
54861 +                *  completed ie ADPCTL.RTIM has reached its terminal value
54862 +                *  of 0x7FF.  This is a debug feature that allows software
54863 +                *  to read the ramp time after each cycle.
54864 +                *  This bit is valid only if OTG_Ver = 1'b1.
54865 +                */
54866 +               unsigned adp_tmout_int:1;
54867 +               /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK)
54868 +                *  When this bit is set, it unmasks the interrupt due to ADP_PRB_INT.
54869 +                *  This bit is valid only if OTG_Ver = 1'b1.
54870 +                */
54871 +               unsigned adp_prb_int_msk:1;
54872 +               /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK)
54873 +                *  When this bit is set, it unmasks the interrupt due to ADP_SNS_INT.
54874 +                *  This bit is valid only if OTG_Ver = 1'b1.
54875 +                */
54876 +               unsigned adp_sns_int_msk:1;
54877 +               /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK)
54878 +                *  When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT.
54879 +                *  This bit is valid only if OTG_Ver = 1'b1.
54880 +                */
54881 +               unsigned adp_tmout_int_msk:1;
54882 +               /** Access Request
54883 +                * 2'b00 - Read/Write Valid (updated by the core) 
54884 +                * 2'b01 - Read
54885 +                * 2'b00 - Write
54886 +                * 2'b00 - Reserved
54887 +                */
54888 +               unsigned ar:2;
54889 +                /** Reserved */
54890 +               unsigned reserved29_31:3;
54891 +       } b;
54892 +} adpctl_data_t;
54893 +
54894 +////////////////////////////////////////////
54895 +// Device Registers
54896 +/**
54897 + * Device Global Registers. <i>Offsets 800h-BFFh</i>
54898 + *
54899 + * The following structures define the size and relative field offsets
54900 + * for the Device Mode Registers.
54901 + *
54902 + * <i>These registers are visible only in Device mode and must not be
54903 + * accessed in Host mode, as the results are unknown.</i>
54904 + */
54905 +typedef struct dwc_otg_dev_global_regs {
54906 +       /** Device Configuration Register. <i>Offset 800h</i> */
54907 +       volatile uint32_t dcfg;
54908 +       /** Device Control Register. <i>Offset: 804h</i> */
54909 +       volatile uint32_t dctl;
54910 +       /** Device Status Register (Read Only). <i>Offset: 808h</i> */
54911 +       volatile uint32_t dsts;
54912 +       /** Reserved. <i>Offset: 80Ch</i> */
54913 +       uint32_t unused;
54914 +       /** Device IN Endpoint Common Interrupt Mask
54915 +        * Register. <i>Offset: 810h</i> */
54916 +       volatile uint32_t diepmsk;
54917 +       /** Device OUT Endpoint Common Interrupt Mask
54918 +        * Register. <i>Offset: 814h</i> */
54919 +       volatile uint32_t doepmsk;
54920 +       /** Device All Endpoints Interrupt Register.  <i>Offset: 818h</i> */
54921 +       volatile uint32_t daint;
54922 +       /** Device All Endpoints Interrupt Mask Register.  <i>Offset:
54923 +        * 81Ch</i> */
54924 +       volatile uint32_t daintmsk;
54925 +       /** Device IN Token Queue Read Register-1 (Read Only).
54926 +        * <i>Offset: 820h</i> */
54927 +       volatile uint32_t dtknqr1;
54928 +       /** Device IN Token Queue Read Register-2 (Read Only).
54929 +        * <i>Offset: 824h</i> */
54930 +       volatile uint32_t dtknqr2;
54931 +       /** Device VBUS  discharge Register.  <i>Offset: 828h</i> */
54932 +       volatile uint32_t dvbusdis;
54933 +       /** Device VBUS Pulse Register.  <i>Offset: 82Ch</i> */
54934 +       volatile uint32_t dvbuspulse;
54935 +       /** Device IN Token Queue Read Register-3 (Read Only). /
54936 +        *      Device Thresholding control register (Read/Write)
54937 +        * <i>Offset: 830h</i> */
54938 +       volatile uint32_t dtknqr3_dthrctl;
54939 +       /** Device IN Token Queue Read Register-4 (Read Only). /
54940 +        *      Device IN EPs empty Inr. Mask Register (Read/Write)
54941 +        * <i>Offset: 834h</i> */
54942 +       volatile uint32_t dtknqr4_fifoemptymsk;
54943 +       /** Device Each Endpoint Interrupt Register (Read Only). /
54944 +        * <i>Offset: 838h</i> */
54945 +       volatile uint32_t deachint;
54946 +       /** Device Each Endpoint Interrupt mask Register (Read/Write). /
54947 +        * <i>Offset: 83Ch</i> */
54948 +       volatile uint32_t deachintmsk;
54949 +       /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
54950 +        * <i>Offset: 840h</i> */
54951 +       volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
54952 +       /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
54953 +        * <i>Offset: 880h</i> */
54954 +       volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
54955 +} dwc_otg_device_global_regs_t;
54956 +
54957 +/**
54958 + * This union represents the bit fields in the Device Configuration
54959 + * Register.  Read the register into the <i>d32</i> member then
54960 + * set/clear the bits using the <i>b</i>it elements.  Write the
54961 + * <i>d32</i> member to the dcfg register.
54962 + */
54963 +typedef union dcfg_data {
54964 +       /** raw register data */
54965 +       uint32_t d32;
54966 +       /** register bits */
54967 +       struct {
54968 +               /** Device Speed */
54969 +               unsigned devspd:2;
54970 +               /** Non Zero Length Status OUT Handshake */
54971 +               unsigned nzstsouthshk:1;
54972 +#define DWC_DCFG_SEND_STALL 1
54973 +
54974 +               unsigned ena32khzs:1;
54975 +               /** Device Addresses */
54976 +               unsigned devaddr:7;
54977 +               /** Periodic Frame Interval */
54978 +               unsigned perfrint:2;
54979 +#define DWC_DCFG_FRAME_INTERVAL_80 0
54980 +#define DWC_DCFG_FRAME_INTERVAL_85 1
54981 +#define DWC_DCFG_FRAME_INTERVAL_90 2
54982 +#define DWC_DCFG_FRAME_INTERVAL_95 3
54983 +               
54984 +               /** Enable Device OUT NAK for bulk in DDMA mode */
54985 +               unsigned endevoutnak:1;
54986 +
54987 +               unsigned reserved14_17:4;
54988 +               /** In Endpoint Mis-match count */
54989 +               unsigned epmscnt:5;
54990 +               /** Enable Descriptor DMA in Device mode */
54991 +               unsigned descdma:1;
54992 +               unsigned perschintvl:2;
54993 +               unsigned resvalid:6;
54994 +       } b;
54995 +} dcfg_data_t;
54996 +
54997 +/**
54998 + * This union represents the bit fields in the Device Control
54999 + * Register.  Read the register into the <i>d32</i> member then
55000 + * set/clear the bits using the <i>b</i>it elements.
55001 + */
55002 +typedef union dctl_data {
55003 +       /** raw register data */
55004 +       uint32_t d32;
55005 +       /** register bits */
55006 +       struct {
55007 +               /** Remote Wakeup */
55008 +               unsigned rmtwkupsig:1;
55009 +               /** Soft Disconnect */
55010 +               unsigned sftdiscon:1;
55011 +               /** Global Non-Periodic IN NAK Status */
55012 +               unsigned gnpinnaksts:1;
55013 +               /** Global OUT NAK Status */
55014 +               unsigned goutnaksts:1;
55015 +               /** Test Control */
55016 +               unsigned tstctl:3;
55017 +               /** Set Global Non-Periodic IN NAK */
55018 +               unsigned sgnpinnak:1;
55019 +               /** Clear Global Non-Periodic IN NAK */
55020 +               unsigned cgnpinnak:1;
55021 +               /** Set Global OUT NAK */
55022 +               unsigned sgoutnak:1;
55023 +               /** Clear Global OUT NAK */
55024 +               unsigned cgoutnak:1;
55025 +               /** Power-On Programming Done */
55026 +               unsigned pwronprgdone:1;
55027 +               /** Reserved */
55028 +               unsigned reserved:1;
55029 +               /** Global Multi Count */
55030 +               unsigned gmc:2;
55031 +               /** Ignore Frame Number for ISOC EPs */
55032 +               unsigned ifrmnum:1;
55033 +               /** NAK on Babble */
55034 +               unsigned nakonbble:1;
55035 +               /** Enable Continue on BNA */
55036 +               unsigned encontonbna:1;
55037 +
55038 +               unsigned reserved18_31:14;
55039 +       } b;
55040 +} dctl_data_t;
55041 +
55042 +/**
55043 + * This union represents the bit fields in the Device Status
55044 + * Register.  Read the register into the <i>d32</i> member then
55045 + * set/clear the bits using the <i>b</i>it elements.
55046 + */
55047 +typedef union dsts_data {
55048 +       /** raw register data */
55049 +       uint32_t d32;
55050 +       /** register bits */
55051 +       struct {
55052 +               /** Suspend Status */
55053 +               unsigned suspsts:1;
55054 +               /** Enumerated Speed */
55055 +               unsigned enumspd:2;
55056 +#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
55057 +#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
55058 +#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ              2
55059 +#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ             3
55060 +               /** Erratic Error */
55061 +               unsigned errticerr:1;
55062 +               unsigned reserved4_7:4;
55063 +               /** Frame or Microframe Number of the received SOF */
55064 +               unsigned soffn:14;
55065 +               unsigned reserved22_31:10;
55066 +       } b;
55067 +} dsts_data_t;
55068 +
55069 +/**
55070 + * This union represents the bit fields in the Device IN EP Interrupt
55071 + * Register and the Device IN EP Common Mask Register.
55072 + *
55073 + * - Read the register into the <i>d32</i> member then set/clear the
55074 + *      bits using the <i>b</i>it elements.
55075 + */
55076 +typedef union diepint_data {
55077 +       /** raw register data */
55078 +       uint32_t d32;
55079 +       /** register bits */
55080 +       struct {
55081 +               /** Transfer complete mask */
55082 +               unsigned xfercompl:1;
55083 +               /** Endpoint disable mask */
55084 +               unsigned epdisabled:1;
55085 +               /** AHB Error mask */
55086 +               unsigned ahberr:1;
55087 +               /** TimeOUT Handshake mask (non-ISOC EPs) */
55088 +               unsigned timeout:1;
55089 +               /** IN Token received with TxF Empty mask */
55090 +               unsigned intktxfemp:1;
55091 +               /** IN Token Received with EP mismatch mask */
55092 +               unsigned intknepmis:1;
55093 +               /** IN Endpoint NAK Effective mask */
55094 +               unsigned inepnakeff:1;
55095 +               /** Reserved */
55096 +               unsigned emptyintr:1;
55097 +
55098 +               unsigned txfifoundrn:1;
55099 +
55100 +               /** BNA Interrupt mask */
55101 +               unsigned bna:1;
55102 +
55103 +               unsigned reserved10_12:3;
55104 +               /** BNA Interrupt mask */
55105 +               unsigned nak:1;
55106 +
55107 +               unsigned reserved14_31:18;
55108 +       } b;
55109 +} diepint_data_t;
55110 +
55111 +/**
55112 + * This union represents the bit fields in the Device IN EP
55113 + * Common/Dedicated Interrupt Mask Register.
55114 + */
55115 +typedef union diepint_data diepmsk_data_t;
55116 +
55117 +/**
55118 + * This union represents the bit fields in the Device OUT EP Interrupt
55119 + * Registerand Device OUT EP Common Interrupt Mask Register.
55120 + *
55121 + * - Read the register into the <i>d32</i> member then set/clear the
55122 + *      bits using the <i>b</i>it elements.
55123 + */
55124 +typedef union doepint_data {
55125 +       /** raw register data */
55126 +       uint32_t d32;
55127 +       /** register bits */
55128 +       struct {
55129 +               /** Transfer complete */
55130 +               unsigned xfercompl:1;
55131 +               /** Endpoint disable  */
55132 +               unsigned epdisabled:1;
55133 +               /** AHB Error */
55134 +               unsigned ahberr:1;
55135 +               /** Setup Phase Done (contorl EPs) */
55136 +               unsigned setup:1;
55137 +               /** OUT Token Received when Endpoint Disabled */
55138 +               unsigned outtknepdis:1;
55139 +
55140 +               unsigned stsphsercvd:1;
55141 +               /** Back-to-Back SETUP Packets Received */
55142 +               unsigned back2backsetup:1;
55143 +
55144 +               unsigned reserved7:1;
55145 +               /** OUT packet Error */
55146 +               unsigned outpkterr:1;
55147 +               /** BNA Interrupt */
55148 +               unsigned bna:1;
55149 +
55150 +               unsigned reserved10:1;
55151 +               /** Packet Drop Status */
55152 +               unsigned pktdrpsts:1;
55153 +               /** Babble Interrupt */
55154 +               unsigned babble:1;
55155 +               /** NAK Interrupt */
55156 +               unsigned nak:1;
55157 +               /** NYET Interrupt */
55158 +               unsigned nyet:1;
55159 +               /** Bit indicating setup packet received */
55160 +               unsigned sr:1;
55161 +
55162 +               unsigned reserved16_31:16;
55163 +       } b;
55164 +} doepint_data_t;
55165 +
55166 +/**
55167 + * This union represents the bit fields in the Device OUT EP
55168 + * Common/Dedicated Interrupt Mask Register.
55169 + */
55170 +typedef union doepint_data doepmsk_data_t;
55171 +
55172 +/**
55173 + * This union represents the bit fields in the Device All EP Interrupt
55174 + * and Mask Registers.
55175 + * - Read the register into the <i>d32</i> member then set/clear the
55176 + *      bits using the <i>b</i>it elements.
55177 + */
55178 +typedef union daint_data {
55179 +       /** raw register data */
55180 +       uint32_t d32;
55181 +       /** register bits */
55182 +       struct {
55183 +               /** IN Endpoint bits */
55184 +               unsigned in:16;
55185 +               /** OUT Endpoint bits */
55186 +               unsigned out:16;
55187 +       } ep;
55188 +       struct {
55189 +               /** IN Endpoint bits */
55190 +               unsigned inep0:1;
55191 +               unsigned inep1:1;
55192 +               unsigned inep2:1;
55193 +               unsigned inep3:1;
55194 +               unsigned inep4:1;
55195 +               unsigned inep5:1;
55196 +               unsigned inep6:1;
55197 +               unsigned inep7:1;
55198 +               unsigned inep8:1;
55199 +               unsigned inep9:1;
55200 +               unsigned inep10:1;
55201 +               unsigned inep11:1;
55202 +               unsigned inep12:1;
55203 +               unsigned inep13:1;
55204 +               unsigned inep14:1;
55205 +               unsigned inep15:1;
55206 +               /** OUT Endpoint bits */
55207 +               unsigned outep0:1;
55208 +               unsigned outep1:1;
55209 +               unsigned outep2:1;
55210 +               unsigned outep3:1;
55211 +               unsigned outep4:1;
55212 +               unsigned outep5:1;
55213 +               unsigned outep6:1;
55214 +               unsigned outep7:1;
55215 +               unsigned outep8:1;
55216 +               unsigned outep9:1;
55217 +               unsigned outep10:1;
55218 +               unsigned outep11:1;
55219 +               unsigned outep12:1;
55220 +               unsigned outep13:1;
55221 +               unsigned outep14:1;
55222 +               unsigned outep15:1;
55223 +       } b;
55224 +} daint_data_t;
55225 +
55226 +/**
55227 + * This union represents the bit fields in the Device IN Token Queue
55228 + * Read Registers.
55229 + * - Read the register into the <i>d32</i> member.
55230 + * - READ-ONLY Register
55231 + */
55232 +typedef union dtknq1_data {
55233 +       /** raw register data */
55234 +       uint32_t d32;
55235 +       /** register bits */
55236 +       struct {
55237 +               /** In Token Queue Write Pointer */
55238 +               unsigned intknwptr:5;
55239 +               /** Reserved */
55240 +               unsigned reserved05_06:2;
55241 +               /** write pointer has wrapped. */
55242 +               unsigned wrap_bit:1;
55243 +               /** EP Numbers of IN Tokens 0 ... 4 */
55244 +               unsigned epnums0_5:24;
55245 +       } b;
55246 +} dtknq1_data_t;
55247 +
55248 +/**
55249 + * This union represents Threshold control Register
55250 + * - Read and write the register into the <i>d32</i> member.
55251 + * - READ-WRITABLE Register
55252 + */
55253 +typedef union dthrctl_data {
55254 +       /** raw register data */
55255 +       uint32_t d32;
55256 +       /** register bits */
55257 +       struct {
55258 +               /** non ISO Tx Thr. Enable */
55259 +               unsigned non_iso_thr_en:1;
55260 +               /** ISO Tx Thr. Enable */
55261 +               unsigned iso_thr_en:1;
55262 +               /** Tx Thr. Length */
55263 +               unsigned tx_thr_len:9;
55264 +               /** AHB Threshold ratio */
55265 +               unsigned ahb_thr_ratio:2;
55266 +               /** Reserved */
55267 +               unsigned reserved13_15:3;
55268 +               /** Rx Thr. Enable */
55269 +               unsigned rx_thr_en:1;
55270 +               /** Rx Thr. Length */
55271 +               unsigned rx_thr_len:9;
55272 +               unsigned reserved26:1;
55273 +               /** Arbiter Parking Enable*/
55274 +               unsigned arbprken:1;
55275 +               /** Reserved */
55276 +               unsigned reserved28_31:4;
55277 +       } b;
55278 +} dthrctl_data_t;
55279 +
55280 +/**
55281 + * Device Logical IN Endpoint-Specific Registers. <i>Offsets
55282 + * 900h-AFCh</i>
55283 + *
55284 + * There will be one set of endpoint registers per logical endpoint
55285 + * implemented.
55286 + *
55287 + * <i>These registers are visible only in Device mode and must not be
55288 + * accessed in Host mode, as the results are unknown.</i>
55289 + */
55290 +typedef struct dwc_otg_dev_in_ep_regs {
55291 +       /** Device IN Endpoint Control Register. <i>Offset:900h +
55292 +        * (ep_num * 20h) + 00h</i> */
55293 +       volatile uint32_t diepctl;
55294 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
55295 +       uint32_t reserved04;
55296 +       /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
55297 +        * (ep_num * 20h) + 08h</i> */
55298 +       volatile uint32_t diepint;
55299 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
55300 +       uint32_t reserved0C;
55301 +       /** Device IN Endpoint Transfer Size
55302 +        * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
55303 +       volatile uint32_t dieptsiz;
55304 +       /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
55305 +        * (ep_num * 20h) + 14h</i> */
55306 +       volatile uint32_t diepdma;
55307 +       /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
55308 +        * (ep_num * 20h) + 18h</i> */
55309 +       volatile uint32_t dtxfsts;
55310 +       /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h +
55311 +        * (ep_num * 20h) + 1Ch</i> */
55312 +       volatile uint32_t diepdmab;
55313 +} dwc_otg_dev_in_ep_regs_t;
55314 +
55315 +/**
55316 + * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
55317 + * B00h-CFCh</i>
55318 + *
55319 + * There will be one set of endpoint registers per logical endpoint
55320 + * implemented.
55321 + *
55322 + * <i>These registers are visible only in Device mode and must not be
55323 + * accessed in Host mode, as the results are unknown.</i>
55324 + */
55325 +typedef struct dwc_otg_dev_out_ep_regs {
55326 +       /** Device OUT Endpoint Control Register. <i>Offset:B00h +
55327 +        * (ep_num * 20h) + 00h</i> */
55328 +       volatile uint32_t doepctl;
55329 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */
55330 +       uint32_t reserved04;
55331 +       /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
55332 +        * (ep_num * 20h) + 08h</i> */
55333 +       volatile uint32_t doepint;
55334 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
55335 +       uint32_t reserved0C;
55336 +       /** Device OUT Endpoint Transfer Size Register. <i>Offset:
55337 +        * B00h + (ep_num * 20h) + 10h</i> */
55338 +       volatile uint32_t doeptsiz;
55339 +       /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
55340 +        * + (ep_num * 20h) + 14h</i> */
55341 +       volatile uint32_t doepdma;
55342 +       /** Reserved. <i>Offset:B00h +   * (ep_num * 20h) + 18h</i> */
55343 +       uint32_t unused;
55344 +       /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h
55345 +        * + (ep_num * 20h) + 1Ch</i> */
55346 +       uint32_t doepdmab;
55347 +} dwc_otg_dev_out_ep_regs_t;
55348 +
55349 +/**
55350 + * This union represents the bit fields in the Device EP Control
55351 + * Register.  Read the register into the <i>d32</i> member then
55352 + * set/clear the bits using the <i>b</i>it elements.
55353 + */
55354 +typedef union depctl_data {
55355 +       /** raw register data */
55356 +       uint32_t d32;
55357 +       /** register bits */
55358 +       struct {
55359 +               /** Maximum Packet Size
55360 +                * IN/OUT EPn
55361 +                * IN/OUT EP0 - 2 bits
55362 +                *       2'b00: 64 Bytes
55363 +                *       2'b01: 32
55364 +                *       2'b10: 16
55365 +                *       2'b11: 8 */
55366 +               unsigned mps:11;
55367 +#define DWC_DEP0CTL_MPS_64      0
55368 +#define DWC_DEP0CTL_MPS_32      1
55369 +#define DWC_DEP0CTL_MPS_16      2
55370 +#define DWC_DEP0CTL_MPS_8       3
55371 +
55372 +               /** Next Endpoint
55373 +                * IN EPn/IN EP0
55374 +                * OUT EPn/OUT EP0 - reserved */
55375 +               unsigned nextep:4;
55376 +
55377 +               /** USB Active Endpoint */
55378 +               unsigned usbactep:1;
55379 +
55380 +               /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
55381 +                * This field contains the PID of the packet going to
55382 +                * be received or transmitted on this endpoint. The
55383 +                * application should program the PID of the first
55384 +                * packet going to be received or transmitted on this
55385 +                * endpoint , after the endpoint is
55386 +                * activated. Application use the SetD1PID and
55387 +                * SetD0PID fields of this register to program either
55388 +                * D0 or D1 PID.
55389 +                *
55390 +                * The encoding for this field is
55391 +                *       - 0: D0
55392 +                *       - 1: D1
55393 +                */
55394 +               unsigned dpid:1;
55395 +
55396 +               /** NAK Status */
55397 +               unsigned naksts:1;
55398 +
55399 +               /** Endpoint Type
55400 +                *      2'b00: Control
55401 +                *      2'b01: Isochronous
55402 +                *      2'b10: Bulk
55403 +                *      2'b11: Interrupt */
55404 +               unsigned eptype:2;
55405 +
55406 +               /** Snoop Mode
55407 +                * OUT EPn/OUT EP0
55408 +                * IN EPn/IN EP0 - reserved */
55409 +               unsigned snp:1;
55410 +
55411 +               /** Stall Handshake */
55412 +               unsigned stall:1;
55413 +
55414 +               /** Tx Fifo Number
55415 +                * IN EPn/IN EP0
55416 +                * OUT EPn/OUT EP0 - reserved */
55417 +               unsigned txfnum:4;
55418 +
55419 +               /** Clear NAK */
55420 +               unsigned cnak:1;
55421 +               /** Set NAK */
55422 +               unsigned snak:1;
55423 +               /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
55424 +                * Writing to this field sets the Endpoint DPID (DPID)
55425 +                * field in this register to DATA0. Set Even
55426 +                * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
55427 +                * Writing to this field sets the Even/Odd
55428 +                * (micro)frame (EO_FrNum) field to even (micro)
55429 +                * frame.
55430 +                */
55431 +               unsigned setd0pid:1;
55432 +               /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
55433 +                * Writing to this field sets the Endpoint DPID (DPID)
55434 +                * field in this register to DATA1 Set Odd
55435 +                * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
55436 +                * Writing to this field sets the Even/Odd
55437 +                * (micro)frame (EO_FrNum) field to odd (micro) frame.
55438 +                */
55439 +               unsigned setd1pid:1;
55440 +
55441 +               /** Endpoint Disable */
55442 +               unsigned epdis:1;
55443 +               /** Endpoint Enable */
55444 +               unsigned epena:1;
55445 +       } b;
55446 +} depctl_data_t;
55447 +
55448 +/**
55449 + * This union represents the bit fields in the Device EP Transfer
55450 + * Size Register.  Read the register into the <i>d32</i> member then
55451 + * set/clear the bits using the <i>b</i>it elements.
55452 + */
55453 +typedef union deptsiz_data {
55454 +               /** raw register data */
55455 +       uint32_t d32;
55456 +               /** register bits */
55457 +       struct {
55458 +               /** Transfer size */
55459 +               unsigned xfersize:19;
55460 +/** Max packet count for EP (pow(2,10)-1) */
55461 +#define MAX_PKT_CNT 1023
55462 +               /** Packet Count */
55463 +               unsigned pktcnt:10;
55464 +               /** Multi Count - Periodic IN endpoints */
55465 +               unsigned mc:2;
55466 +               unsigned reserved:1;
55467 +       } b;
55468 +} deptsiz_data_t;
55469 +
55470 +/**
55471 + * This union represents the bit fields in the Device EP 0 Transfer
55472 + * Size Register.  Read the register into the <i>d32</i> member then
55473 + * set/clear the bits using the <i>b</i>it elements.
55474 + */
55475 +typedef union deptsiz0_data {
55476 +               /** raw register data */
55477 +       uint32_t d32;
55478 +               /** register bits */
55479 +       struct {
55480 +               /** Transfer size */
55481 +               unsigned xfersize:7;
55482 +                               /** Reserved */
55483 +               unsigned reserved7_18:12;
55484 +               /** Packet Count */
55485 +               unsigned pktcnt:2;
55486 +                               /** Reserved */
55487 +               unsigned reserved21_28:8;
55488 +                               /**Setup Packet Count (DOEPTSIZ0 Only) */
55489 +               unsigned supcnt:2;
55490 +               unsigned reserved31;
55491 +       } b;
55492 +} deptsiz0_data_t;
55493 +
55494 +/////////////////////////////////////////////////
55495 +// DMA Descriptor Specific Structures
55496 +//
55497 +
55498 +/** Buffer status definitions */
55499 +
55500 +#define BS_HOST_READY  0x0
55501 +#define BS_DMA_BUSY            0x1
55502 +#define BS_DMA_DONE            0x2
55503 +#define BS_HOST_BUSY   0x3
55504 +
55505 +/** Receive/Transmit status definitions */
55506 +
55507 +#define RTS_SUCCESS            0x0
55508 +#define RTS_BUFFLUSH   0x1
55509 +#define RTS_RESERVED   0x2
55510 +#define RTS_BUFERR             0x3
55511 +
55512 +/**
55513 + * This union represents the bit fields in the DMA Descriptor
55514 + * status quadlet. Read the quadlet into the <i>d32</i> member then
55515 + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
55516 + * <i>b_iso_in</i> elements.
55517 + */
55518 +typedef union dev_dma_desc_sts {
55519 +               /** raw register data */
55520 +       uint32_t d32;
55521 +               /** quadlet bits */
55522 +       struct {
55523 +               /** Received number of bytes */
55524 +               unsigned bytes:16;
55525 +               /** NAK bit - only for OUT EPs */
55526 +               unsigned nak:1;
55527 +               unsigned reserved17_22:6;
55528 +               /** Multiple Transfer - only for OUT EPs */
55529 +               unsigned mtrf:1;
55530 +               /** Setup Packet received - only for OUT EPs */
55531 +               unsigned sr:1;
55532 +               /** Interrupt On Complete */
55533 +               unsigned ioc:1;
55534 +               /** Short Packet */
55535 +               unsigned sp:1;
55536 +               /** Last */
55537 +               unsigned l:1;
55538 +               /** Receive Status */
55539 +               unsigned sts:2;
55540 +               /** Buffer Status */
55541 +               unsigned bs:2;
55542 +       } b;
55543 +
55544 +//#ifdef DWC_EN_ISOC
55545 +               /** iso out quadlet bits */
55546 +       struct {
55547 +               /** Received number of bytes */
55548 +               unsigned rxbytes:11;
55549 +
55550 +               unsigned reserved11:1;
55551 +               /** Frame Number */
55552 +               unsigned framenum:11;
55553 +               /** Received ISO Data PID */
55554 +               unsigned pid:2;
55555 +               /** Interrupt On Complete */
55556 +               unsigned ioc:1;
55557 +               /** Short Packet */
55558 +               unsigned sp:1;
55559 +               /** Last */
55560 +               unsigned l:1;
55561 +               /** Receive Status */
55562 +               unsigned rxsts:2;
55563 +               /** Buffer Status */
55564 +               unsigned bs:2;
55565 +       } b_iso_out;
55566 +
55567 +               /** iso in quadlet bits */
55568 +       struct {
55569 +               /** Transmited number of bytes */
55570 +               unsigned txbytes:12;
55571 +               /** Frame Number */
55572 +               unsigned framenum:11;
55573 +               /** Transmited ISO Data PID */
55574 +               unsigned pid:2;
55575 +               /** Interrupt On Complete */
55576 +               unsigned ioc:1;
55577 +               /** Short Packet */
55578 +               unsigned sp:1;
55579 +               /** Last */
55580 +               unsigned l:1;
55581 +               /** Transmit Status */
55582 +               unsigned txsts:2;
55583 +               /** Buffer Status */
55584 +               unsigned bs:2;
55585 +       } b_iso_in;
55586 +//#endif                                /* DWC_EN_ISOC */
55587 +} dev_dma_desc_sts_t;
55588 +
55589 +/**
55590 + * DMA Descriptor structure
55591 + *
55592 + * DMA Descriptor structure contains two quadlets:
55593 + * Status quadlet and Data buffer pointer.
55594 + */
55595 +typedef struct dwc_otg_dev_dma_desc {
55596 +       /** DMA Descriptor status quadlet */
55597 +       dev_dma_desc_sts_t status;
55598 +       /** DMA Descriptor data buffer pointer */
55599 +       uint32_t buf;
55600 +} dwc_otg_dev_dma_desc_t;
55601 +
55602 +/**
55603 + * The dwc_otg_dev_if structure contains information needed to manage
55604 + * the DWC_otg controller acting in device mode. It represents the
55605 + * programming view of the device-specific aspects of the controller.
55606 + */
55607 +typedef struct dwc_otg_dev_if {
55608 +       /** Pointer to device Global registers.
55609 +        * Device Global Registers starting at offset 800h
55610 +        */
55611 +       dwc_otg_device_global_regs_t *dev_global_regs;
55612 +#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
55613 +
55614 +       /**
55615 +        * Device Logical IN Endpoint-Specific Registers 900h-AFCh
55616 +        */
55617 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
55618 +#define DWC_DEV_IN_EP_REG_OFFSET 0x900
55619 +#define DWC_EP_REG_OFFSET 0x20
55620 +
55621 +       /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
55622 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
55623 +#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
55624 +
55625 +       /* Device configuration information */
55626 +       uint8_t speed;                           /**< Device Speed      0: Unknown, 1: LS, 2:FS, 3: HS */
55627 +       uint8_t num_in_eps;              /**< Number # of Tx EP range: 0-15 exept ep0 */
55628 +       uint8_t num_out_eps;             /**< Number # of Rx EP range: 0-15 exept ep 0*/
55629 +
55630 +       /** Size of periodic FIFOs (Bytes) */
55631 +       uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];
55632 +
55633 +       /** Size of Tx FIFOs (Bytes) */
55634 +       uint16_t tx_fifo_size[MAX_TX_FIFOS];
55635 +
55636 +       /** Thresholding enable flags and length varaiables **/
55637 +       uint16_t rx_thr_en;
55638 +       uint16_t iso_tx_thr_en;
55639 +       uint16_t non_iso_tx_thr_en;
55640 +
55641 +       uint16_t rx_thr_length;
55642 +       uint16_t tx_thr_length;
55643 +
55644 +       /**
55645 +        * Pointers to the DMA Descriptors for EP0 Control
55646 +        * transfers (virtual and physical)
55647 +        */
55648 +
55649 +       /** 2 descriptors for SETUP packets */
55650 +       dwc_dma_t dma_setup_desc_addr[2];
55651 +       dwc_otg_dev_dma_desc_t *setup_desc_addr[2];
55652 +
55653 +       /** Pointer to Descriptor with latest SETUP packet */
55654 +       dwc_otg_dev_dma_desc_t *psetup;
55655 +
55656 +       /** Index of current SETUP handler descriptor */
55657 +       uint32_t setup_desc_index;
55658 +
55659 +       /** Descriptor for Data In or Status In phases */
55660 +       dwc_dma_t dma_in_desc_addr;
55661 +       dwc_otg_dev_dma_desc_t *in_desc_addr;
55662 +
55663 +       /** Descriptor for Data Out or Status Out phases */
55664 +       dwc_dma_t dma_out_desc_addr;
55665 +       dwc_otg_dev_dma_desc_t *out_desc_addr;
55666 +
55667 +       /** Setup Packet Detected - if set clear NAK when queueing */
55668 +       uint32_t spd;
55669 +       /** Isoc ep pointer on which incomplete happens */
55670 +       void *isoc_ep;
55671 +
55672 +} dwc_otg_dev_if_t;
55673 +
55674 +/////////////////////////////////////////////////
55675 +// Host Mode Register Structures
55676 +//
55677 +/**
55678 + * The Host Global Registers structure defines the size and relative
55679 + * field offsets for the Host Mode Global Registers.  Host Global
55680 + * Registers offsets 400h-7FFh.
55681 +*/
55682 +typedef struct dwc_otg_host_global_regs {
55683 +       /** Host Configuration Register.   <i>Offset: 400h</i> */
55684 +       volatile uint32_t hcfg;
55685 +       /** Host Frame Interval Register.       <i>Offset: 404h</i> */
55686 +       volatile uint32_t hfir;
55687 +       /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
55688 +       volatile uint32_t hfnum;
55689 +       /** Reserved.   <i>Offset: 40Ch</i> */
55690 +       uint32_t reserved40C;
55691 +       /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
55692 +       volatile uint32_t hptxsts;
55693 +       /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
55694 +       volatile uint32_t haint;
55695 +       /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
55696 +       volatile uint32_t haintmsk;
55697 +       /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
55698 +       volatile uint32_t hflbaddr;
55699 +} dwc_otg_host_global_regs_t;
55700 +
55701 +/**
55702 + * This union represents the bit fields in the Host Configuration Register.
55703 + * Read the register into the <i>d32</i> member then set/clear the bits using
55704 + * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
55705 + */
55706 +typedef union hcfg_data {
55707 +       /** raw register data */
55708 +       uint32_t d32;
55709 +
55710 +       /** register bits */
55711 +       struct {
55712 +               /** FS/LS Phy Clock Select */
55713 +               unsigned fslspclksel:2;
55714 +#define DWC_HCFG_30_60_MHZ 0
55715 +#define DWC_HCFG_48_MHZ           1
55716 +#define DWC_HCFG_6_MHZ    2
55717 +
55718 +               /** FS/LS Only Support */
55719 +               unsigned fslssupp:1;
55720 +               unsigned reserved3_6:4;
55721 +               /** Enable 32-KHz Suspend Mode */
55722 +               unsigned ena32khzs:1;
55723 +               /** Resume Validation Periiod */
55724 +               unsigned resvalid:8;
55725 +               unsigned reserved16_22:7;
55726 +               /** Enable Scatter/gather DMA in Host mode */
55727 +               unsigned descdma:1;
55728 +               /** Frame List Entries */
55729 +               unsigned frlisten:2;
55730 +               /** Enable Periodic Scheduling */
55731 +               unsigned perschedena:1;
55732 +               unsigned reserved27_30:4;
55733 +               unsigned modechtimen:1;
55734 +       } b;
55735 +} hcfg_data_t;
55736 +
55737 +/**
55738 + * This union represents the bit fields in the Host Frame Remaing/Number
55739 + * Register. 
55740 + */
55741 +typedef union hfir_data {
55742 +       /** raw register data */
55743 +       uint32_t d32;
55744 +
55745 +       /** register bits */
55746 +       struct {
55747 +               unsigned frint:16;
55748 +               unsigned hfirrldctrl:1;
55749 +               unsigned reserved:15;
55750 +       } b;
55751 +} hfir_data_t;
55752 +
55753 +/**
55754 + * This union represents the bit fields in the Host Frame Remaing/Number
55755 + * Register. 
55756 + */
55757 +typedef union hfnum_data {
55758 +       /** raw register data */
55759 +       uint32_t d32;
55760 +
55761 +       /** register bits */
55762 +       struct {
55763 +               unsigned frnum:16;
55764 +#define DWC_HFNUM_MAX_FRNUM 0x3FFF
55765 +               unsigned frrem:16;
55766 +       } b;
55767 +} hfnum_data_t;
55768 +
55769 +typedef union hptxsts_data {
55770 +       /** raw register data */
55771 +       uint32_t d32;
55772 +
55773 +       /** register bits */
55774 +       struct {
55775 +               unsigned ptxfspcavail:16;
55776 +               unsigned ptxqspcavail:8;
55777 +               /** Top of the Periodic Transmit Request Queue
55778 +                *      - bit 24 - Terminate (last entry for the selected channel)
55779 +                *      - bits 26:25 - Token Type
55780 +                *        - 2'b00 - Zero length
55781 +                *        - 2'b01 - Ping
55782 +                *        - 2'b10 - Disable
55783 +                *      - bits 30:27 - Channel Number
55784 +                *      - bit 31 - Odd/even microframe
55785 +                */
55786 +               unsigned ptxqtop_terminate:1;
55787 +               unsigned ptxqtop_token:2;
55788 +               unsigned ptxqtop_chnum:4;
55789 +               unsigned ptxqtop_odd:1;
55790 +       } b;
55791 +} hptxsts_data_t;
55792 +
55793 +/**
55794 + * This union represents the bit fields in the Host Port Control and Status
55795 + * Register. Read the register into the <i>d32</i> member then set/clear the
55796 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55797 + * hprt0 register.
55798 + */
55799 +typedef union hprt0_data {
55800 +       /** raw register data */
55801 +       uint32_t d32;
55802 +       /** register bits */
55803 +       struct {
55804 +               unsigned prtconnsts:1;
55805 +               unsigned prtconndet:1;
55806 +               unsigned prtena:1;
55807 +               unsigned prtenchng:1;
55808 +               unsigned prtovrcurract:1;
55809 +               unsigned prtovrcurrchng:1;
55810 +               unsigned prtres:1;
55811 +               unsigned prtsusp:1;
55812 +               unsigned prtrst:1;
55813 +               unsigned reserved9:1;
55814 +               unsigned prtlnsts:2;
55815 +               unsigned prtpwr:1;
55816 +               unsigned prttstctl:4;
55817 +               unsigned prtspd:2;
55818 +#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
55819 +#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
55820 +#define DWC_HPRT0_PRTSPD_LOW_SPEED     2
55821 +               unsigned reserved19_31:13;
55822 +       } b;
55823 +} hprt0_data_t;
55824 +
55825 +/**
55826 + * This union represents the bit fields in the Host All Interrupt
55827 + * Register. 
55828 + */
55829 +typedef union haint_data {
55830 +       /** raw register data */
55831 +       uint32_t d32;
55832 +       /** register bits */
55833 +       struct {
55834 +               unsigned ch0:1;
55835 +               unsigned ch1:1;
55836 +               unsigned ch2:1;
55837 +               unsigned ch3:1;
55838 +               unsigned ch4:1;
55839 +               unsigned ch5:1;
55840 +               unsigned ch6:1;
55841 +               unsigned ch7:1;
55842 +               unsigned ch8:1;
55843 +               unsigned ch9:1;
55844 +               unsigned ch10:1;
55845 +               unsigned ch11:1;
55846 +               unsigned ch12:1;
55847 +               unsigned ch13:1;
55848 +               unsigned ch14:1;
55849 +               unsigned ch15:1;
55850 +               unsigned reserved:16;
55851 +       } b;
55852 +
55853 +       struct {
55854 +               unsigned chint:16;
55855 +               unsigned reserved:16;
55856 +       } b2;
55857 +} haint_data_t;
55858 +
55859 +/**
55860 + * This union represents the bit fields in the Host All Interrupt
55861 + * Register. 
55862 + */
55863 +typedef union haintmsk_data {
55864 +       /** raw register data */
55865 +       uint32_t d32;
55866 +       /** register bits */
55867 +       struct {
55868 +               unsigned ch0:1;
55869 +               unsigned ch1:1;
55870 +               unsigned ch2:1;
55871 +               unsigned ch3:1;
55872 +               unsigned ch4:1;
55873 +               unsigned ch5:1;
55874 +               unsigned ch6:1;
55875 +               unsigned ch7:1;
55876 +               unsigned ch8:1;
55877 +               unsigned ch9:1;
55878 +               unsigned ch10:1;
55879 +               unsigned ch11:1;
55880 +               unsigned ch12:1;
55881 +               unsigned ch13:1;
55882 +               unsigned ch14:1;
55883 +               unsigned ch15:1;
55884 +               unsigned reserved:16;
55885 +       } b;
55886 +
55887 +       struct {
55888 +               unsigned chint:16;
55889 +               unsigned reserved:16;
55890 +       } b2;
55891 +} haintmsk_data_t;
55892 +
55893 +/**
55894 + * Host Channel Specific Registers. <i>500h-5FCh</i>
55895 + */
55896 +typedef struct dwc_otg_hc_regs {
55897 +       /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
55898 +       volatile uint32_t hcchar;
55899 +       /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
55900 +       volatile uint32_t hcsplt;
55901 +       /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
55902 +       volatile uint32_t hcint;
55903 +       /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
55904 +       volatile uint32_t hcintmsk;
55905 +       /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
55906 +       volatile uint32_t hctsiz;
55907 +       /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
55908 +       volatile uint32_t hcdma;
55909 +       volatile uint32_t reserved;
55910 +       /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
55911 +       volatile uint32_t hcdmab;
55912 +} dwc_otg_hc_regs_t;
55913 +
55914 +/**
55915 + * This union represents the bit fields in the Host Channel Characteristics
55916 + * Register. Read the register into the <i>d32</i> member then set/clear the
55917 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55918 + * hcchar register.
55919 + */
55920 +typedef union hcchar_data {
55921 +       /** raw register data */
55922 +       uint32_t d32;
55923 +
55924 +       /** register bits */
55925 +       struct {
55926 +               /** Maximum packet size in bytes */
55927 +               unsigned mps:11;
55928 +
55929 +               /** Endpoint number */
55930 +               unsigned epnum:4;
55931 +
55932 +               /** 0: OUT, 1: IN */
55933 +               unsigned epdir:1;
55934 +
55935 +               unsigned reserved:1;
55936 +
55937 +               /** 0: Full/high speed device, 1: Low speed device */
55938 +               unsigned lspddev:1;
55939 +
55940 +               /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
55941 +               unsigned eptype:2;
55942 +
55943 +               /** Packets per frame for periodic transfers. 0 is reserved. */
55944 +               unsigned multicnt:2;
55945 +
55946 +               /** Device address */
55947 +               unsigned devaddr:7;
55948 +
55949 +               /**
55950 +                * Frame to transmit periodic transaction.
55951 +                * 0: even, 1: odd
55952 +                */
55953 +               unsigned oddfrm:1;
55954 +
55955 +               /** Channel disable */
55956 +               unsigned chdis:1;
55957 +
55958 +               /** Channel enable */
55959 +               unsigned chen:1;
55960 +       } b;
55961 +} hcchar_data_t;
55962 +
55963 +typedef union hcsplt_data {
55964 +       /** raw register data */
55965 +       uint32_t d32;
55966 +
55967 +       /** register bits */
55968 +       struct {
55969 +               /** Port Address */
55970 +               unsigned prtaddr:7;
55971 +
55972 +               /** Hub Address */
55973 +               unsigned hubaddr:7;
55974 +
55975 +               /** Transaction Position */
55976 +               unsigned xactpos:2;
55977 +#define DWC_HCSPLIT_XACTPOS_MID 0
55978 +#define DWC_HCSPLIT_XACTPOS_END 1
55979 +#define DWC_HCSPLIT_XACTPOS_BEGIN 2
55980 +#define DWC_HCSPLIT_XACTPOS_ALL 3
55981 +
55982 +               /** Do Complete Split */
55983 +               unsigned compsplt:1;
55984 +
55985 +               /** Reserved */
55986 +               unsigned reserved:14;
55987 +
55988 +               /** Split Enble */
55989 +               unsigned spltena:1;
55990 +       } b;
55991 +} hcsplt_data_t;
55992 +
55993 +/**
55994 + * This union represents the bit fields in the Host All Interrupt
55995 + * Register. 
55996 + */
55997 +typedef union hcint_data {
55998 +       /** raw register data */
55999 +       uint32_t d32;
56000 +       /** register bits */
56001 +       struct {
56002 +               /** Transfer Complete */
56003 +               unsigned xfercomp:1;
56004 +               /** Channel Halted */
56005 +               unsigned chhltd:1;
56006 +               /** AHB Error */
56007 +               unsigned ahberr:1;
56008 +               /** STALL Response Received */
56009 +               unsigned stall:1;
56010 +               /** NAK Response Received */
56011 +               unsigned nak:1;
56012 +               /** ACK Response Received */
56013 +               unsigned ack:1;
56014 +               /** NYET Response Received */
56015 +               unsigned nyet:1;
56016 +               /** Transaction Err */
56017 +               unsigned xacterr:1;
56018 +               /** Babble Error */
56019 +               unsigned bblerr:1;
56020 +               /** Frame Overrun */
56021 +               unsigned frmovrun:1;
56022 +               /** Data Toggle Error */
56023 +               unsigned datatglerr:1;
56024 +               /** Buffer Not Available (only for DDMA mode) */
56025 +               unsigned bna:1;
56026 +               /** Exessive transaction error (only for DDMA mode) */
56027 +               unsigned xcs_xact:1;
56028 +               /** Frame List Rollover interrupt */
56029 +               unsigned frm_list_roll:1;
56030 +               /** Reserved */
56031 +               unsigned reserved14_31:18;
56032 +       } b;
56033 +} hcint_data_t;
56034 +
56035 +/**
56036 + * This union represents the bit fields in the Host Channel Interrupt Mask
56037 + * Register. Read the register into the <i>d32</i> member then set/clear the
56038 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
56039 + * hcintmsk register.
56040 + */
56041 +typedef union hcintmsk_data {
56042 +       /** raw register data */
56043 +       uint32_t d32;
56044 +
56045 +       /** register bits */
56046 +       struct {
56047 +               unsigned xfercompl:1;
56048 +               unsigned chhltd:1;
56049 +               unsigned ahberr:1;
56050 +               unsigned stall:1;
56051 +               unsigned nak:1;
56052 +               unsigned ack:1;
56053 +               unsigned nyet:1;
56054 +               unsigned xacterr:1;
56055 +               unsigned bblerr:1;
56056 +               unsigned frmovrun:1;
56057 +               unsigned datatglerr:1;
56058 +               unsigned bna:1;
56059 +               unsigned xcs_xact:1;
56060 +               unsigned frm_list_roll:1;
56061 +               unsigned reserved14_31:18;
56062 +       } b;
56063 +} hcintmsk_data_t;
56064 +
56065 +/**
56066 + * This union represents the bit fields in the Host Channel Transfer Size
56067 + * Register. Read the register into the <i>d32</i> member then set/clear the
56068 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
56069 + * hcchar register.
56070 + */
56071 +
56072 +typedef union hctsiz_data {
56073 +       /** raw register data */
56074 +       uint32_t d32;
56075 +
56076 +       /** register bits */
56077 +       struct {
56078 +               /** Total transfer size in bytes */
56079 +               unsigned xfersize:19;
56080 +
56081 +               /** Data packets to transfer */
56082 +               unsigned pktcnt:10;
56083 +
56084 +               /**
56085 +                * Packet ID for next data packet
56086 +                * 0: DATA0
56087 +                * 1: DATA2
56088 +                * 2: DATA1
56089 +                * 3: MDATA (non-Control), SETUP (Control)
56090 +                */
56091 +               unsigned pid:2;
56092 +#define DWC_HCTSIZ_DATA0 0
56093 +#define DWC_HCTSIZ_DATA1 2
56094 +#define DWC_HCTSIZ_DATA2 1
56095 +#define DWC_HCTSIZ_MDATA 3
56096 +#define DWC_HCTSIZ_SETUP 3
56097 +
56098 +               /** Do PING protocol when 1 */
56099 +               unsigned dopng:1;
56100 +       } b;
56101 +
56102 +       /** register bits */
56103 +       struct {
56104 +               /** Scheduling information */
56105 +               unsigned schinfo:8;
56106 +
56107 +               /** Number of transfer descriptors.
56108 +                * Max value:
56109 +                * 64 in general,
56110 +                * 256 only for HS isochronous endpoint.
56111 +                */
56112 +               unsigned ntd:8;
56113 +
56114 +               /** Data packets to transfer */
56115 +               unsigned reserved16_28:13;
56116 +
56117 +               /**
56118 +                * Packet ID for next data packet
56119 +                * 0: DATA0
56120 +                * 1: DATA2
56121 +                * 2: DATA1
56122 +                * 3: MDATA (non-Control)
56123 +                */
56124 +               unsigned pid:2;
56125 +
56126 +               /** Do PING protocol when 1 */
56127 +               unsigned dopng:1;
56128 +       } b_ddma;
56129 +} hctsiz_data_t;
56130 +
56131 +/**
56132 + * This union represents the bit fields in the Host DMA Address 
56133 + * Register used in Descriptor DMA mode.
56134 + */
56135 +typedef union hcdma_data {
56136 +       /** raw register data */
56137 +       uint32_t d32;
56138 +       /** register bits */
56139 +       struct {
56140 +               unsigned reserved0_2:3;
56141 +               /** Current Transfer Descriptor. Not used for ISOC */
56142 +               unsigned ctd:8;
56143 +               /** Start Address of Descriptor List */
56144 +               unsigned dma_addr:21;
56145 +       } b;
56146 +} hcdma_data_t;
56147 +
56148 +/**
56149 + * This union represents the bit fields in the DMA Descriptor
56150 + * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
56151 + * set/clear the bits using the <i>b</i>it elements.
56152 + */
56153 +typedef union host_dma_desc_sts {
56154 +       /** raw register data */
56155 +       uint32_t d32;
56156 +       /** quadlet bits */
56157 +
56158 +       /* for non-isochronous  */
56159 +       struct {
56160 +               /** Number of bytes */
56161 +               unsigned n_bytes:17;
56162 +               /** QTD offset to jump when Short Packet received - only for IN EPs */
56163 +               unsigned qtd_offset:6;
56164 +               /**
56165 +                * Set to request the core to jump to alternate QTD if
56166 +                * Short Packet received - only for IN EPs
56167 +                */
56168 +               unsigned a_qtd:1;
56169 +                /**
56170 +                 * Setup Packet bit. When set indicates that buffer contains
56171 +                 * setup packet.
56172 +                 */
56173 +               unsigned sup:1;
56174 +               /** Interrupt On Complete */
56175 +               unsigned ioc:1;
56176 +               /** End of List */
56177 +               unsigned eol:1;
56178 +               unsigned reserved27:1;
56179 +               /** Rx/Tx Status */
56180 +               unsigned sts:2;
56181 +#define DMA_DESC_STS_PKTERR    1
56182 +               unsigned reserved30:1;
56183 +               /** Active Bit */
56184 +               unsigned a:1;
56185 +       } b;
56186 +       /* for isochronous */
56187 +       struct {
56188 +               /** Number of bytes */
56189 +               unsigned n_bytes:12;
56190 +               unsigned reserved12_24:13;
56191 +               /** Interrupt On Complete */
56192 +               unsigned ioc:1;
56193 +               unsigned reserved26_27:2;
56194 +               /** Rx/Tx Status */
56195 +               unsigned sts:2;
56196 +               unsigned reserved30:1;
56197 +               /** Active Bit */
56198 +               unsigned a:1;
56199 +       } b_isoc;
56200 +} host_dma_desc_sts_t;
56201 +
56202 +#define        MAX_DMA_DESC_SIZE               131071
56203 +#define MAX_DMA_DESC_NUM_GENERIC       64
56204 +#define MAX_DMA_DESC_NUM_HS_ISOC       256
56205 +#define MAX_FRLIST_EN_NUM              64
56206 +/**
56207 + * Host-mode DMA Descriptor structure
56208 + *
56209 + * DMA Descriptor structure contains two quadlets:
56210 + * Status quadlet and Data buffer pointer.
56211 + */
56212 +typedef struct dwc_otg_host_dma_desc {
56213 +       /** DMA Descriptor status quadlet */
56214 +       host_dma_desc_sts_t status;
56215 +       /** DMA Descriptor data buffer pointer */
56216 +       uint32_t buf;
56217 +} dwc_otg_host_dma_desc_t;
56218 +
56219 +/** OTG Host Interface Structure.
56220 + *
56221 + * The OTG Host Interface Structure structure contains information
56222 + * needed to manage the DWC_otg controller acting in host mode. It
56223 + * represents the programming view of the host-specific aspects of the
56224 + * controller.
56225 + */
56226 +typedef struct dwc_otg_host_if {
56227 +       /** Host Global Registers starting at offset 400h.*/
56228 +       dwc_otg_host_global_regs_t *host_global_regs;
56229 +#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
56230 +
56231 +       /** Host Port 0 Control and Status Register */
56232 +       volatile uint32_t *hprt0;
56233 +#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
56234 +
56235 +       /** Host Channel Specific Registers at offsets 500h-5FCh. */
56236 +       dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
56237 +#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
56238 +#define DWC_OTG_CHAN_REGS_OFFSET 0x20
56239 +
56240 +       /* Host configuration information */
56241 +       /** Number of Host Channels (range: 1-16) */
56242 +       uint8_t num_host_channels;
56243 +       /** Periodic EPs supported (0: no, 1: yes) */
56244 +       uint8_t perio_eps_supported;
56245 +       /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
56246 +       uint16_t perio_tx_fifo_size;
56247 +
56248 +} dwc_otg_host_if_t;
56249 +
56250 +/**
56251 + * This union represents the bit fields in the Power and Clock Gating Control
56252 + * Register. Read the register into the <i>d32</i> member then set/clear the
56253 + * bits using the <i>b</i>it elements.
56254 + */
56255 +typedef union pcgcctl_data {
56256 +       /** raw register data */
56257 +       uint32_t d32;
56258 +
56259 +       /** register bits */
56260 +       struct {
56261 +               /** Stop Pclk */
56262 +               unsigned stoppclk:1;
56263 +               /** Gate Hclk */
56264 +               unsigned gatehclk:1;
56265 +               /** Power Clamp */
56266 +               unsigned pwrclmp:1;
56267 +               /** Reset Power Down Modules */
56268 +               unsigned rstpdwnmodule:1;
56269 +               /** Reserved */
56270 +               unsigned reserved:1;
56271 +               /** Enable Sleep Clock Gating (Enbl_L1Gating) */
56272 +               unsigned enbl_sleep_gating:1;
56273 +               /** PHY In Sleep (PhySleep) */
56274 +               unsigned phy_in_sleep:1;
56275 +               /** Deep Sleep*/
56276 +               unsigned deep_sleep:1;
56277 +               unsigned resetaftsusp:1;
56278 +               unsigned restoremode:1;
56279 +               unsigned enbl_extnd_hiber:1;
56280 +               unsigned extnd_hiber_pwrclmp:1;
56281 +               unsigned extnd_hiber_switch:1;
56282 +               unsigned ess_reg_restored:1;
56283 +               unsigned prt_clk_sel:2;
56284 +               unsigned port_power:1;
56285 +               unsigned max_xcvrselect:2;
56286 +               unsigned max_termsel:1;
56287 +               unsigned mac_dev_addr:7;
56288 +               unsigned p2hd_dev_enum_spd:2;
56289 +               unsigned p2hd_prt_spd:2;
56290 +               unsigned if_dev_mode:1;
56291 +       } b;
56292 +} pcgcctl_data_t;
56293 +
56294 +/**
56295 + * This union represents the bit fields in the Global Data FIFO Software
56296 + * Configuration Register. Read the register into the <i>d32</i> member then
56297 + * set/clear the bits using the <i>b</i>it elements.
56298 + */
56299 +typedef union gdfifocfg_data {
56300 +       /* raw register data */
56301 +       uint32_t d32;
56302 +       /** register bits */
56303 +       struct {
56304 +               /** OTG Data FIFO depth */
56305 +               unsigned gdfifocfg:16;
56306 +               /** Start address of EP info controller */
56307 +               unsigned epinfobase:16;
56308 +       } b;
56309 +} gdfifocfg_data_t;
56310 +
56311 +/**
56312 + * This union represents the bit fields in the Global Power Down Register
56313 + * Register. Read the register into the <i>d32</i> member then set/clear the
56314 + * bits using the <i>b</i>it elements.
56315 + */
56316 +typedef union gpwrdn_data {
56317 +       /* raw register data */
56318 +       uint32_t d32;
56319 +
56320 +       /** register bits */
56321 +       struct {
56322 +               /** PMU Interrupt Select */
56323 +               unsigned pmuintsel:1;
56324 +               /** PMU Active */
56325 +               unsigned pmuactv:1;
56326 +               /** Restore */
56327 +               unsigned restore:1;
56328 +               /** Power Down Clamp */
56329 +               unsigned pwrdnclmp:1;
56330 +               /** Power Down Reset */
56331 +               unsigned pwrdnrstn:1;
56332 +               /** Power Down Switch */
56333 +               unsigned pwrdnswtch:1;
56334 +               /** Disable VBUS */
56335 +               unsigned dis_vbus:1;
56336 +               /** Line State Change */
56337 +               unsigned lnstschng:1;
56338 +               /** Line state change mask */
56339 +               unsigned lnstchng_msk:1;
56340 +               /** Reset Detected */
56341 +               unsigned rst_det:1;
56342 +               /** Reset Detect mask */
56343 +               unsigned rst_det_msk:1;
56344 +               /** Disconnect Detected */
56345 +               unsigned disconn_det:1;
56346 +               /** Disconnect Detect mask */
56347 +               unsigned disconn_det_msk:1;
56348 +               /** Connect Detected*/
56349 +               unsigned connect_det:1;
56350 +               /** Connect Detected Mask*/
56351 +               unsigned connect_det_msk:1;
56352 +               /** SRP Detected */
56353 +               unsigned srp_det:1;
56354 +               /** SRP Detect mask */
56355 +               unsigned srp_det_msk:1;
56356 +               /** Status Change Interrupt */
56357 +               unsigned sts_chngint:1;
56358 +               /** Status Change Interrupt Mask */
56359 +               unsigned sts_chngint_msk:1;
56360 +               /** Line State */
56361 +               unsigned linestate:2;
56362 +               /** Indicates current mode(status of IDDIG signal) */
56363 +               unsigned idsts:1;
56364 +               /** B Session Valid signal status*/
56365 +               unsigned bsessvld:1;
56366 +               /** ADP Event Detected */
56367 +               unsigned adp_int:1;
56368 +               /** Multi Valued ID pin */
56369 +               unsigned mult_val_id_bc:5;
56370 +               /** Reserved 24_31 */
56371 +               unsigned reserved29_31:3;
56372 +       } b;
56373 +} gpwrdn_data_t;
56374 +
56375 +#endif
56376 diff --git a/drivers/usb/host/dwc_otg/test/Makefile b/drivers/usb/host/dwc_otg/test/Makefile
56377 new file mode 100644
56378 index 0000000..fc45375
56379 --- /dev/null
56380 +++ b/drivers/usb/host/dwc_otg/test/Makefile
56381 @@ -0,0 +1,16 @@
56382 +
56383 +PERL=/usr/bin/perl
56384 +PL_TESTS=test_sysfs.pl test_mod_param.pl
56385 +
56386 +.PHONY : test
56387 +test : perl_tests
56388 +
56389 +perl_tests :
56390 +       @echo
56391 +       @echo Running perl tests
56392 +       @for test in $(PL_TESTS); do \
56393 +         if $(PERL) ./$$test ; then \
56394 +           echo "=======> $$test, PASSED" ; \
56395 +         else echo "=======> $$test, FAILED" ; \
56396 +         fi \
56397 +       done
56398 diff --git a/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
56399 new file mode 100644
56400 index 0000000..233b04a
56401 --- /dev/null
56402 +++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
56403 @@ -0,0 +1,337 @@
56404 +package dwc_otg_test;
56405 +
56406 +use strict;
56407 +use Exporter ();
56408 +
56409 +use vars qw(@ISA @EXPORT
56410 +$sysfsdir $paramdir $errors $params 
56411 +);
56412 +
56413 +@ISA = qw(Exporter);
56414 +
56415 +#
56416 +# Globals
56417 +#
56418 +$sysfsdir = "/sys/devices/lm0";
56419 +$paramdir = "/sys/module/dwc_otg";
56420 +$errors = 0;
56421 +
56422 +$params = [
56423 +          {
56424 +           NAME => "otg_cap",
56425 +           DEFAULT => 0,
56426 +           ENUM => [],
56427 +           LOW => 0,
56428 +           HIGH => 2
56429 +          },
56430 +          {
56431 +           NAME => "dma_enable",
56432 +           DEFAULT => 0,
56433 +           ENUM => [],
56434 +           LOW => 0,
56435 +           HIGH => 1
56436 +          },
56437 +          { 
56438 +           NAME => "dma_burst_size",
56439 +           DEFAULT => 32,
56440 +           ENUM => [1, 4, 8, 16, 32, 64, 128, 256],
56441 +           LOW => 1,
56442 +           HIGH => 256
56443 +          },
56444 +          { 
56445 +           NAME => "host_speed",
56446 +           DEFAULT => 0,
56447 +           ENUM => [],
56448 +           LOW => 0,
56449 +           HIGH => 1
56450 +          },
56451 +          { 
56452 +           NAME => "host_support_fs_ls_low_power",
56453 +           DEFAULT => 0,
56454 +           ENUM => [],
56455 +           LOW => 0,
56456 +           HIGH => 1
56457 +          },
56458 +          { 
56459 +           NAME => "host_ls_low_power_phy_clk",
56460 +           DEFAULT => 0,
56461 +           ENUM => [],
56462 +           LOW => 0,
56463 +           HIGH => 1
56464 +          },
56465 +          { 
56466 +           NAME => "dev_speed",
56467 +           DEFAULT => 0,
56468 +           ENUM => [],
56469 +           LOW => 0,
56470 +           HIGH => 1
56471 +          },
56472 +          { 
56473 +           NAME => "enable_dynamic_fifo",
56474 +           DEFAULT => 1,
56475 +           ENUM => [],
56476 +           LOW => 0,
56477 +           HIGH => 1
56478 +          },
56479 +          { 
56480 +           NAME => "data_fifo_size",
56481 +           DEFAULT => 8192,
56482 +           ENUM => [],
56483 +           LOW => 32,
56484 +           HIGH => 32768
56485 +          },
56486 +          { 
56487 +           NAME => "dev_rx_fifo_size",
56488 +           DEFAULT => 1064,
56489 +           ENUM => [],
56490 +           LOW => 16,
56491 +           HIGH => 32768
56492 +          },
56493 +          { 
56494 +           NAME => "dev_nperio_tx_fifo_size",
56495 +           DEFAULT => 1024,
56496 +           ENUM => [],
56497 +           LOW => 16,
56498 +           HIGH => 32768
56499 +          },
56500 +          { 
56501 +           NAME => "dev_perio_tx_fifo_size_1",
56502 +           DEFAULT => 256,
56503 +           ENUM => [],
56504 +           LOW => 4,
56505 +           HIGH => 768
56506 +          },
56507 +          { 
56508 +           NAME => "dev_perio_tx_fifo_size_2",
56509 +           DEFAULT => 256,
56510 +           ENUM => [],
56511 +           LOW => 4,
56512 +           HIGH => 768
56513 +          },
56514 +          { 
56515 +           NAME => "dev_perio_tx_fifo_size_3",
56516 +           DEFAULT => 256,
56517 +           ENUM => [],
56518 +           LOW => 4,
56519 +           HIGH => 768
56520 +          },
56521 +          { 
56522 +           NAME => "dev_perio_tx_fifo_size_4",
56523 +           DEFAULT => 256,
56524 +           ENUM => [],
56525 +           LOW => 4,
56526 +           HIGH => 768
56527 +          },
56528 +          { 
56529 +           NAME => "dev_perio_tx_fifo_size_5",
56530 +           DEFAULT => 256,
56531 +           ENUM => [],
56532 +           LOW => 4,
56533 +           HIGH => 768
56534 +          },
56535 +          { 
56536 +           NAME => "dev_perio_tx_fifo_size_6",
56537 +           DEFAULT => 256,
56538 +           ENUM => [],
56539 +           LOW => 4,
56540 +           HIGH => 768
56541 +          },
56542 +          { 
56543 +           NAME => "dev_perio_tx_fifo_size_7",
56544 +           DEFAULT => 256,
56545 +           ENUM => [],
56546 +           LOW => 4,
56547 +           HIGH => 768
56548 +          },
56549 +          { 
56550 +           NAME => "dev_perio_tx_fifo_size_8",
56551 +           DEFAULT => 256,
56552 +           ENUM => [],
56553 +           LOW => 4,
56554 +           HIGH => 768
56555 +          },
56556 +          { 
56557 +           NAME => "dev_perio_tx_fifo_size_9",
56558 +           DEFAULT => 256,
56559 +           ENUM => [],
56560 +           LOW => 4,
56561 +           HIGH => 768
56562 +          },
56563 +          { 
56564 +           NAME => "dev_perio_tx_fifo_size_10",
56565 +           DEFAULT => 256,
56566 +           ENUM => [],
56567 +           LOW => 4,
56568 +           HIGH => 768
56569 +          },
56570 +          { 
56571 +           NAME => "dev_perio_tx_fifo_size_11",
56572 +           DEFAULT => 256,
56573 +           ENUM => [],
56574 +           LOW => 4,
56575 +           HIGH => 768
56576 +          },
56577 +          { 
56578 +           NAME => "dev_perio_tx_fifo_size_12",
56579 +           DEFAULT => 256,
56580 +           ENUM => [],
56581 +           LOW => 4,
56582 +           HIGH => 768
56583 +          },
56584 +          { 
56585 +           NAME => "dev_perio_tx_fifo_size_13",
56586 +           DEFAULT => 256,
56587 +           ENUM => [],
56588 +           LOW => 4,
56589 +           HIGH => 768
56590 +          },
56591 +          { 
56592 +           NAME => "dev_perio_tx_fifo_size_14",
56593 +           DEFAULT => 256,
56594 +           ENUM => [],
56595 +           LOW => 4,
56596 +           HIGH => 768
56597 +          },
56598 +          { 
56599 +           NAME => "dev_perio_tx_fifo_size_15",
56600 +           DEFAULT => 256,
56601 +           ENUM => [],
56602 +           LOW => 4,
56603 +           HIGH => 768
56604 +          },
56605 +          { 
56606 +           NAME => "host_rx_fifo_size",
56607 +           DEFAULT => 1024,
56608 +           ENUM => [],
56609 +           LOW => 16,
56610 +           HIGH => 32768
56611 +          },
56612 +          { 
56613 +           NAME => "host_nperio_tx_fifo_size",
56614 +           DEFAULT => 1024,
56615 +           ENUM => [],
56616 +           LOW => 16,
56617 +           HIGH => 32768
56618 +          },
56619 +          { 
56620 +           NAME => "host_perio_tx_fifo_size",
56621 +           DEFAULT => 1024,
56622 +           ENUM => [],
56623 +           LOW => 16,
56624 +           HIGH => 32768
56625 +          },
56626 +          { 
56627 +           NAME => "max_transfer_size",
56628 +           DEFAULT => 65535,
56629 +           ENUM => [],
56630 +           LOW => 2047,
56631 +           HIGH => 65535
56632 +          },
56633 +          { 
56634 +           NAME => "max_packet_count",
56635 +           DEFAULT => 511,
56636 +           ENUM => [],
56637 +           LOW => 15,
56638 +           HIGH => 511
56639 +          },
56640 +          { 
56641 +           NAME => "host_channels",
56642 +           DEFAULT => 12,
56643 +           ENUM => [],
56644 +           LOW => 1,
56645 +           HIGH => 16
56646 +          },
56647 +          { 
56648 +           NAME => "dev_endpoints",
56649 +           DEFAULT => 6,
56650 +           ENUM => [],
56651 +           LOW => 1,
56652 +           HIGH => 15
56653 +          },
56654 +          { 
56655 +           NAME => "phy_type",
56656 +           DEFAULT => 1,
56657 +           ENUM => [],
56658 +           LOW => 0,
56659 +           HIGH => 2
56660 +          },
56661 +          { 
56662 +           NAME => "phy_utmi_width",
56663 +           DEFAULT => 16,
56664 +           ENUM => [8, 16],
56665 +           LOW => 8,
56666 +           HIGH => 16
56667 +          },
56668 +          { 
56669 +           NAME => "phy_ulpi_ddr",
56670 +           DEFAULT => 0,
56671 +           ENUM => [],
56672 +           LOW => 0,
56673 +           HIGH => 1
56674 +          },
56675 +         ];
56676 +
56677 +
56678 +#
56679 +#
56680 +sub check_arch {
56681 +  $_ = `uname -m`;
56682 +  chomp;
56683 +  unless (m/armv4tl/) {
56684 +    warn "# \n# Can't execute on $_.  Run on integrator platform.\n# \n";
56685 +    return 0;
56686 +  }
56687 +  return 1;
56688 +}
56689 +
56690 +#
56691 +#
56692 +sub load_module {
56693 +  my $params = shift;
56694 +  print "\nRemoving Module\n";
56695 +  system "rmmod dwc_otg";
56696 +  print "Loading Module\n";
56697 +  if ($params ne "") {
56698 +    print "Module Parameters: $params\n";
56699 +  }
56700 +  if (system("modprobe dwc_otg $params")) { 
56701 +    warn "Unable to load module\n";
56702 +    return 0; 
56703 +  }
56704 +  return 1;
56705 +}
56706 +
56707 +#
56708 +#
56709 +sub test_status {
56710 +  my $arg = shift;
56711 +
56712 +  print "\n";
56713 +
56714 +  if (defined $arg) {
56715 +    warn "WARNING: $arg\n";
56716 +  }
56717 +  
56718 +  if ($errors > 0) {
56719 +    warn "TEST FAILED with $errors errors\n";
56720 +    return 0;
56721 +  } else {
56722 +    print "TEST PASSED\n";
56723 +    return 0 if (defined $arg);
56724 +  }
56725 +  return 1;
56726 +}
56727 +
56728 +#
56729 +#
56730 +@EXPORT = qw(
56731 +$sysfsdir
56732 +$paramdir
56733 +$params
56734 +$errors
56735 +check_arch
56736 +load_module
56737 +test_status
56738 +);
56739 +
56740 +1;
56741 diff --git a/drivers/usb/host/dwc_otg/test/test_mod_param.pl b/drivers/usb/host/dwc_otg/test/test_mod_param.pl
56742 new file mode 100644
56743 index 0000000..e887dce
56744 --- /dev/null
56745 +++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl
56746 @@ -0,0 +1,133 @@
56747 +#!/usr/bin/perl -w
56748 +# 
56749 +# Run this program on the integrator.
56750 +#
56751 +# - Tests module parameter default values.
56752 +# - Tests setting of valid module parameter values via modprobe.
56753 +# - Tests invalid module parameter values.
56754 +# -----------------------------------------------------------------------------
56755 +use strict;
56756 +use dwc_otg_test;
56757 +
56758 +check_arch() or die;
56759 +
56760 +#
56761 +#
56762 +sub test {
56763 +  my ($param,$expected) = @_;
56764 +  my $value = get($param);
56765 +
56766 +  if ($value == $expected) {
56767 +    print "$param = $value, okay\n";
56768 +  }
56769 +
56770 +  else {
56771 +    warn "ERROR: value of $param != $expected, $value\n";
56772 +    $errors ++;
56773 +  }
56774 +}
56775 +
56776 +#
56777 +#
56778 +sub get {
56779 +  my $param = shift;
56780 +  my $tmp = `cat $paramdir/$param`;
56781 +  chomp $tmp;
56782 +  return $tmp;
56783 +}
56784 +
56785 +#
56786 +#
56787 +sub test_main {
56788 +
56789 +  print "\nTesting Module Parameters\n";
56790 +
56791 +  load_module("") or die;
56792 +
56793 +  # Test initial values
56794 +  print "\nTesting Default Values\n";
56795 +  foreach (@{$params}) {
56796 +    test ($_->{NAME}, $_->{DEFAULT});
56797 +  }
56798 +
56799 +  # Test low value
56800 +  print "\nTesting Low Value\n";
56801 +  my $cmd_params = "";
56802 +  foreach (@{$params}) {
56803 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} ";
56804 +  }
56805 +  load_module($cmd_params) or die;
56806 +
56807 +  foreach (@{$params}) {
56808 +    test ($_->{NAME}, $_->{LOW});
56809 +  }
56810 +
56811 +  # Test high value
56812 +  print "\nTesting High Value\n";
56813 +  $cmd_params = "";
56814 +  foreach (@{$params}) {
56815 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} ";
56816 +  }
56817 +  load_module($cmd_params) or die;
56818 +
56819 +  foreach (@{$params}) {
56820 +    test ($_->{NAME}, $_->{HIGH});
56821 +  }
56822 +
56823 +  # Test Enum
56824 +  print "\nTesting Enumerated\n";
56825 +  foreach (@{$params}) {
56826 +    if (defined $_->{ENUM}) {
56827 +      my $value;
56828 +      foreach $value (@{$_->{ENUM}}) {
56829 +       $cmd_params = "$_->{NAME}=$value";
56830 +       load_module($cmd_params) or die;
56831 +       test ($_->{NAME}, $value);
56832 +      }
56833 +    }
56834 +  }
56835 +
56836 +  # Test Invalid Values
56837 +  print "\nTesting Invalid Values\n";
56838 +  $cmd_params = "";
56839 +  foreach (@{$params}) {
56840 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1;
56841 +  }
56842 +  load_module($cmd_params) or die;
56843 +
56844 +  foreach (@{$params}) {
56845 +    test ($_->{NAME}, $_->{DEFAULT});
56846 +  }
56847 +
56848 +  $cmd_params = "";
56849 +  foreach (@{$params}) {
56850 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1;
56851 +  }
56852 +  load_module($cmd_params) or die;
56853 +
56854 +  foreach (@{$params}) {
56855 +    test ($_->{NAME}, $_->{DEFAULT});
56856 +  }
56857 +
56858 +  print "\nTesting Enumerated\n";
56859 +  foreach (@{$params}) {
56860 +    if (defined $_->{ENUM}) {
56861 +      my $value;
56862 +      foreach $value (@{$_->{ENUM}}) {
56863 +       $value = $value + 1;
56864 +       $cmd_params = "$_->{NAME}=$value";
56865 +       load_module($cmd_params) or die;
56866 +       test ($_->{NAME}, $_->{DEFAULT});
56867 +       $value = $value - 2;
56868 +       $cmd_params = "$_->{NAME}=$value";
56869 +       load_module($cmd_params) or die;
56870 +       test ($_->{NAME}, $_->{DEFAULT});
56871 +      }
56872 +    }
56873 +  }
56874 +
56875 +  test_status() or die;
56876 +}
56877 +
56878 +test_main();
56879 +0;
56880 diff --git a/drivers/usb/host/dwc_otg/test/test_sysfs.pl b/drivers/usb/host/dwc_otg/test/test_sysfs.pl
56881 new file mode 100644
56882 index 0000000..abcf284
56883 --- /dev/null
56884 +++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl
56885 @@ -0,0 +1,193 @@
56886 +#!/usr/bin/perl -w
56887 +# 
56888 +# Run this program on the integrator
56889 +# - Tests select sysfs attributes.
56890 +# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc.
56891 +# -----------------------------------------------------------------------------
56892 +use strict;
56893 +use dwc_otg_test;
56894 +
56895 +check_arch() or die;
56896 +
56897 +#
56898 +#
56899 +sub test {
56900 +  my ($attr,$expected) = @_;
56901 +  my $string = get($attr);
56902 +
56903 +  if ($string eq $expected) {
56904 +    printf("$attr = $string, okay\n");
56905 +  }
56906 +  else {
56907 +    warn "ERROR: value of $attr != $expected, $string\n";
56908 +    $errors ++;
56909 +  }
56910 +}
56911 +
56912 +#
56913 +#
56914 +sub set {
56915 +  my ($reg, $value) = @_;
56916 +  system "echo $value > $sysfsdir/$reg";
56917 +}
56918 +
56919 +#
56920 +#
56921 +sub get {
56922 +  my $attr = shift;
56923 +  my $string = `cat $sysfsdir/$attr`;
56924 +  chomp $string;
56925 +  if ($string =~ m/\s\=\s/) {
56926 +    my $tmp;
56927 +    ($tmp, $string) = split /\s=\s/, $string;
56928 +  }
56929 +  return $string;
56930 +}
56931 +
56932 +#
56933 +#
56934 +sub test_main {
56935 +  print("\nTesting Sysfs Attributes\n");
56936 +
56937 +  load_module("") or die;
56938 +
56939 +  # Test initial values of regoffset/regvalue/guid/gsnpsid
56940 +  print("\nTesting Default Values\n");
56941 +
56942 +  test("regoffset", "0xffffffff");
56943 +  test("regvalue", "invalid offset");
56944 +  test("guid", "0x12345678");  # this will fail if it has been changed
56945 +  test("gsnpsid", "0x4f54200a");
56946 +
56947 +  # Test operation of regoffset/regvalue
56948 +  print("\nTesting regoffset\n");
56949 +  set('regoffset', '5a5a5a5a');
56950 +  test("regoffset", "0xffffffff");
56951 +
56952 +  set('regoffset', '0');
56953 +  test("regoffset", "0x00000000");
56954 +
56955 +  set('regoffset', '40000');
56956 +  test("regoffset", "0x00000000");
56957 +
56958 +  set('regoffset', '3ffff');
56959 +  test("regoffset", "0x0003ffff");
56960 +
56961 +  set('regoffset', '1');
56962 +  test("regoffset", "0x00000001");
56963 +
56964 +  print("\nTesting regvalue\n");
56965 +  set('regoffset', '3c');
56966 +  test("regvalue", "0x12345678");
56967 +  set('regvalue', '5a5a5a5a');
56968 +  test("regvalue", "0x5a5a5a5a");
56969 +  set('regvalue','a5a5a5a5');
56970 +  test("regvalue", "0xa5a5a5a5");
56971 +  set('guid','12345678');
56972 +
56973 +  # Test HNP Capable
56974 +  print("\nTesting HNP Capable bit\n");
56975 +  set('hnpcapable', '1');
56976 +  test("hnpcapable", "0x1");
56977 +  set('hnpcapable','0');
56978 +  test("hnpcapable", "0x0");
56979 +
56980 +  set('regoffset','0c');
56981 +
56982 +  my $old = get('gusbcfg');
56983 +  print("setting hnpcapable\n");
56984 +  set('hnpcapable', '1');
56985 +  test("hnpcapable", "0x1");
56986 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9)));
56987 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9)));
56988 +
56989 +  $old = get('gusbcfg');
56990 +  print("clearing hnpcapable\n");
56991 +  set('hnpcapable', '0');
56992 +  test("hnpcapable", "0x0");
56993 +  test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9)));
56994 +  test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9)));
56995 +
56996 +  # Test SRP Capable
56997 +  print("\nTesting SRP Capable bit\n");
56998 +  set('srpcapable', '1');
56999 +  test("srpcapable", "0x1");
57000 +  set('srpcapable','0');
57001 +  test("srpcapable", "0x0");
57002 +
57003 +  set('regoffset','0c');
57004 +
57005 +  $old = get('gusbcfg');
57006 +  print("setting srpcapable\n");
57007 +  set('srpcapable', '1');
57008 +  test("srpcapable", "0x1");
57009 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8)));
57010 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8)));
57011 +
57012 +  $old = get('gusbcfg');
57013 +  print("clearing srpcapable\n");
57014 +  set('srpcapable', '0');
57015 +  test("srpcapable", "0x0");
57016 +  test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8)));
57017 +  test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8)));
57018 +
57019 +  # Test GGPIO
57020 +  print("\nTesting GGPIO\n");
57021 +  set('ggpio','5a5a5a5a');
57022 +  test('ggpio','0x5a5a0000');
57023 +  set('ggpio','a5a5a5a5');
57024 +  test('ggpio','0xa5a50000');
57025 +  set('ggpio','11110000');
57026 +  test('ggpio','0x11110000');
57027 +  set('ggpio','00001111');
57028 +  test('ggpio','0x00000000');
57029 +
57030 +  # Test DEVSPEED
57031 +  print("\nTesting DEVSPEED\n");
57032 +  set('regoffset','800');
57033 +  $old = get('regvalue');
57034 +  set('devspeed','0');
57035 +  test('devspeed','0x0');
57036 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
57037 +  set('devspeed','1');
57038 +  test('devspeed','0x1');
57039 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
57040 +  set('devspeed','2');
57041 +  test('devspeed','0x2');
57042 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2));
57043 +  set('devspeed','3');
57044 +  test('devspeed','0x3');
57045 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3));
57046 +  set('devspeed','4');
57047 +  test('devspeed','0x0');
57048 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
57049 +  set('devspeed','5');
57050 +  test('devspeed','0x1');
57051 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
57052 +
57053 +
57054 +  #  mode      Returns the current mode:0 for device mode1 for host mode       Read
57055 +  #  hnp       Initiate the Host Negotiation Protocol.  Read returns the status.       Read/Write
57056 +  #  srp       Initiate the Session Request Protocol.  Read returns the status.        Read/Write
57057 +  #  buspower  Get or Set the Power State of the bus (0 - Off or 1 - On)       Read/Write
57058 +  #  bussuspend        Suspend the USB bus.    Read/Write
57059 +  #  busconnected      Get the connection status of the bus    Read
57060 +
57061 +  #  gotgctl   Get or set the Core Control Status Register.    Read/Write
57062 +  ##  gusbcfg  Get or set the Core USB Configuration Register  Read/Write
57063 +  #  grxfsiz   Get or set the Receive FIFO Size Register       Read/Write
57064 +  #  gnptxfsiz Get or set the non-periodic Transmit Size Register      Read/Write
57065 +  #  gpvndctl  Get or set the PHY Vendor Control Register      Read/Write
57066 +  ##  ggpio    Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write
57067 +  ##  guid     Get or set the value of the User ID Register    Read/Write
57068 +  ##  gsnpsid  Get the value of the Synopsys ID Regester       Read
57069 +  ##  devspeed Get or set the device speed setting in the DCFG register        Read/Write
57070 +  #  enumspeed Gets the device enumeration Speed.      Read
57071 +  #  hptxfsiz  Get the value of the Host Periodic Transmit FIFO        Read
57072 +  #  hprt0     Get or Set the value in the Host Port Control and Status Register       Read/Write
57073 +
57074 +  test_status("TEST NYI") or die;
57075 +}
57076 +
57077 +test_main();
57078 +0;
57079 -- 
57080 1.9.1
57081