[brcm2708] adds target used by rapsberry pi
[openwrt.git] / target / linux / brcm2708 / patches-3.3 / 0001-Add-dwc_otg-driver.patch
1 From c2eaacd30565604bbf776ca6e83c9889ea87ea74 Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Tue, 17 Jan 2012 19:14:08 +0000
4 Subject: [PATCH 1/7] 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/hub.c                             |   52 +-
11  drivers/usb/core/message.c                         |   79 +
12  drivers/usb/core/otg_whitelist.h                   |  172 +-
13  drivers/usb/gadget/Kconfig                         |   28 +
14  drivers/usb/gadget/file_storage.c                  |   70 +-
15  drivers/usb/host/Kconfig                           |   13 +
16  drivers/usb/host/Makefile                          |    2 +
17  drivers/usb/host/dwc_common_port/Makefile          |   44 +
18  drivers/usb/host/dwc_common_port/Makefile.linux    |   36 +
19  drivers/usb/host/dwc_common_port/doc/doxygen.cfg   |  270 +
20  .../html/dir_c13d72e45af28cdc461a5f284d3d36fc.html |   81 +
21  .../usb/host/dwc_common_port/doc/html/dirs.html    |   22 +
22  .../usb/host/dwc_common_port/doc/html/doxygen.css  |  358 ++
23  .../host/dwc_common_port/doc/html/dwc__cc_8h.html  |  709 +++
24  .../dwc_common_port/doc/html/dwc__crypto_8c.html   |  435 ++
25  .../dwc_common_port/doc/html/dwc__crypto_8h.html   |  618 +++
26  .../host/dwc_common_port/doc/html/dwc__dh_8h.html  |  166 +
27  .../dwc_common_port/doc/html/dwc__list_8h.html     | 1844 +++++++
28  .../dwc_common_port/doc/html/dwc__modpow_8h.html   |   48 +
29  .../dwc_common_port/doc/html/dwc__notifier_8h.html |  306 ++
30  .../host/dwc_common_port/doc/html/dwc__os_8h.html  | 3090 +++++++++++
31  .../usb/host/dwc_common_port/doc/html/files.html   |   34 +
32  .../usb/host/dwc_common_port/doc/html/globals.html |  163 +
33  .../dwc_common_port/doc/html/globals_defs.html     |   41 +
34  .../dwc_common_port/doc/html/globals_func.html     |  153 +
35  .../dwc_common_port/doc/html/globals_type.html     |   41 +
36  .../usb/host/dwc_common_port/doc/html/index.html   |    8 +
37  .../usb/host/dwc_common_port/doc/html/main.html    |   45 +
38  .../usb/host/dwc_common_port/doc/html/pages.html   |   23 +
39  drivers/usb/host/dwc_common_port/doc/html/tabs.css |  102 +
40  .../usb/host/dwc_common_port/doc/html/todo.html    |   23 +
41  .../usb/host/dwc_common_port/doc/html/tree.html    |   90 +
42  drivers/usb/host/dwc_common_port/dwc_cc.c          |  506 ++
43  drivers/usb/host/dwc_common_port/dwc_cc.h          |  209 +
44  .../usb/host/dwc_common_port/dwc_common_linux.c    | 1247 +++++
45  drivers/usb/host/dwc_common_port/dwc_crypto.c      |  306 ++
46  drivers/usb/host/dwc_common_port/dwc_crypto.h      |  103 +
47  drivers/usb/host/dwc_common_port/dwc_dh.c          |  286 ++
48  drivers/usb/host/dwc_common_port/dwc_dh.h          |   98 +
49  drivers/usb/host/dwc_common_port/dwc_list.h        |  616 +++
50  drivers/usb/host/dwc_common_port/dwc_mem.c         |  172 +
51  drivers/usb/host/dwc_common_port/dwc_modpow.c      |  622 +++
52  drivers/usb/host/dwc_common_port/dwc_modpow.h      |   26 +
53  drivers/usb/host/dwc_common_port/dwc_notifier.c    |  256 +
54  drivers/usb/host/dwc_common_port/dwc_notifier.h    |  112 +
55  drivers/usb/host/dwc_common_port/dwc_os.h          |  924 ++++
56  drivers/usb/host/dwc_common_port/usb.h             |  850 +++
57  drivers/usb/host/dwc_otg/Makefile                  |   78 +
58  drivers/usb/host/dwc_otg/doc/doxygen.cfg           |  224 +
59  drivers/usb/host/dwc_otg/doc/html/annotated.html   |  120 +
60  drivers/usb/host/dwc_otg/doc/html/doxygen.css      |  358 ++
61  .../dwc_otg/doc/html/dummy__audio_8c-source.html   | 1550 ++++++
62  .../doc/html/dwc__cfi__common_8h-source.html       |  115 +
63  .../host/dwc_otg/doc/html/dwc__cfi__common_8h.html |  119 +
64  .../dwc_otg/doc/html/dwc__otg__attr_8c-source.html |  828 +++
65  .../host/dwc_otg/doc/html/dwc__otg__attr_8c.html   |  485 ++
66  .../dwc_otg/doc/html/dwc__otg__attr_8h-source.html |  105 +
67  .../host/dwc_otg/doc/html/dwc__otg__attr_8h.html   |  116 +
68  .../dwc_otg/doc/html/dwc__otg__cfi_8c-source.html  | 1724 +++++++
69  .../host/dwc_otg/doc/html/dwc__otg__cfi_8c.html    |   36 +
70  .../dwc_otg/doc/html/dwc__otg__cfi_8h-source.html  |  299 ++
71  .../host/dwc_otg/doc/html/dwc__otg__cfi_8h.html    |  302 ++
72  .../dwc_otg/doc/html/dwc__otg__cil_8c-source.html  | 4922 ++++++++++++++++++
73  .../host/dwc_otg/doc/html/dwc__otg__cil_8c.html    | 3103 +++++++++++
74  .../dwc_otg/doc/html/dwc__otg__cil_8h-source.html  |  709 +++
75  .../host/dwc_otg/doc/html/dwc__otg__cil_8h.html    | 1844 +++++++
76  .../doc/html/dwc__otg__cil__intr_8c-source.html    |  742 +++
77  .../dwc_otg/doc/html/dwc__otg__cil__intr_8c.html   |  645 +++
78  .../doc/html/dwc__otg__core__if_8h-source.html     |  365 ++
79  .../dwc_otg/doc/html/dwc__otg__core__if_8h.html    | 1730 +++++++
80  .../dwc_otg/doc/html/dwc__otg__dbg_8h-source.html  |  100 +
81  .../host/dwc_otg/doc/html/dwc__otg__dbg_8h.html    |  133 +
82  .../doc/html/dwc__otg__driver_8c-source.html       | 1079 ++++
83  .../host/dwc_otg/doc/html/dwc__otg__driver_8c.html |  719 +++
84  .../doc/html/dwc__otg__driver_8h-source.html       |  110 +
85  .../host/dwc_otg/doc/html/dwc__otg__driver_8h.html |   50 +
86  .../dwc_otg/doc/html/dwc__otg__hcd_8c-source.html  | 2946 +++++++++++
87  .../host/dwc_otg/doc/html/dwc__otg__hcd_8c.html    | 1837 +++++++
88  .../dwc_otg/doc/html/dwc__otg__hcd_8h-source.html  |  517 ++
89  .../host/dwc_otg/doc/html/dwc__otg__hcd_8h.html    | 1310 +++++
90  .../doc/html/dwc__otg__hcd__ddma_8c-source.html    | 1070 ++++
91  .../dwc_otg/doc/html/dwc__otg__hcd__ddma_8c.html   |  311 ++
92  .../doc/html/dwc__otg__hcd__if_8h-source.html      |  191 +
93  .../dwc_otg/doc/html/dwc__otg__hcd__if_8h.html     | 1381 +++++
94  .../doc/html/dwc__otg__hcd__intr_8c-source.html    | 1873 +++++++
95  .../dwc_otg/doc/html/dwc__otg__hcd__intr_8c.html   | 1252 +++++
96  .../doc/html/dwc__otg__hcd__linux_8c-source.html   |  726 +++
97  .../dwc_otg/doc/html/dwc__otg__hcd__linux_8c.html  |  514 ++
98  .../doc/html/dwc__otg__hcd__queue_8c-source.html   |  633 +++
99  .../dwc_otg/doc/html/dwc__otg__hcd__queue_8c.html  |  667 +++
100  .../dwc_otg/doc/html/dwc__otg__pcd_8c-source.html  | 1851 +++++++
101  .../host/dwc_otg/doc/html/dwc__otg__pcd_8c.html    | 1343 +++++
102  .../dwc_otg/doc/html/dwc__otg__pcd_8h-source.html  |  171 +
103  .../host/dwc_otg/doc/html/dwc__otg__pcd_8h.html    |  254 +
104  .../doc/html/dwc__otg__pcd__if_8h-source.html      |  174 +
105  .../dwc_otg/doc/html/dwc__otg__pcd__if_8h.html     |  976 ++++
106  .../doc/html/dwc__otg__pcd__intr_8c-source.html    | 3629 +++++++++++++
107  .../dwc_otg/doc/html/dwc__otg__pcd__intr_8c.html   | 1599 ++++++
108  .../doc/html/dwc__otg__pcd__linux_8c-source.html   |  997 ++++
109  .../dwc_otg/doc/html/dwc__otg__pcd__linux_8c.html  |  796 +++
110  .../dwc_otg/doc/html/dwc__otg__regs_8h-source.html | 1260 +++++
111  .../host/dwc_otg/doc/html/dwc__otg__regs_8h.html   | 1468 ++++++
112  drivers/usb/host/dwc_otg/doc/html/files.html       |   52 +
113  drivers/usb/host/dwc_otg/doc/html/functions.html   |   82 +
114  .../usb/host/dwc_otg/doc/html/functions_0x62.html  |   99 +
115  .../usb/host/dwc_otg/doc/html/functions_0x63.html  |  110 +
116  .../usb/host/dwc_otg/doc/html/functions_0x64.html  |  158 +
117  .../usb/host/dwc_otg/doc/html/functions_0x65.html  |  109 +
118  .../usb/host/dwc_otg/doc/html/functions_0x66.html  |   81 +
119  .../usb/host/dwc_otg/doc/html/functions_0x67.html  |   95 +
120  .../usb/host/dwc_otg/doc/html/functions_0x68.html  |  119 +
121  .../usb/host/dwc_otg/doc/html/functions_0x69.html  |  121 +
122  .../usb/host/dwc_otg/doc/html/functions_0x6c.html  |   74 +
123  .../usb/host/dwc_otg/doc/html/functions_0x6d.html  |   79 +
124  .../usb/host/dwc_otg/doc/html/functions_0x6e.html  |   99 +
125  .../usb/host/dwc_otg/doc/html/functions_0x6f.html  |  101 +
126  .../usb/host/dwc_otg/doc/html/functions_0x70.html  |  144 +
127  .../usb/host/dwc_otg/doc/html/functions_0x71.html  |   71 +
128  .../usb/host/dwc_otg/doc/html/functions_0x72.html  |  141 +
129  .../usb/host/dwc_otg/doc/html/functions_0x73.html  |  128 +
130  .../usb/host/dwc_otg/doc/html/functions_0x74.html  |   88 +
131  .../usb/host/dwc_otg/doc/html/functions_0x75.html  |   78 +
132  .../usb/host/dwc_otg/doc/html/functions_0x76.html  |   65 +
133  .../usb/host/dwc_otg/doc/html/functions_0x77.html  |   79 +
134  .../usb/host/dwc_otg/doc/html/functions_0x78.html  |   77 +
135  .../usb/host/dwc_otg/doc/html/functions_func.html  |   36 +
136  .../usb/host/dwc_otg/doc/html/functions_vars.html  |   82 +
137  .../host/dwc_otg/doc/html/functions_vars_0x62.html |   99 +
138  .../host/dwc_otg/doc/html/functions_vars_0x63.html |  110 +
139  .../host/dwc_otg/doc/html/functions_vars_0x64.html |  157 +
140  .../host/dwc_otg/doc/html/functions_vars_0x65.html |  109 +
141  .../host/dwc_otg/doc/html/functions_vars_0x66.html |   81 +
142  .../host/dwc_otg/doc/html/functions_vars_0x67.html |   95 +
143  .../host/dwc_otg/doc/html/functions_vars_0x68.html |  119 +
144  .../host/dwc_otg/doc/html/functions_vars_0x69.html |  121 +
145  .../host/dwc_otg/doc/html/functions_vars_0x6c.html |   74 +
146  .../host/dwc_otg/doc/html/functions_vars_0x6d.html |   79 +
147  .../host/dwc_otg/doc/html/functions_vars_0x6e.html |   99 +
148  .../host/dwc_otg/doc/html/functions_vars_0x6f.html |  101 +
149  .../host/dwc_otg/doc/html/functions_vars_0x70.html |  144 +
150  .../host/dwc_otg/doc/html/functions_vars_0x71.html |   71 +
151  .../host/dwc_otg/doc/html/functions_vars_0x72.html |  141 +
152  .../host/dwc_otg/doc/html/functions_vars_0x73.html |  128 +
153  .../host/dwc_otg/doc/html/functions_vars_0x74.html |   88 +
154  .../host/dwc_otg/doc/html/functions_vars_0x75.html |   78 +
155  .../host/dwc_otg/doc/html/functions_vars_0x76.html |   65 +
156  .../host/dwc_otg/doc/html/functions_vars_0x77.html |   79 +
157  .../host/dwc_otg/doc/html/functions_vars_0x78.html |   77 +
158  drivers/usb/host/dwc_otg/doc/html/globals.html     |   87 +
159  .../usb/host/dwc_otg/doc/html/globals_0x61.html    |   76 +
160  .../usb/host/dwc_otg/doc/html/globals_0x62.html    |   83 +
161  .../usb/host/dwc_otg/doc/html/globals_0x63.html    |  100 +
162  .../usb/host/dwc_otg/doc/html/globals_0x64.html    |  686 +++
163  .../usb/host/dwc_otg/doc/html/globals_0x65.html    |   78 +
164  .../usb/host/dwc_otg/doc/html/globals_0x66.html    |   87 +
165  .../usb/host/dwc_otg/doc/html/globals_0x67.html    |   93 +
166  .../usb/host/dwc_otg/doc/html/globals_0x68.html    |  129 +
167  .../usb/host/dwc_otg/doc/html/globals_0x69.html    |   76 +
168  .../usb/host/dwc_otg/doc/html/globals_0x6b.html    |   69 +
169  .../usb/host/dwc_otg/doc/html/globals_0x6d.html    |   84 +
170  .../usb/host/dwc_otg/doc/html/globals_0x6e.html    |   68 +
171  .../usb/host/dwc_otg/doc/html/globals_0x6f.html    |   73 +
172  .../usb/host/dwc_otg/doc/html/globals_0x70.html    |   84 +
173  .../usb/host/dwc_otg/doc/html/globals_0x71.html    |   70 +
174  .../usb/host/dwc_otg/doc/html/globals_0x72.html    |   94 +
175  .../usb/host/dwc_otg/doc/html/globals_0x73.html    |   85 +
176  .../usb/host/dwc_otg/doc/html/globals_0x74.html    |   68 +
177  .../usb/host/dwc_otg/doc/html/globals_0x75.html    |   80 +
178  .../usb/host/dwc_otg/doc/html/globals_0x76.html    |   75 +
179  .../usb/host/dwc_otg/doc/html/globals_0x77.html    |   74 +
180  .../usb/host/dwc_otg/doc/html/globals_defs.html    |   68 +
181  .../host/dwc_otg/doc/html/globals_defs_0x61.html   |   64 +
182  .../host/dwc_otg/doc/html/globals_defs_0x62.html   |   71 +
183  .../host/dwc_otg/doc/html/globals_defs_0x63.html   |   74 +
184  .../host/dwc_otg/doc/html/globals_defs_0x64.html   |  241 +
185  .../host/dwc_otg/doc/html/globals_defs_0x66.html   |   71 +
186  .../host/dwc_otg/doc/html/globals_defs_0x67.html   |   62 +
187  .../host/dwc_otg/doc/html/globals_defs_0x68.html   |   63 +
188  .../host/dwc_otg/doc/html/globals_defs_0x69.html   |   62 +
189  .../host/dwc_otg/doc/html/globals_defs_0x6d.html   |   76 +
190  .../host/dwc_otg/doc/html/globals_defs_0x6e.html   |   62 +
191  .../host/dwc_otg/doc/html/globals_defs_0x6f.html   |   67 +
192  .../host/dwc_otg/doc/html/globals_defs_0x72.html   |   66 +
193  .../host/dwc_otg/doc/html/globals_defs_0x73.html   |   63 +
194  .../host/dwc_otg/doc/html/globals_defs_0x75.html   |   64 +
195  .../host/dwc_otg/doc/html/globals_defs_0x76.html   |   68 +
196  .../usb/host/dwc_otg/doc/html/globals_enum.html    |   44 +
197  .../usb/host/dwc_otg/doc/html/globals_eval.html    |   43 +
198  .../usb/host/dwc_otg/doc/html/globals_func.html    |   77 +
199  .../host/dwc_otg/doc/html/globals_func_0x61.html   |   70 +
200  .../host/dwc_otg/doc/html/globals_func_0x62.html   |   68 +
201  .../host/dwc_otg/doc/html/globals_func_0x63.html   |   77 +
202  .../host/dwc_otg/doc/html/globals_func_0x64.html   |  427 ++
203  .../host/dwc_otg/doc/html/globals_func_0x65.html   |   73 +
204  .../host/dwc_otg/doc/html/globals_func_0x66.html   |   72 +
205  .../host/dwc_otg/doc/html/globals_func_0x67.html   |   78 +
206  .../host/dwc_otg/doc/html/globals_func_0x68.html   |  101 +
207  .../host/dwc_otg/doc/html/globals_func_0x69.html   |   71 +
208  .../host/dwc_otg/doc/html/globals_func_0x6b.html   |   66 +
209  .../host/dwc_otg/doc/html/globals_func_0x6d.html   |   66 +
210  .../host/dwc_otg/doc/html/globals_func_0x70.html   |   78 +
211  .../host/dwc_otg/doc/html/globals_func_0x71.html   |   67 +
212  .../host/dwc_otg/doc/html/globals_func_0x72.html   |   80 +
213  .../host/dwc_otg/doc/html/globals_func_0x73.html   |   77 +
214  .../host/dwc_otg/doc/html/globals_func_0x75.html   |   73 +
215  .../host/dwc_otg/doc/html/globals_func_0x76.html   |   65 +
216  .../host/dwc_otg/doc/html/globals_func_0x77.html   |   70 +
217  .../usb/host/dwc_otg/doc/html/globals_type.html    |  175 +
218  .../usb/host/dwc_otg/doc/html/globals_vars.html    |  120 +
219  drivers/usb/host/dwc_otg/doc/html/index.html       |    8 +
220  .../dwc_otg/doc/html/linux module attributes.html  |  130 +
221  drivers/usb/host/dwc_otg/doc/html/main.html        |   21 +
222  .../host/dwc_otg/doc/html/module parameters.html   |  189 +
223  drivers/usb/host/dwc_otg/doc/html/pages.html       |   27 +
224  .../html/struct__ddma__align__buffer__setup.html   |   46 +
225  .../html/struct__ddma__concat__buffer__setup.html  |   46 +
226  .../struct__ddma__concat__buffer__setup__hdr.html  |   49 +
227  .../doc/html/struct__ddma__sg__buffer__setup.html  |   57 +
228  .../doc/html/struct__rx__fifo__size__setup.html    |   43 +
229  .../doc/html/struct__tx__fifo__size__setup.html    |   46 +
230  .../doc/html/structcfi__all__features__header.html |   75 +
231  .../dwc_otg/doc/html/structcfi__dma__buff.html     |   41 +
232  .../usb/host/dwc_otg/doc/html/structcfi__ep.html   |   69 +
233  .../doc/html/structcfi__feature__desc__header.html |   60 +
234  .../usb/host/dwc_otg/doc/html/structcfi__ops.html  |   64 +
235  .../host/dwc_otg/doc/html/structcfi__string.html   |   48 +
236  .../doc/html/structcfi__usb__ctrlrequest.html      |   58 +
237  .../usb/host/dwc_otg/doc/html/structcfiobject.html |   62 +
238  .../usb/host/dwc_otg/doc/html/structdwc__ep.html   |  192 +
239  .../usb/host/dwc_otg/doc/html/structdwc__hc.html   |  345 ++
240  .../doc/html/structdwc__otg__cil__callbacks.html   |   70 +
241  .../html/structdwc__otg__core__global__regs.html   |  557 ++
242  .../dwc_otg/doc/html/structdwc__otg__core__if.html |  190 +
243  .../doc/html/structdwc__otg__core__params.html     |  606 +++
244  .../doc/html/structdwc__otg__dev__dma__desc.html   |   50 +
245  .../html/structdwc__otg__dev__global__regs.html    |  441 ++
246  .../dwc_otg/doc/html/structdwc__otg__dev__if.html  |  142 +
247  .../html/structdwc__otg__dev__in__ep__regs.html    |  221 +
248  .../html/structdwc__otg__dev__out__ep__regs.html   |  221 +
249  .../dwc_otg/doc/html/structdwc__otg__device.html   |   64 +
250  .../structdwc__otg__driver__module__params.html    |  146 +
251  .../dwc_otg/doc/html/structdwc__otg__hc__regs.html |  200 +
252  .../host/dwc_otg/doc/html/structdwc__otg__hcd.html |  377 ++
253  .../html/structdwc__otg__hcd__function__ops.html   |   53 +
254  .../structdwc__otg__hcd__iso__packet__desc.html    |   47 +
255  .../doc/html/structdwc__otg__hcd__pipe__info.html  |   50 +
256  .../dwc_otg/doc/html/structdwc__otg__hcd__urb.html |   80 +
257  .../doc/html/structdwc__otg__host__dma__desc.html  |   50 +
258  .../html/structdwc__otg__host__global__regs.html   |  219 +
259  .../dwc_otg/doc/html/structdwc__otg__host__if.html |   66 +
260  .../host/dwc_otg/doc/html/structdwc__otg__pcd.html |  152 +
261  .../dwc_otg/doc/html/structdwc__otg__pcd__ep.html  |   77 +
262  .../html/structdwc__otg__pcd__function__ops.html   |   73 +
263  .../doc/html/structdwc__otg__pcd__request.html     |   64 +
264  .../host/dwc_otg/doc/html/structdwc__otg__qh.html  |  228 +
265  .../host/dwc_otg/doc/html/structdwc__otg__qtd.html |  157 +
266  .../dwc_otg/doc/html/structgadget__wrapper.html    |   53 +
267  .../dwc_otg/doc/html/structiso__pkt__info.html     |   49 +
268  .../doc/html/structwrapper__priv__data.html        |   38 +
269  .../usb/host/dwc_otg/doc/html/structzero__dev.html |   56 +
270  drivers/usb/host/dwc_otg/doc/html/tabs.css         |  102 +
271  drivers/usb/host/dwc_otg/doc/html/todo.html        |  262 +
272  drivers/usb/host/dwc_otg/doc/html/tree.html        |  201 +
273  .../host/dwc_otg/doc/html/uniondaint__data.html    |  131 +
274  .../usb/host/dwc_otg/doc/html/uniondcfg__data.html |   74 +
275  .../usb/host/dwc_otg/doc/html/uniondctl__data.html |   96 +
276  .../host/dwc_otg/doc/html/uniondepctl__data.html   |  139 +
277  .../host/dwc_otg/doc/html/uniondeptsiz0__data.html |   69 +
278  .../host/dwc_otg/doc/html/uniondeptsiz__data.html  |   63 +
279  .../dwc_otg/doc/html/uniondev__dma__desc__sts.html |  140 +
280  .../doc/html/uniondevice__grxsts__data.html        |   62 +
281  .../host/dwc_otg/doc/html/uniondiepint__data.html  |   90 +
282  .../host/dwc_otg/doc/html/uniondoepint__data.html  |   98 +
283  .../usb/host/dwc_otg/doc/html/uniondsts__data.html |   68 +
284  .../host/dwc_otg/doc/html/uniondthrctl__data.html  |  178 +
285  .../host/dwc_otg/doc/html/uniondtknq1__data.html   |   86 +
286  .../host/dwc_otg/doc/html/uniondtxfsts__data.html  |   56 +
287  ...otg__hcd_1_1dwc__otg__hcd__internal__flags.html |   66 +
288  .../host/dwc_otg/doc/html/unionfifosize__data.html |   56 +
289  .../host/dwc_otg/doc/html/uniongahbcfg__data.html  |   66 +
290  .../host/dwc_otg/doc/html/uniongi2cctl__data.html  |   72 +
291  .../host/dwc_otg/doc/html/uniongintmsk__data.html  |  114 +
292  .../host/dwc_otg/doc/html/uniongintsts__data.html  |  114 +
293  .../host/dwc_otg/doc/html/unionglpmctl__data.html  |  178 +
294  .../host/dwc_otg/doc/html/uniongnptxsts__data.html |   69 +
295  .../host/dwc_otg/doc/html/uniongotgctl__data.html  |   80 +
296  .../host/dwc_otg/doc/html/uniongotgint__data.html  |   79 +
297  .../host/dwc_otg/doc/html/uniongrstctl__data.html  |  249 +
298  .../host/dwc_otg/doc/html/uniongusbcfg__data.html  |   98 +
299  .../host/dwc_otg/doc/html/unionhaint__data.html    |   93 +
300  .../host/dwc_otg/doc/html/unionhaintmsk__data.html |   93 +
301  .../host/dwc_otg/doc/html/unionhcchar__data.html   |  123 +
302  .../host/dwc_otg/doc/html/unionhcdma__data.html    |   78 +
303  .../usb/host/dwc_otg/doc/html/unionhcfg__data.html |   72 +
304  .../host/dwc_otg/doc/html/unionhcint__data.html    |   95 +
305  .../host/dwc_otg/doc/html/unionhcintmsk__data.html |   82 +
306  .../host/dwc_otg/doc/html/unionhcsplt__data.html   |   63 +
307  .../host/dwc_otg/doc/html/unionhctsiz__data.html   |  105 +
308  .../usb/host/dwc_otg/doc/html/unionhfir__data.html |   54 +
309  .../host/dwc_otg/doc/html/unionhfnum__data.html    |   54 +
310  .../doc/html/unionhost__dma__desc__sts.html        |  123 +
311  .../dwc_otg/doc/html/unionhost__grxsts__data.html  |   60 +
312  .../host/dwc_otg/doc/html/unionhprt0__data.html    |   82 +
313  .../host/dwc_otg/doc/html/unionhptxsts__data.html  |   62 +
314  .../host/dwc_otg/doc/html/unionhwcfg1__data.html   |   84 +
315  .../host/dwc_otg/doc/html/unionhwcfg2__data.html   |   82 +
316  .../host/dwc_otg/doc/html/unionhwcfg3__data.html   |   76 +
317  .../host/dwc_otg/doc/html/unionhwcfg4__data.html   |   80 +
318  .../host/dwc_otg/doc/html/unionpcgcctl__data.html  |   78 +
319  drivers/usb/host/dwc_otg/dummy_audio.c             | 1575 ++++++
320  drivers/usb/host/dwc_otg/dwc_cfi_common.h          |  142 +
321  drivers/usb/host/dwc_otg/dwc_otg_attr.c            | 1316 +++++
322  drivers/usb/host/dwc_otg/dwc_otg_attr.h            |   88 +
323  drivers/usb/host/dwc_otg/dwc_otg_cfi.c             | 1876 +++++++
324  drivers/usb/host/dwc_otg/dwc_otg_cfi.h             |  319 ++
325  drivers/usb/host/dwc_otg/dwc_otg_cil.c             | 5410 ++++++++++++++++++++
326  drivers/usb/host/dwc_otg/dwc_otg_cil.h             | 1143 +++++
327  drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c        |  846 +++
328  drivers/usb/host/dwc_otg/dwc_otg_core_if.h         |  641 +++
329  drivers/usb/host/dwc_otg/dwc_otg_dbg.h             |  113 +
330  drivers/usb/host/dwc_otg/dwc_otg_driver.c          | 1577 ++++++
331  drivers/usb/host/dwc_otg/dwc_otg_driver.h          |  101 +
332  drivers/usb/host/dwc_otg/dwc_otg_hcd.c             | 3330 ++++++++++++
333  drivers/usb/host/dwc_otg/dwc_otg_hcd.h             |  804 +++
334  drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c        | 1106 ++++
335  drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h          |  393 ++
336  drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c        | 2065 ++++++++
337  drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c       |  840 +++
338  drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c       |  732 +++
339  drivers/usb/host/dwc_otg/dwc_otg_pcd.c             | 2067 ++++++++
340  drivers/usb/host/dwc_otg/dwc_otg_pcd.h             |  216 +
341  drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h          |  333 ++
342  drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c        | 4077 +++++++++++++++
343  drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c       | 1288 +++++
344  drivers/usb/host/dwc_otg/dwc_otg_regs.h            | 2237 ++++++++
345  drivers/usb/host/dwc_otg/test/Makefile             |   16 +
346  drivers/usb/host/dwc_otg/test/dwc_otg_test.pm      |  337 ++
347  drivers/usb/host/dwc_otg/test/test_mod_param.pl    |  133 +
348  drivers/usb/host/dwc_otg/test/test_sysfs.pl        |  193 +
349  341 files changed, 124762 insertions(+), 59 deletions(-)
350  create mode 100644 drivers/usb/host/dwc_common_port/Makefile
351  create mode 100644 drivers/usb/host/dwc_common_port/Makefile.linux
352  create mode 100644 drivers/usb/host/dwc_common_port/doc/doxygen.cfg
353  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dir_c13d72e45af28cdc461a5f284d3d36fc.html
354  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dirs.html
355  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/doxygen.css
356  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__cc_8h.html
357  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__crypto_8c.html
358  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__crypto_8h.html
359  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__dh_8h.html
360  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__list_8h.html
361  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__modpow_8h.html
362  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__notifier_8h.html
363  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/dwc__os_8h.html
364  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/files.html
365  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/globals.html
366  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/globals_defs.html
367  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/globals_func.html
368  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/globals_type.html
369  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/index.html
370  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/main.html
371  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/pages.html
372  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/tabs.css
373  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/todo.html
374  create mode 100644 drivers/usb/host/dwc_common_port/doc/html/tree.html
375  create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.c
376  create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.h
377  create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_linux.c
378  create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.c
379  create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.h
380  create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.c
381  create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.h
382  create mode 100644 drivers/usb/host/dwc_common_port/dwc_list.h
383  create mode 100644 drivers/usb/host/dwc_common_port/dwc_mem.c
384  create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.c
385  create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.h
386  create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.c
387  create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.h
388  create mode 100644 drivers/usb/host/dwc_common_port/dwc_os.h
389  create mode 100644 drivers/usb/host/dwc_common_port/usb.h
390  create mode 100644 drivers/usb/host/dwc_otg/Makefile
391  create mode 100644 drivers/usb/host/dwc_otg/doc/doxygen.cfg
392  create mode 100644 drivers/usb/host/dwc_otg/doc/html/annotated.html
393  create mode 100644 drivers/usb/host/dwc_otg/doc/html/doxygen.css
394  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dummy__audio_8c-source.html
395  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__cfi__common_8h-source.html
396  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__cfi__common_8h.html
397  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__attr_8c-source.html
398  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__attr_8c.html
399  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__attr_8h-source.html
400  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__attr_8h.html
401  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cfi_8c-source.html
402  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cfi_8c.html
403  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cfi_8h-source.html
404  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cfi_8h.html
405  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil_8c-source.html
406  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil_8c.html
407  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil_8h-source.html
408  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil_8h.html
409  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil__intr_8c-source.html
410  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__cil__intr_8c.html
411  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__core__if_8h-source.html
412  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__core__if_8h.html
413  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__dbg_8h-source.html
414  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__dbg_8h.html
415  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__driver_8c-source.html
416  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__driver_8c.html
417  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__driver_8h-source.html
418  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__driver_8h.html
419  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd_8c-source.html
420  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd_8c.html
421  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd_8h-source.html
422  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd_8h.html
423  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__ddma_8c-source.html
424  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__ddma_8c.html
425  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__if_8h-source.html
426  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__if_8h.html
427  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__intr_8c-source.html
428  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__intr_8c.html
429  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__linux_8c-source.html
430  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__linux_8c.html
431  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__queue_8c-source.html
432  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__hcd__queue_8c.html
433  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd_8c-source.html
434  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd_8c.html
435  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd_8h-source.html
436  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd_8h.html
437  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__if_8h-source.html
438  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__if_8h.html
439  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__intr_8c-source.html
440  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__intr_8c.html
441  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__linux_8c-source.html
442  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__pcd__linux_8c.html
443  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__regs_8h-source.html
444  create mode 100644 drivers/usb/host/dwc_otg/doc/html/dwc__otg__regs_8h.html
445  create mode 100644 drivers/usb/host/dwc_otg/doc/html/files.html
446  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions.html
447  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x62.html
448  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x63.html
449  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x64.html
450  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x65.html
451  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x66.html
452  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x67.html
453  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x68.html
454  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x69.html
455  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x6c.html
456  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x6d.html
457  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x6e.html
458  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x6f.html
459  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x70.html
460  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x71.html
461  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x72.html
462  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x73.html
463  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x74.html
464  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x75.html
465  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x76.html
466  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x77.html
467  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_0x78.html
468  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_func.html
469  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars.html
470  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x62.html
471  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x63.html
472  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x64.html
473  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x65.html
474  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x66.html
475  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x67.html
476  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x68.html
477  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x69.html
478  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x6c.html
479  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x6d.html
480  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x6e.html
481  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x6f.html
482  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x70.html
483  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x71.html
484  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x72.html
485  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x73.html
486  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x74.html
487  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x75.html
488  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x76.html
489  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x77.html
490  create mode 100644 drivers/usb/host/dwc_otg/doc/html/functions_vars_0x78.html
491  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals.html
492  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x61.html
493  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x62.html
494  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x63.html
495  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x64.html
496  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x65.html
497  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x66.html
498  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x67.html
499  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x68.html
500  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x69.html
501  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x6b.html
502  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x6d.html
503  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x6e.html
504  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x6f.html
505  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x70.html
506  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x71.html
507  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x72.html
508  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x73.html
509  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x74.html
510  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x75.html
511  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x76.html
512  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_0x77.html
513  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs.html
514  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x61.html
515  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x62.html
516  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x63.html
517  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x64.html
518  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x66.html
519  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x67.html
520  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x68.html
521  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x69.html
522  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x6d.html
523  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x6e.html
524  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x6f.html
525  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x72.html
526  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x73.html
527  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x75.html
528  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_defs_0x76.html
529  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_enum.html
530  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_eval.html
531  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func.html
532  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x61.html
533  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x62.html
534  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x63.html
535  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x64.html
536  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x65.html
537  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x66.html
538  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x67.html
539  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x68.html
540  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x69.html
541  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x6b.html
542  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x6d.html
543  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x70.html
544  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x71.html
545  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x72.html
546  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x73.html
547  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x75.html
548  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x76.html
549  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_func_0x77.html
550  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_type.html
551  create mode 100644 drivers/usb/host/dwc_otg/doc/html/globals_vars.html
552  create mode 100644 drivers/usb/host/dwc_otg/doc/html/index.html
553  create mode 100644 drivers/usb/host/dwc_otg/doc/html/linux module attributes.html
554  create mode 100644 drivers/usb/host/dwc_otg/doc/html/main.html
555  create mode 100644 drivers/usb/host/dwc_otg/doc/html/module parameters.html
556  create mode 100644 drivers/usb/host/dwc_otg/doc/html/pages.html
557  create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__ddma__align__buffer__setup.html
558  create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__ddma__concat__buffer__setup.html
559  create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__ddma__concat__buffer__setup__hdr.html
560  create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__ddma__sg__buffer__setup.html
561  create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__rx__fifo__size__setup.html
562  create mode 100644 drivers/usb/host/dwc_otg/doc/html/struct__tx__fifo__size__setup.html
563  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__all__features__header.html
564  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__dma__buff.html
565  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__ep.html
566  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__feature__desc__header.html
567  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__ops.html
568  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__string.html
569  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfi__usb__ctrlrequest.html
570  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structcfiobject.html
571  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__ep.html
572  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__hc.html
573  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__cil__callbacks.html
574  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__core__global__regs.html
575  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__core__if.html
576  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__core__params.html
577  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__dma__desc.html
578  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__global__regs.html
579  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__if.html
580  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__in__ep__regs.html
581  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__dev__out__ep__regs.html
582  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__device.html
583  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__driver__module__params.html
584  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hc__regs.html
585  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd.html
586  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd__function__ops.html
587  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd__iso__packet__desc.html
588  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd__pipe__info.html
589  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__hcd__urb.html
590  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__host__dma__desc.html
591  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__host__global__regs.html
592  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__host__if.html
593  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__pcd.html
594  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__pcd__ep.html
595  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__pcd__function__ops.html
596  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__pcd__request.html
597  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__qh.html
598  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structdwc__otg__qtd.html
599  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structgadget__wrapper.html
600  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structiso__pkt__info.html
601  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structwrapper__priv__data.html
602  create mode 100644 drivers/usb/host/dwc_otg/doc/html/structzero__dev.html
603  create mode 100644 drivers/usb/host/dwc_otg/doc/html/tabs.css
604  create mode 100644 drivers/usb/host/dwc_otg/doc/html/todo.html
605  create mode 100644 drivers/usb/host/dwc_otg/doc/html/tree.html
606  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondaint__data.html
607  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondcfg__data.html
608  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondctl__data.html
609  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondepctl__data.html
610  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondeptsiz0__data.html
611  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondeptsiz__data.html
612  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondev__dma__desc__sts.html
613  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondevice__grxsts__data.html
614  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondiepint__data.html
615  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondoepint__data.html
616  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondsts__data.html
617  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondthrctl__data.html
618  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondtknq1__data.html
619  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondtxfsts__data.html
620  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniondwc__otg__hcd_1_1dwc__otg__hcd__internal__flags.html
621  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionfifosize__data.html
622  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongahbcfg__data.html
623  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongi2cctl__data.html
624  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongintmsk__data.html
625  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongintsts__data.html
626  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionglpmctl__data.html
627  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongnptxsts__data.html
628  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongotgctl__data.html
629  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongotgint__data.html
630  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongrstctl__data.html
631  create mode 100644 drivers/usb/host/dwc_otg/doc/html/uniongusbcfg__data.html
632  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhaint__data.html
633  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhaintmsk__data.html
634  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcchar__data.html
635  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcdma__data.html
636  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcfg__data.html
637  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcint__data.html
638  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcintmsk__data.html
639  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhcsplt__data.html
640  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhctsiz__data.html
641  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhfir__data.html
642  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhfnum__data.html
643  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhost__dma__desc__sts.html
644  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhost__grxsts__data.html
645  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhprt0__data.html
646  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhptxsts__data.html
647  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhwcfg1__data.html
648  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhwcfg2__data.html
649  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhwcfg3__data.html
650  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionhwcfg4__data.html
651  create mode 100644 drivers/usb/host/dwc_otg/doc/html/unionpcgcctl__data.html
652  create mode 100644 drivers/usb/host/dwc_otg/dummy_audio.c
653  create mode 100644 drivers/usb/host/dwc_otg/dwc_cfi_common.h
654  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c
655  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h
656  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.c
657  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.h
658  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c
659  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h
660  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
661  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_core_if.h
662  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_dbg.h
663  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.c
664  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h
665  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c
666  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h
667  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
668  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
669  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
670  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
671  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
672  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.c
673  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.h
674  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
675  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
676  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
677  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h
678  create mode 100644 drivers/usb/host/dwc_otg/test/Makefile
679  create mode 100644 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
680  create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl
681  create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl
682
683 --- a/drivers/usb/Makefile
684 +++ b/drivers/usb/Makefile
685 @@ -25,6 +25,7 @@ obj-$(CONFIG_USB_U132_HCD)    += host/
686  obj-$(CONFIG_USB_R8A66597_HCD) += host/
687  obj-$(CONFIG_USB_HWA_HCD)      += host/
688  obj-$(CONFIG_USB_ISP1760_HCD)  += host/
689 +obj-$(CONFIG_USB_DWCOTG)       += host/
690  obj-$(CONFIG_USB_IMX21_HCD)    += host/
691  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += host/
692  
693 --- a/drivers/usb/core/generic.c
694 +++ b/drivers/usb/core/generic.c
695 @@ -149,6 +149,7 @@ int usb_choose_configuration(struct usb_
696                 dev_warn(&udev->dev,
697                         "no configuration chosen from %d choice%s\n",
698                         num_configs, plural(num_configs));
699 +               dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
700         }
701         return i;
702  }
703 --- a/drivers/usb/core/hub.c
704 +++ b/drivers/usb/core/hub.c
705 @@ -1075,6 +1075,8 @@ static int hub_configure(struct usb_hub
706         INIT_WORK(&hub->tt.clear_work, hub_tt_work);
707         switch (hdev->descriptor.bDeviceProtocol) {
708         case USB_HUB_PR_FS:
709 +               dev_dbg(hub_dev, "TT with no hub-specific protocol - "
710 +                       "no TT\n");             
711                 break;
712         case USB_HUB_PR_HS_SINGLE_TT:
713                 dev_dbg(hub_dev, "Single TT\n");
714 @@ -1091,6 +1093,7 @@ static int hub_configure(struct usb_hub
715                 hub->tt.hub = hdev;
716                 break;
717         case USB_HUB_PR_SS:
718 +               dev_dbg(hub_dev, "USB 3.0 hub - no TT\n");
719                 /* USB 3.0 hubs don't have a TT */
720                 break;
721         default:
722 @@ -1719,6 +1722,12 @@ static inline void announce_device(struc
723  #endif
724  
725  #ifdef CONFIG_USB_OTG
726 +
727 +static int enable_whitelist;
728 +module_param(enable_whitelist, bool, S_IRUGO | S_IWUSR);
729 +MODULE_PARM_DESC(enable_whitelist,
730 +                "only recognize devices in OTG whitelist if true");
731 +
732  #include "otg_whitelist.h"
733  #endif
734  
735 @@ -1773,9 +1782,15 @@ static int usb_enumerate_device_otg(stru
736                                         dev_info(&udev->dev,
737                                                 "can't set HNP mode: %d\n",
738                                                 err);
739 +                                       dev_printk(KERN_CRIT, &udev->dev,
740 +                                               "Not Connected/Responding\n");
741 +
742                                         bus->b_hnp_enable = 0;
743 +                               } else {
744 +                                       dev_info(&udev->dev,
745 +                                               "HNP Not Supported\n");
746                                 }
747 -                       }
748 +                        }
749                 }
750         }
751  
752 @@ -1784,12 +1799,27 @@ static int usb_enumerate_device_otg(stru
753                 /* Maybe it can talk to us, though we can't talk to it.
754                  * (Includes HNP test device.)
755                  */
756 -               if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
757 +               if (udev->bus->b_hnp_enable || udev->bus->is_b_host ||
758 +                   udev->descriptor.idVendor == 0x1a0a) {
759                         err = usb_port_suspend(udev, PMSG_SUSPEND);
760 -                       if (err < 0)
761 +                       if (err < 0) {
762                                 dev_dbg(&udev->dev, "HNP fail, %d\n", err);
763 +                       } else {
764 +                           /* Return Connection Refused(ECONNREFUSED)
765 +                            * instead of No Device(ENODEV) so that the
766 +                            * retry loop in hub_port_connect_change() is
767 +                            * exited without disabling the port
768 +                            */
769 +                           err = -ECONNREFUSED;
770 +                           goto fail;
771 +                       }
772                 }
773 -               err = -ENOTSUPP;
774 +               //err = -ENOTSUPP;
775 +               /* Return Not Connected (ENOTCONN) instead of No
776 +                * Device(ENODEV) so that the retry loop in
777 +                * hub_port_connect_change() is exited
778 +                */
779 +               err = -ENOTCONN;
780                 goto fail;
781         }
782  fail:
783 @@ -2980,7 +3010,9 @@ hub_port_init (struct usb_hub *hub, stru
784                                 buf->bMaxPacketSize0 = 0;
785                                 r = usb_control_msg(udev, usb_rcvaddr0pipe(),
786                                         USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
787 -                                       USB_DT_DEVICE << 8, 0,
788 +                                       USB_DT_DEVICE << 8,
789 +                                       //USB_DT_DEVICE << 64, // DWC patch suggestion!
790 +                                       0,
791                                         buf, GET_DESCRIPTOR_BUFSIZE,
792                                         initial_descriptor_timeout);
793                                 switch (buf->bMaxPacketSize0) {
794 @@ -3426,8 +3458,10 @@ loop:
795                 release_devnum(udev);
796                 hub_free_dev(udev);
797                 usb_put_dev(udev);
798 -               if ((status == -ENOTCONN) || (status == -ENOTSUPP))
799 -                       break;
800 +               if (status == -ENOTCONN || status == -ENOTSUPP ||
801 +                       status == -ECONNREFUSED)
802 +                       // break; //DWC patch
803 +                       return;
804         }
805         if (hub->hdev->parent ||
806                         !hcd->driver->port_handed_over ||
807 --- a/drivers/usb/core/message.c
808 +++ b/drivers/usb/core/message.c
809 @@ -1837,6 +1837,85 @@ free_interfaces:
810         if (cp->string == NULL &&
811                         !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
812                 cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
813 +/* Uncomment this define to enable the HS Electrical Test support */
814 +#define DWC_HS_ELECT_TST 1
815 +#ifdef DWC_HS_ELECT_TST
816 +               /* Here we implement the HS Electrical Test support. The
817 +                * tester uses a vendor ID of 0x1A0A to indicate we should
818 +                * run a special test sequence. The product ID tells us
819 +                * which sequence to run. We invoke the test sequence by
820 +                * sending a non-standard SetFeature command to our root
821 +                * hub port. Our dwc_otg_hcd_hub_control() routine will
822 +                * recognize the command and perform the desired test
823 +                * sequence.
824 +                */
825 +               if (dev->descriptor.idVendor == 0x1A0A) {
826 +                       /* HSOTG Electrical Test */
827 +                       dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
828 +
829 +                       if (dev->bus && dev->bus->root_hub) {
830 +                               struct usb_device *hdev = dev->bus->root_hub;
831 +                               dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
832 +
833 +                               switch (dev->descriptor.idProduct) {
834 +                               case 0x0101:    /* TEST_SE0_NAK */
835 +                                       dev_warn(&dev->dev, "TEST_SE0_NAK\n");
836 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
837 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
838 +                                                       USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
839 +                                       break;
840 +
841 +                               case 0x0102:    /* TEST_J */
842 +                                       dev_warn(&dev->dev, "TEST_J\n");
843 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
844 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
845 +                                                       USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
846 +                                       break;
847 +
848 +                               case 0x0103:    /* TEST_K */
849 +                                       dev_warn(&dev->dev, "TEST_K\n");
850 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
851 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
852 +                                                       USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
853 +                                       break;
854 +
855 +                               case 0x0104:    /* TEST_PACKET */
856 +                                       dev_warn(&dev->dev, "TEST_PACKET\n");
857 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
858 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
859 +                                                       USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
860 +                                       break;
861 +
862 +                               case 0x0105:    /* TEST_FORCE_ENABLE */
863 +                                       dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
864 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
865 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
866 +                                                       USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
867 +                                       break;
868 +
869 +                               case 0x0106:    /* HS_HOST_PORT_SUSPEND_RESUME */
870 +                                       dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
871 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
872 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
873 +                                                       USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
874 +                                       break;
875 +
876 +                               case 0x0107:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
877 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
878 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
879 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
880 +                                                       USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
881 +                                       break;
882 +
883 +                               case 0x0108:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
884 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
885 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
886 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
887 +                                                       USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
888 +                               }
889 +                       }
890 +               }
891 +#endif /* DWC_HS_ELECT_TST */
892  
893         /* Now that all the interfaces are set up, register them
894          * to trigger binding of drivers to interfaces.  probe()
895 --- a/drivers/usb/core/otg_whitelist.h
896 +++ b/drivers/usb/core/otg_whitelist.h
897 @@ -19,33 +19,82 @@
898  static struct usb_device_id whitelist_table [] = {
899  
900  /* hubs are optional in OTG, but very handy ... */
901 +#define CERT_WITHOUT_HUBS
902 +#if defined(CERT_WITHOUT_HUBS)
903 +{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
904 +#else
905  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
906  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
907 +{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
908 +#endif
909  
910  #ifdef CONFIG_USB_PRINTER              /* ignoring nonstatic linkage! */
911  /* FIXME actually, printers are NOT supposed to use device classes;
912   * they're supposed to use interface classes...
913   */
914 -{ USB_DEVICE_INFO(7, 1, 1) },
915 -{ USB_DEVICE_INFO(7, 1, 2) },
916 -{ USB_DEVICE_INFO(7, 1, 3) },
917 +//{ USB_DEVICE_INFO(7, 1, 1) },
918 +//{ USB_DEVICE_INFO(7, 1, 2) },
919 +//{ USB_DEVICE_INFO(7, 1, 3) },
920  #endif
921  
922  #ifdef CONFIG_USB_NET_CDCETHER
923  /* Linux-USB CDC Ethernet gadget */
924 -{ USB_DEVICE(0x0525, 0xa4a1), },
925 +//{ USB_DEVICE(0x0525, 0xa4a1), },
926  /* Linux-USB CDC Ethernet + RNDIS gadget */
927 -{ USB_DEVICE(0x0525, 0xa4a2), },
928 +//{ USB_DEVICE(0x0525, 0xa4a2), },
929  #endif
930  
931  #if    defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
932  /* gadget zero, for testing */
933 -{ USB_DEVICE(0x0525, 0xa4a0), },
934 +//{ USB_DEVICE(0x0525, 0xa4a0), },
935  #endif
936 +   
937 +/* OPT Tester */
938 +{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
939 +{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
940 +{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
941 +{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
942 +{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
943 +{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME  */
944 +{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
945 +{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
946 +
947 +/* Sony cameras */        
948 +{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
949 +   
950 +/* Memory Devices */
951 +//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
952 +//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
953 +//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
954 +//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD  */
955 +{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
956 +//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
957 +
958 +/* HP Printers */
959 +//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
960 +//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
961 +
962 +/* Speakers */
963 +//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
964 +//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
965  
966  { }    /* Terminating entry */
967  };
968  
969 +static inline void report_errors(struct usb_device *dev)
970 +{
971 +       /* OTG MESSAGE: report errors here, customize to match your product */
972 +       dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
973 +                le16_to_cpu(dev->descriptor.idVendor),
974 +                le16_to_cpu(dev->descriptor.idProduct));
975 +        if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
976 +                dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
977 +        } else {        
978 +                dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
979 +        }
980 +}
981 +
982 +
983  static int is_targeted(struct usb_device *dev)
984  {
985         struct usb_device_id    *id = whitelist_table;
986 @@ -55,58 +104,83 @@ static int is_targeted(struct usb_device
987                 return 1;
988  
989         /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
990 -       if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
991 -            le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
992 -               return 0;
993 +       if (dev->descriptor.idVendor == 0x1a0a && 
994 +            dev->descriptor.idProduct == 0xbadd) {
995 +                return 0;
996 +       } else if (!enable_whitelist) {
997 +               return 1;
998 +        } else {
999  
1000 -       /* NOTE: can't use usb_match_id() since interface caches
1001 -        * aren't set up yet. this is cut/paste from that code.
1002 -        */
1003 -       for (id = whitelist_table; id->match_flags; id++) {
1004 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
1005 -                   id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
1006 -                       continue;
1007 -
1008 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
1009 -                   id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
1010 -                       continue;
1011 -
1012 -               /* No need to test id->bcdDevice_lo != 0, since 0 is never
1013 -                  greater than any unsigned number. */
1014 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
1015 -                   (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
1016 -                       continue;
1017 -
1018 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
1019 -                   (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
1020 -                       continue;
1021 -
1022 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
1023 -                   (id->bDeviceClass != dev->descriptor.bDeviceClass))
1024 -                       continue;
1025 -
1026 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
1027 -                   (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
1028 -                       continue;
1029 -
1030 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
1031 -                   (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
1032 -                       continue;
1033 +#ifdef DEBUG
1034 +                dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
1035 +                        dev->descriptor.idVendor,
1036 +                        dev->descriptor.idProduct,
1037 +                        dev->descriptor.bDeviceClass,
1038 +                        dev->descriptor.bDeviceSubClass,
1039 +                        dev->descriptor.bDeviceProtocol);
1040 +#endif
1041  
1042                 return 1;
1043 +               /* NOTE: can't use usb_match_id() since interface caches
1044 +                * aren't set up yet. this is cut/paste from that code.
1045 +                */
1046 +               for (id = whitelist_table; id->match_flags; id++) {
1047 +#ifdef DEBUG
1048 +                       dev_dbg(&dev->dev, 
1049 +                               "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
1050 +                               id->idVendor,
1051 +                               id->idProduct,
1052 +                               id->bDeviceClass,
1053 +                               id->bDeviceSubClass,
1054 +                               id->bDeviceProtocol);
1055 +#endif                       
1056 +
1057 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
1058 +                           id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
1059 +                               continue;
1060 +
1061 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
1062 +                           id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
1063 +                               continue;
1064 +
1065 +                       /* No need to test id->bcdDevice_lo != 0, since 0 is never
1066 +                          greater than any unsigned number. */
1067 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
1068 +                           (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
1069 +                               continue;
1070 +
1071 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
1072 +                           (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
1073 +                               continue;
1074 +
1075 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
1076 +                           (id->bDeviceClass != dev->descriptor.bDeviceClass))
1077 +                               continue;
1078 +
1079 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
1080 +                           (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
1081 +                               continue;
1082 +
1083 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
1084 +                           (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
1085 +                               continue;
1086 +
1087 +                       return 1;
1088 +               }
1089         }
1090  
1091         /* add other match criteria here ... */
1092  
1093 -
1094 -       /* OTG MESSAGE: report errors here, customize to match your product */
1095 -       dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
1096 -               le16_to_cpu(dev->descriptor.idVendor),
1097 -               le16_to_cpu(dev->descriptor.idProduct));
1098  #ifdef CONFIG_USB_OTG_WHITELIST
1099 +       report_errors(dev);
1100         return 0;
1101  #else
1102 -       return 1;
1103 +       if (enable_whitelist) {
1104 +               report_errors(dev);
1105 +               return 0;
1106 +       } else {
1107 +               return 1;
1108 +       }
1109  #endif
1110  }
1111  
1112 --- a/drivers/usb/gadget/Kconfig
1113 +++ b/drivers/usb/gadget/Kconfig
1114 @@ -536,6 +536,34 @@ config USB_GADGET_SUPERSPEED
1115         bool
1116         depends on USB_GADGET_DUALSPEED
1117  
1118 +config USB_GADGET_SNPS_DWC_OTG
1119 +       boolean "Synopsys Driver for DWC_otg Controller"
1120 +       depends on USB && EXPERIMENTAL
1121 +       select USB_OTG
1122 +       select USB_GADGET_DUALSPEED
1123 +       help
1124 +          Selects the Synopsys Driver for the DWC_otg Controller.
1125 +
1126 +config USB_DWC_OTG_LPM
1127 +       boolean "Enable LPM support"
1128 +       depends on USB && EXPERIMENTAL
1129 +       help
1130 +          Enables LPM support.
1131 +
1132 +config USB_GADGET_SNPS_DWC_OTG
1133 +       boolean "Synopsys Driver for DWC_otg Controller"
1134 +       depends on USB && EXPERIMENTAL
1135 +       select USB_OTG
1136 +       select USB_GADGET_DUALSPEED
1137 +       help
1138 +          Selects the Synopsys Driver for the DWC_otg Controller.
1139 +
1140 +config USB_DWC_OTG_LPM
1141 +       boolean "Enable LPM support"
1142 +       depends on USB && EXPERIMENTAL
1143 +       help
1144 +          Enables LPM support.
1145 +
1146  #
1147  # USB Gadget Drivers
1148  #
1149 --- a/drivers/usb/gadget/file_storage.c
1150 +++ b/drivers/usb/gadget/file_storage.c
1151 @@ -573,8 +573,37 @@ config_desc = {
1152         .iConfiguration =       FSG_STRING_CONFIG,
1153         .bmAttributes =         USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
1154         .bMaxPower =            CONFIG_USB_GADGET_VBUS_DRAW / 2,
1155 +        //.bMaxPower =         0, //unused suggestion by DWC patch
1156  };
1157  
1158 +#ifdef CONFIG_USB_DWC_OTG_LPM
1159 +#define USB_DEVICE_CAPABILITY_20_EXTENSION     0x02
1160 +#define USB_20_EXT_LPM                         0x02
1161 +typedef struct usb_dev_cap_20_ext_desc {
1162 +       __u8 bLength;
1163 +       __u8 bDescriptorType;
1164 +       __u8 bDevCapabilityType;
1165 +       __le32 bmAttributes;
1166 +} __attribute__ ((__packed__)) usb_dev_cap_20_ext_desc_t;
1167 +
1168 +static struct usb_bos_20_ext_desc {
1169 +       struct usb_bos_descriptor bos_desc;
1170 +       struct usb_dev_cap_20_ext_desc dev_cap_20_ext_desc;
1171 +} __attribute__ ((__packed__)) bos_20_ext_desc = {
1172 +       {
1173 +               .bLength =              sizeof(struct usb_bos_descriptor),
1174 +               .bDescriptorType =      USB_DT_BOS,
1175 +               .wTotalLength =         sizeof(struct usb_bos_20_ext_desc),
1176 +               .bNumDeviceCaps =       1,
1177 +       },
1178 +       {
1179 +               .bLength =              sizeof(struct usb_dev_cap_20_ext_desc),
1180 +               .bDescriptorType =      USB_DT_DEVICE_CAPABILITY,
1181 +               .bDevCapabilityType =   USB_DEVICE_CAPABILITY_20_EXTENSION,
1182 +               .bmAttributes =         USB_20_EXT_LPM,
1183 +       },
1184 +};
1185 +#endif
1186  
1187  static struct usb_qualifier_descriptor
1188  dev_qualifier = {
1189 @@ -989,6 +1018,24 @@ get_config:
1190                         if (gadget_is_superspeed(fsg->gadget))
1191                                 value = populate_bos(fsg, req->buf);
1192                         break;
1193 +#ifdef CONFIG_USB_DWC_OTG_LPM
1194 +               case USB_DT_BOS:
1195 +                       /* When the PCD has LPM enabled set the LPM
1196 +                        * Feature bit to 1 when not enabled set the
1197 +                        * bit to 0. */
1198 +                       if (usb_gadget_test_lpm_support(fsg->gadget)) {
1199 +                               VDBG(fsg, "LPM support enabled in DWC UDC PCD\n");
1200 +                               bos_20_ext_desc.dev_cap_20_ext_desc.bmAttributes |= USB_20_EXT_LPM;
1201 +                       } else {
1202 +                               VDBG(fsg, "LPM support disabled in DWC UDC PCD\n");
1203 +                               bos_20_ext_desc.dev_cap_20_ext_desc.bmAttributes &= ~USB_20_EXT_LPM;
1204 +                       }
1205 +                       DBG(fsg, "sending BOS descriptor to host\n");
1206 +                       value = sizeof bos_20_ext_desc;
1207 +                       memcpy(req->buf, &bos_20_ext_desc, value);
1208 +                       break;
1209 +#endif
1210 +
1211                 }
1212  
1213                 break;
1214 @@ -2650,6 +2697,9 @@ static int received_cbw(struct fsg_dev *
1215                         fsg_set_halt(fsg, fsg->bulk_out);
1216                         halt_bulk_in_endpoint(fsg);
1217                 }
1218 +               fsg->bulk_in->ops->set_halt(fsg->bulk_in, 3);
1219 +               fsg_set_halt(fsg, fsg->bulk_out);
1220 +               fsg->bulk_out->ops->set_halt(fsg->bulk_out, 3);
1221                 return -EINVAL;
1222         }
1223  
1224 @@ -3011,7 +3061,8 @@ static void handle_exception(struct fsg_
1225                  * bulk endpoint, clear the halt now.  (The SuperH UDC
1226                  * requires this.) */
1227                 if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
1228 -                       usb_ep_clear_halt(fsg->bulk_in);
1229 +                       //usb_ep_clear_halt(fsg->bulk_in); //DWC patch:
1230 +                       fsg->bulk_in->ops->set_halt(fsg->bulk_in, 2);
1231  
1232                 if (transport_is_bbb()) {
1233                         if (fsg->ep0_req_tag == exception_req_tag)
1234 @@ -3085,6 +3136,9 @@ static int fsg_main_thread(void *fsg_)
1235          * that expects a __user pointer and it will work okay. */
1236         set_fs(get_ds());
1237  
1238 +       /* Setting this thread high priority */
1239 +       set_user_nice(current, -20);
1240 +
1241         /* The main loop */
1242         while (fsg->state != FSG_STATE_TERMINATED) {
1243                 if (exception_in_progress(fsg) || signal_pending(current)) {
1244 @@ -3232,6 +3286,13 @@ static int __init check_parameters(struc
1245                 gcnum = usb_gadget_controller_number(fsg->gadget);
1246                 if (gcnum >= 0)
1247                         mod_data.release = 0x0300 + gcnum;
1248 +               else if (gadget_is_dwc_otg(fsg->gadget)) {
1249 +                       mod_data.release = __constant_cpu_to_le16 (0x0200);
1250 +                       mod_data.vendor  = __constant_cpu_to_le16 (0x053f);
1251 +                       if (mod_data.product == DRIVER_PRODUCT_ID) {
1252 +                               mod_data.product  = __constant_cpu_to_le16 (0x0000);
1253 +                       }
1254 +               }
1255                 else {
1256                         WARNING(fsg, "controller '%s' not recognized\n",
1257                                 fsg->gadget->name);
1258 @@ -3493,6 +3554,13 @@ static int __init fsg_bind(struct usb_ga
1259  
1260         rc = -ENOMEM;
1261  
1262 +#ifdef CONFIG_USB_DWC_OTG_LPM
1263 +       /* When LPM is enabled, Inform the host that the remote wake
1264 +        * up capability is supported. */
1265 +       if (usb_gadget_test_lpm_support(fsg->gadget))
1266 +               config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
1267 +#endif
1268 +
1269         /* Allocate the request and buffer for endpoint 0 */
1270         fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
1271         if (!req)
1272 --- a/drivers/usb/host/Kconfig
1273 +++ b/drivers/usb/host/Kconfig
1274 @@ -571,6 +571,19 @@ config USB_HWA_HCD
1275           To compile this driver a module, choose M here: the module
1276           will be called "hwa-hc".
1277  
1278 +config USB_DWCOTG
1279 +       tristate "Synopsis DWC host support"
1280 +       depends on USB
1281 +       help
1282 +         The Synopsis DWC controller is a dual-role
1283 +         host/peripheral/OTG ("On The Go") USB controllers.
1284 +
1285 +         Enable this option to support this IP in host controller mode.
1286 +         If unsure, say N.
1287 +
1288 +         To compile this driver as a module, choose M here: the
1289 +         modules built will be called dwc_otg and dwc_common_port.
1290 +
1291  config USB_IMX21_HCD
1292         tristate "i.MX21 HCD support"
1293         depends on USB && ARM && ARCH_MXC
1294 --- a/drivers/usb/host/Makefile
1295 +++ b/drivers/usb/host/Makefile
1296 @@ -33,6 +33,8 @@ obj-$(CONFIG_USB_U132_HCD)    += u132-hcd.o
1297  obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
1298  obj-$(CONFIG_USB_ISP1760_HCD)  += isp1760.o
1299  obj-$(CONFIG_USB_HWA_HCD)      += hwa-hc.o
1300 +
1301 +obj-$(CONFIG_USB_DWCOTG)        += dwc_otg/ dwc_common_port/
1302  obj-$(CONFIG_USB_IMX21_HCD)    += imx21-hcd.o
1303  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += fsl-mph-dr-of.o
1304  obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
1305 --- /dev/null
1306 +++ b/drivers/usb/host/dwc_common_port/Makefile
1307 @@ -0,0 +1,44 @@
1308 +#
1309 +# Makefile for DWC_common library
1310 +#
1311 +
1312 +ifneq ($(KERNELRELEASE),)
1313 +
1314 +#CPPFLAGS      += -DDEBUG_MEMORY
1315 +
1316 +CPPFLAGS       += -DDEBUG
1317 +CPPFLAGS       += -DDWC_LINUX
1318 +
1319 +obj-$(CONFIG_USB_DWCOTG)       += dwc_common_port_lib.o
1320 +dwc_common_port_lib-objs       := dwc_cc.o dwc_modpow.o dwc_dh.o \
1321 +                                  dwc_crypto.o dwc_notifier.o \
1322 +                                  dwc_common_linux.o dwc_mem.o
1323 +
1324 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
1325 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
1326 +
1327 +ifneq ($(kernrel3),2.6.20)
1328 +# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually
1329 +EXTRA_CFLAGS += $(CPPFLAGS)
1330 +endif
1331 +
1332 +else
1333 +
1334 +ifeq ($(DOXYGEN),)
1335 +DOXYGEN                := $(DOXYGEN)
1336 +endif
1337 +
1338 +default:
1339 +       $(MAKE) -C$(KDIR) M=$(PWD) modules
1340 +
1341 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
1342 +       $(DOXYGEN) doc/doxygen.cfg
1343 +
1344 +tags:  $(wildcard *.[hc])
1345 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
1346 +
1347 +endif
1348 +
1349 +clean:
1350 +       rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
1351 +
1352 --- /dev/null
1353 +++ b/drivers/usb/host/dwc_common_port/Makefile.linux
1354 @@ -0,0 +1,36 @@
1355 +#
1356 +# Makefile for DWC_common library
1357 +#
1358 +ifneq ($(KERNELRELEASE),)
1359 +
1360 +#CPPFLAGS      += -DDEBUG_MEMORY
1361 +
1362 +#CPPFLAGS      += -DDEBUG
1363 +CPPFLAGS       += -DDWC_LINUX
1364 +
1365 +obj-m          := dwc_common_port_lib.o
1366 +dwc_common_port_lib-objs       := dwc_cc.o dwc_modpow.o dwc_dh.o \
1367 +                                  dwc_crypto.o dwc_notifier.o \
1368 +                                  dwc_common_linux.o dwc_mem.o
1369 +
1370 +else
1371 +
1372 +
1373 +ifeq ($(DOXYGEN),)
1374 +DOXYGEN                := $(DOXYGEN)
1375 +endif
1376 +
1377 +default:
1378 +       $(MAKE) -C$(KDIR) M=$(PWD) modules
1379 +
1380 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
1381 +       $(DOXYGEN) doc/doxygen.cfg
1382 +
1383 +tags:  $(wildcard *.[hc])
1384 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
1385 +
1386 +endif
1387 +
1388 +clean:
1389 +       rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
1390 +
1391 --- /dev/null
1392 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.c
1393 @@ -0,0 +1,506 @@
1394 +/* =========================================================================
1395 + * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.c $
1396 + * $Revision: #1 $
1397 + * $Date: 2008/12/21 $
1398 + * $Change: 1156609 $
1399 + *
1400 + * Synopsys Portability Library Software and documentation
1401 + * (hereinafter, "Software") is an Unsupported proprietary work of
1402 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
1403 + * between Synopsys and you.
1404 + *
1405 + * The Software IS NOT an item of Licensed Software or Licensed Product
1406 + * under any End User Software License Agreement or Agreement for
1407 + * Licensed Product with Synopsys or any supplement thereto. You are
1408 + * permitted to use and redistribute this Software in source and binary
1409 + * forms, with or without modification, provided that redistributions
1410 + * of source code must retain this notice. You may not view, use,
1411 + * disclose, copy or distribute this file or any information contained
1412 + * herein except pursuant to this license grant from Synopsys. If you
1413 + * do not agree with this notice, including the disclaimer below, then
1414 + * you are not authorized to use the Software.
1415 + *
1416 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
1417 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1418 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1419 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
1420 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1421 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1422 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1423 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1424 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1425 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1426 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1427 + * DAMAGE.
1428 + * ========================================================================= */
1429 +#include "dwc_cc.h"
1430 +
1431 +typedef struct dwc_cc
1432 +{
1433 +       uint32_t uid;
1434 +       uint8_t chid[16];
1435 +       uint8_t cdid[16];
1436 +       uint8_t ck[16];
1437 +       uint8_t *name;
1438 +       uint8_t length;
1439 +        DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
1440 +} dwc_cc_t;
1441 +
1442 +DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
1443 +
1444 +/** The main structure for CC management.  */
1445 +struct dwc_cc_if
1446 +{
1447 +       dwc_mutex_t *mutex;
1448 +       char *filename;
1449 +
1450 +       unsigned is_host:1;
1451 +
1452 +       dwc_notifier_t *notifier;
1453 +
1454 +       struct context_list list;
1455 +};
1456 +
1457 +#ifdef DEBUG
1458 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
1459 +{
1460 +       int i;
1461 +       DWC_PRINTF("%s: ", name);
1462 +       for (i=0; i<len; i++) {
1463 +               DWC_PRINTF("%02x ", bytes[i]);
1464 +       }
1465 +       DWC_PRINTF("\n");
1466 +}
1467 +#else
1468 +#define dump_bytes(x...)
1469 +#endif
1470 +
1471 +static dwc_cc_t *alloc_cc(uint8_t *name, uint32_t length)
1472 +{
1473 +       dwc_cc_t *cc = DWC_ALLOC(sizeof(dwc_cc_t));
1474 +       if (!cc) {
1475 +               return NULL;
1476 +       }
1477 +       DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
1478 +
1479 +       if (name) {
1480 +               cc->length = length;
1481 +               cc->name = DWC_ALLOC(length);
1482 +               DWC_MEMCPY(cc->name, name, length);
1483 +       }
1484 +
1485 +       return cc;
1486 +}
1487 +
1488 +static void free_cc(dwc_cc_t *cc)
1489 +{
1490 +       if (cc->name) {
1491 +               DWC_FREE(cc->name);
1492 +       }
1493 +       DWC_FREE(cc);
1494 +}
1495 +
1496 +static uint32_t next_uid(dwc_cc_if_t *cc_if)
1497 +{
1498 +       uint32_t uid = 0;
1499 +       dwc_cc_t *cc;
1500 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
1501 +               if (cc->uid > uid) {
1502 +                       uid = cc->uid;
1503 +               }
1504 +       }
1505 +
1506 +       if (uid == 0) {
1507 +               uid = 255;
1508 +       }
1509 +
1510 +       return uid + 1;
1511 +}
1512 +
1513 +static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
1514 +{
1515 +       dwc_cc_t *cc;
1516 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
1517 +               if (cc->uid == uid) {
1518 +                       return cc;
1519 +               }
1520 +       }
1521 +       return NULL;
1522 +}
1523 +
1524 +static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
1525 +{
1526 +       unsigned int size = 0;
1527 +       dwc_cc_t *cc;
1528 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
1529 +               size += (48 + 1);
1530 +               if (cc->name) {
1531 +                       size += cc->length;
1532 +               }
1533 +       }
1534 +       return size;
1535 +}
1536 +
1537 +static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
1538 +{
1539 +       uint32_t uid = 0;
1540 +       dwc_cc_t *cc;
1541 +
1542 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
1543 +               if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
1544 +                       uid = cc->uid;
1545 +                       break;
1546 +               }
1547 +       }
1548 +       return uid;
1549 +}
1550 +static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
1551 +{
1552 +       uint32_t uid = 0;
1553 +       dwc_cc_t *cc;
1554 +
1555 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
1556 +               if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
1557 +                       uid = cc->uid;
1558 +                       break;
1559 +               }
1560 +       }
1561 +       return uid;
1562 +}
1563 +
1564 +/* Internal cc_add */
1565 +static int32_t cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
1566 +{
1567 +       dwc_cc_t *cc;
1568 +       uint32_t uid;
1569 +
1570 +       if (cc_if->is_host) {
1571 +               uid = cc_match_cdid(cc_if, cdid);
1572 +       }
1573 +       else {
1574 +               uid = cc_match_chid(cc_if, chid);
1575 +       }
1576 +
1577 +       if (uid) {
1578 +               DWC_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
1579 +               cc = cc_find(cc_if, uid);
1580 +       }
1581 +       else {
1582 +               cc = alloc_cc(name, length);
1583 +               cc->uid = next_uid(cc_if);
1584 +               DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
1585 +       }
1586 +
1587 +       DWC_MEMCPY(&(cc->chid[0]), chid, 16);
1588 +       DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
1589 +       DWC_MEMCPY(&(cc->ck[0]), ck, 16);
1590 +
1591 +       DWC_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
1592 +       dump_bytes("CHID", cc->chid, 16);
1593 +       dump_bytes("CDID", cc->cdid, 16);
1594 +       dump_bytes("CK", cc->ck, 16);
1595 +       return cc->uid;
1596 +}
1597 +
1598 +/* Internal cc_clear */
1599 +static void cc_clear(dwc_cc_if_t *cc_if)
1600 +{
1601 +       while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
1602 +               dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
1603 +               DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
1604 +               free_cc(cc);
1605 +       }
1606 +}
1607 +
1608 +dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host)
1609 +{
1610 +       dwc_cc_if_t *cc_if = NULL;
1611 +
1612 +       /* Allocate a common_cc_if structure */
1613 +       cc_if = DWC_ALLOC(sizeof(dwc_cc_if_t));
1614 +
1615 +       if(!cc_if)
1616 +               return NULL;
1617 +
1618 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
1619 +       DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
1620 +#else
1621 +       cc_if->mutex = DWC_MUTEX_ALLOC();
1622 +#endif
1623 +       DWC_CIRCLEQ_INIT(&cc_if->list);
1624 +       cc_if->is_host = is_host;
1625 +       cc_if->notifier = notifier;
1626 +       return cc_if;
1627 +}
1628 +
1629 +void dwc_cc_if_free(dwc_cc_if_t *cc_if)
1630 +{
1631 +       DWC_MUTEX_FREE(cc_if->mutex);
1632 +       cc_clear(cc_if);
1633 +       DWC_FREE(cc_if);
1634 +}
1635 +
1636 +static void cc_changed(dwc_cc_if_t *cc_if)
1637 +{
1638 +       if (cc_if->notifier) {
1639 +               dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
1640 +       }
1641 +}
1642 +
1643 +void dwc_cc_clear(dwc_cc_if_t *cc_if)
1644 +{
1645 +       DWC_MUTEX_LOCK(cc_if->mutex);
1646 +       cc_clear(cc_if);
1647 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1648 +       cc_changed(cc_if);
1649 +}
1650 +
1651 +int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
1652 +{
1653 +       uint32_t uid;
1654 +
1655 +       DWC_MUTEX_LOCK(cc_if->mutex);
1656 +       uid = cc_add(cc_if, chid, cdid, ck, name, length);
1657 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1658 +       cc_changed(cc_if);
1659 +
1660 +       return uid;
1661 +}
1662 +
1663 +void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id,
1664 +                         uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
1665 +{
1666 +       dwc_cc_t* cc;
1667 +
1668 +       DWC_DEBUG("Change connection context %d", id);
1669 +
1670 +       DWC_MUTEX_LOCK(cc_if->mutex);
1671 +       cc = cc_find(cc_if, id);
1672 +       if (!cc) {
1673 +               DWC_ERROR("Uid %d not found in cc list", id);
1674 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
1675 +               return;
1676 +       }
1677 +
1678 +       if (chid) {
1679 +               DWC_MEMCPY(&(cc->chid[0]), chid, 16);
1680 +       }
1681 +       if (cdid) {
1682 +               DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
1683 +       }
1684 +       if (ck) {
1685 +               DWC_MEMCPY(&(cc->ck[0]), ck, 16);
1686 +       }
1687 +
1688 +       if (name) {
1689 +               if (cc->name) {
1690 +                       DWC_FREE(cc->name);
1691 +               }
1692 +               cc->name = DWC_ALLOC(length);
1693 +               cc->length = length;
1694 +               DWC_MEMCPY(cc->name, name, length);
1695 +       }
1696 +
1697 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1698 +
1699 +       cc_changed(cc_if);
1700 +
1701 +       DWC_DEBUG("Changed connection context id=%d\n", id);
1702 +       dump_bytes("New CHID", cc->chid, 16);
1703 +       dump_bytes("New CDID", cc->cdid, 16);
1704 +       dump_bytes("New CK", cc->ck, 16);
1705 +}
1706 +
1707 +void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id)
1708 +{
1709 +       dwc_cc_t *cc;
1710 +
1711 +       DWC_DEBUG("Removing connection context %d", id);
1712 +
1713 +       DWC_MUTEX_LOCK(cc_if->mutex);
1714 +       cc = cc_find(cc_if, id);
1715 +       if (!cc) {
1716 +               DWC_ERROR("Uid %d not found in cc list", id);
1717 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
1718 +               return;
1719 +       }
1720 +
1721 +       DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
1722 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1723 +       free_cc(cc);
1724 +
1725 +       cc_changed(cc_if);
1726 +}
1727 +
1728 +uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length)
1729 +{
1730 +       uint8_t *buf, *x;
1731 +       uint8_t zero = 0;
1732 +       dwc_cc_t *cc;
1733 +
1734 +       DWC_MUTEX_LOCK(cc_if->mutex);
1735 +       *length = cc_data_size(cc_if);
1736 +       if (!(*length)) {
1737 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
1738 +               return NULL;
1739 +       }
1740 +
1741 +       DWC_DEBUG("Creating data for saving (length=%d)", *length);
1742 +
1743 +       buf = DWC_ALLOC(*length);
1744 +       if (!buf) {
1745 +               *length = 0;
1746 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
1747 +               return NULL;
1748 +       }
1749 +
1750 +       x = buf;
1751 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
1752 +               DWC_MEMCPY(x, cc->chid, 16);
1753 +               x += 16;
1754 +               DWC_MEMCPY(x, cc->cdid, 16);
1755 +               x += 16;
1756 +               DWC_MEMCPY(x, cc->ck, 16);
1757 +               x += 16;
1758 +               if (cc->name) {
1759 +                       DWC_MEMCPY(x, &cc->length, 1);
1760 +                       x += 1;
1761 +                       DWC_MEMCPY(x, cc->name, cc->length);
1762 +                       x += cc->length;
1763 +               }
1764 +               else {
1765 +                       DWC_MEMCPY(x, &zero, 1);
1766 +                       x += 1;
1767 +               }
1768 +       }
1769 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1770 +
1771 +       return buf;
1772 +}
1773 +
1774 +void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
1775 +{
1776 +       uint8_t name_length;
1777 +       uint8_t *name;
1778 +       uint8_t *chid;
1779 +       uint8_t *cdid;
1780 +       uint8_t *ck;
1781 +       uint32_t i = 0;
1782 +
1783 +       DWC_MUTEX_LOCK(cc_if->mutex);
1784 +       cc_clear(cc_if);
1785 +
1786 +       while (i < length) {
1787 +               chid = &data[i];
1788 +               i += 16;
1789 +               cdid = &data[i];
1790 +               i += 16;
1791 +               ck = &data[i];
1792 +               i += 16;
1793 +
1794 +               name_length = data[i];
1795 +               i ++;
1796 +
1797 +               if (name_length) {
1798 +                       name = &data[i];
1799 +                       i += name_length;
1800 +               }
1801 +               else {
1802 +                       name = NULL;
1803 +               }
1804 +
1805 +               /* check to see if we haven't overflown the buffer */
1806 +               if (i > length) {
1807 +                       DWC_ERROR("Data format error while attempting to load CCs "
1808 +                                 "(nlen=%d, iter=%d, buflen=%d).", name_length, i, length);
1809 +                       break;
1810 +               }
1811 +
1812 +               cc_add(cc_if, chid, cdid, ck, name, name_length);
1813 +       }
1814 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1815 +
1816 +       cc_changed(cc_if);
1817 +}
1818 +
1819 +uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
1820 +{
1821 +       uint32_t uid = 0;
1822 +
1823 +       DWC_MUTEX_LOCK(cc_if->mutex);
1824 +       uid = cc_match_chid(cc_if, chid);
1825 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1826 +       return uid;
1827 +}
1828 +uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
1829 +{
1830 +       uint32_t uid = 0;
1831 +
1832 +       DWC_MUTEX_LOCK(cc_if->mutex);
1833 +       uid = cc_match_cdid(cc_if, cdid);
1834 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1835 +       return uid;
1836 +}
1837 +
1838 +uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
1839 +{
1840 +       uint8_t *ck = NULL;
1841 +       dwc_cc_t *cc;
1842 +
1843 +       DWC_MUTEX_LOCK(cc_if->mutex);
1844 +       cc = cc_find(cc_if, id);
1845 +       if (cc) {
1846 +               ck = cc->ck;
1847 +       }
1848 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1849 +
1850 +       return ck;
1851 +
1852 +}
1853 +
1854 +uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
1855 +{
1856 +       uint8_t *retval = NULL;
1857 +       dwc_cc_t *cc;
1858 +
1859 +       DWC_MUTEX_LOCK(cc_if->mutex);
1860 +       cc = cc_find(cc_if, id);
1861 +       if (cc) {
1862 +               retval = cc->chid;
1863 +       }
1864 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1865 +
1866 +       return retval;
1867 +}
1868 +
1869 +uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
1870 +{
1871 +       uint8_t *retval = NULL;
1872 +       dwc_cc_t *cc;
1873 +
1874 +       DWC_MUTEX_LOCK(cc_if->mutex);
1875 +       cc = cc_find(cc_if, id);
1876 +       if (cc) {
1877 +               retval = cc->cdid;
1878 +       }
1879 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1880 +
1881 +       return retval;
1882 +}
1883 +
1884 +uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
1885 +{
1886 +       uint8_t *retval = NULL;
1887 +       dwc_cc_t *cc;
1888 +
1889 +       DWC_MUTEX_LOCK(cc_if->mutex);
1890 +       *length = 0;
1891 +       cc = cc_find(cc_if, id);
1892 +       if (cc) {
1893 +               *length = cc->length;
1894 +               retval = cc->name;
1895 +       }
1896 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
1897 +
1898 +       return retval;
1899 +}
1900 --- /dev/null
1901 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.h
1902 @@ -0,0 +1,209 @@
1903 +/* =========================================================================
1904 + * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.h $
1905 + * $Revision: #1 $
1906 + * $Date: 2008/12/21 $
1907 + * $Change: 1156609 $
1908 + *
1909 + * Synopsys Portability Library Software and documentation
1910 + * (hereinafter, "Software") is an Unsupported proprietary work of
1911 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
1912 + * between Synopsys and you.
1913 + *
1914 + * The Software IS NOT an item of Licensed Software or Licensed Product
1915 + * under any End User Software License Agreement or Agreement for
1916 + * Licensed Product with Synopsys or any supplement thereto. You are
1917 + * permitted to use and redistribute this Software in source and binary
1918 + * forms, with or without modification, provided that redistributions
1919 + * of source code must retain this notice. You may not view, use,
1920 + * disclose, copy or distribute this file or any information contained
1921 + * herein except pursuant to this license grant from Synopsys. If you
1922 + * do not agree with this notice, including the disclaimer below, then
1923 + * you are not authorized to use the Software.
1924 + *
1925 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
1926 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1927 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1928 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
1929 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1930 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1931 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1932 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1933 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1934 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1935 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1936 + * DAMAGE.
1937 + * ========================================================================= */
1938 +#ifndef _DWC_CC_H_
1939 +#define _DWC_CC_H_
1940 +
1941 +/** @file
1942 + *
1943 + * This file defines the Context Context library.
1944 + *
1945 + * The main data structure is dwc_cc_if_t which is returned by either the
1946 + * dwc_cc_if_alloc function or returned by the module to the user via a provided
1947 + * function. The data structure is opaque and should only be manipulated via the
1948 + * functions provied in this API.
1949 + *
1950 + * It manages a list of connection contexts and operations can be performed to
1951 + * add, remove, query, search, and change, those contexts.  Additionally,
1952 + * a dwc_notifier_t object can be requested from the manager so that
1953 + * the user can be notified whenever the context list has changed.
1954 + */
1955 +
1956 +#include "dwc_os.h"
1957 +#include "dwc_list.h"
1958 +#include "dwc_notifier.h"
1959 +
1960 +
1961 +/* Notifications */
1962 +#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"
1963 +
1964 +struct dwc_cc_if;
1965 +typedef struct dwc_cc_if dwc_cc_if_t;
1966 +
1967 +
1968 +/** @name Connection Context Operations */
1969 +/** @{ */
1970 +
1971 +/** This function allocates memory for a dwc_cc_if_t structure, initializes
1972 + * fields to default values, and returns a pointer to the structure or NULL on
1973 + * error. */
1974 +extern dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host);
1975 +
1976 +/** Frees the memory for the specified CC structure allocated from
1977 + * dwc_cc_if_alloc(). */
1978 +extern void dwc_cc_if_free(dwc_cc_if_t *cc_if);
1979 +
1980 +/** Removes all contexts from the connection context list */
1981 +extern void dwc_cc_clear(dwc_cc_if_t *cc_if);
1982 +
1983 +/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.
1984 + * If a CHID already exists, the CK and name are overwritten.  Statistics are
1985 + * not overwritten.
1986 + *
1987 + * @param cc_if The cc_if structure.
1988 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.
1989 + * @param ck A pointer to the 16-byte CK.  This value will be copied.
1990 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.
1991 + * @param name An optional host friendly name as defined in the association model
1992 + * spec.  Must be a UTF16-LE unicode string.  Can be NULL to indicated no name.
1993 + * @param length The length othe unicode string.
1994 + * @return A unique identifier used to refer to this context that is valid for
1995 + * as long as this context is still in the list. */
1996 +extern int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length);
1997 +
1998 +/** Changes the CHID, CK, CDID, or Name values of a connection context in the
1999 + * list, preserving any accumulated statistics.  This would typically be called
2000 + * if the host decideds to change the context with a SET_CONNECTION request.
2001 + *
2002 + * @param cc_if The cc_if structure.
2003 + * @param id The identifier of the connection context.
2004 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.  NULL
2005 + * indicates no change.
2006 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.  NULL
2007 + * indicates no change.
2008 + * @param ck A pointer to the 16-byte CK.  This value will be copied.  NULL
2009 + * indicates no change.
2010 + * @param name Host friendly name UTF16-LE.  NULL indicates no change.
2011 + * @param length Length of name. */
2012 +extern void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length);
2013 +
2014 +/** Remove the specified connection context.
2015 + * @param cc_if The cc_if structure.
2016 + * @param id The identifier of the connection context to remove. */
2017 +extern void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id);
2018 +
2019 +/** Get a binary block of data for the connection context list and attributes.
2020 + * This data can be used by the OS specific driver to save the connection
2021 + * context list into non-volatile memory.
2022 + *
2023 + * @param cc_if The cc_if structure.
2024 + * @param length Return the length of the data buffer.
2025 + * @return A pointer to the data buffer.  The memory for this buffer should be freed with DWC_FREE() after use. */
2026 +extern uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length);
2027 +
2028 +/** Restore the connection context list from the binary data that was previously
2029 + * returned from a call to dwc_cc_data_for_save.  This can be used by the OS specific
2030 + * driver to load a connection context list from non-volatile memory.
2031 + *
2032 + * @param cc_if The cc_if structure.
2033 + * @param data The data bytes as returned from dwc_cc_data_for_save.
2034 + * @param length The length of the data. */
2035 +extern void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, unsigned int length);
2036 +
2037 +/** Find the connection context from the specified CHID.
2038 + *
2039 + * @param cc_if The cc_if structure.
2040 + * @param chid A pointer to the CHID data.
2041 + * @return A non-zero identifier of the connection context if the CHID matches.
2042 + * Otherwise returns 0. */
2043 +extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);
2044 +
2045 +/** Find the connection context from the specified CDID.
2046 + *
2047 + * @param cc_if The cc_if structure.
2048 + * @param cdid A pointer to the CDID data.
2049 + * @return A non-zero identifier of the connection context if the CHID matches.
2050 + * Otherwise returns 0. */
2051 +extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);
2052 +
2053 +/** Retrieve the CK from the specified connection context.
2054 + *
2055 + * @param cc_if The cc_if structure.
2056 + * @param id The identifier of the connection context.
2057 + * @return A pointer to the CK data.  The memory does not need to be freed. */
2058 +extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);
2059 +
2060 +/** Retrieve the CHID from the specified connection context.
2061 + *
2062 + * @param cc_if The cc_if structure.
2063 + * @param id The identifier of the connection context.
2064 + * @return A pointer to the CHID data.  The memory does not need to be freed. */
2065 +extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);
2066 +
2067 +/** Retrieve the CDID from the specified connection context.
2068 + *
2069 + * @param cc_if The cc_if structure.
2070 + * @param id The identifier of the connection context.
2071 + * @return A pointer to the CDID data.  The memory does not need to be freed. */
2072 +extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);
2073 +
2074 +extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);
2075 +
2076 +/** Checks a buffer for non-zero.
2077 + * @param id A pointer to a 16 byte buffer. 
2078 + * @return true if the 16 byte value is non-zero. */
2079 +static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {
2080 +       int i;
2081 +       for (i=0; i<16; i++) {
2082 +               if (id[i]) return 1;
2083 +       }
2084 +       return 0;
2085 +}
2086 +
2087 +/** Checks a buffer for zero.
2088 + * @param id A pointer to a 16 byte buffer. 
2089 + * @return true if the 16 byte value is zero. */
2090 +static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {
2091 +       return !dwc_assoc_is_not_zero_id(id);
2092 +}
2093 +
2094 +/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into
2095 + * buffer. */
2096 +static inline int dwc_print_id_string(char *buffer, uint8_t *id) {
2097 +       char *ptr = buffer;
2098 +       int i;
2099 +       for (i=0; i<16; i++) {
2100 +               ptr += DWC_SPRINTF(ptr, "%02x", id[i]);
2101 +               if (i < 15) {
2102 +                       ptr += DWC_SPRINTF(ptr, " ");
2103 +               }
2104 +       }
2105 +       return ptr - buffer;
2106 +}
2107 +
2108 +/** @} */
2109 +
2110 +#endif /* _DWC_CC_H_ */
2111 +
2112 --- /dev/null
2113 +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
2114 @@ -0,0 +1,1247 @@
2115 +#include "dwc_cc.h"
2116 +#include "dwc_modpow.h"
2117 +#include "dwc_dh.h"
2118 +#include "dwc_crypto.h"
2119 +#include "dwc_notifier.h"
2120 +
2121 +#include <linux/kernel.h>
2122 +#include <linux/init.h>
2123 +#include <linux/module.h>
2124 +#include <linux/kthread.h>
2125 +
2126 +MODULE_DESCRIPTION("DWC Common Library - Portable version");
2127 +MODULE_AUTHOR("Synopsys Inc.");
2128 +MODULE_LICENSE ("GPL");
2129 +
2130 +static int dwc_common_port_init_module(void)
2131 +{
2132 +       printk( KERN_DEBUG "Module dwc_common_port init\n" );
2133 +#ifdef DEBUG_MEMORY
2134 +       dwc_memory_debug_start();
2135 +#endif
2136 +       dwc_alloc_notification_manager();
2137 +       return 0;
2138 +}
2139 +
2140 +static void dwc_common_port_exit_module(void)
2141 +{
2142 +       printk( KERN_DEBUG "Module dwc_common_port exit\n" );
2143 +       dwc_free_notification_manager();
2144 +#ifdef DEBUG_MEMORY
2145 +       dwc_memory_debug_stop();
2146 +#endif
2147 +}
2148 +
2149 +module_init(dwc_common_port_init_module);
2150 +module_exit(dwc_common_port_exit_module);
2151 +
2152 +/* CC */
2153 +EXPORT_SYMBOL(dwc_cc_if_alloc);
2154 +EXPORT_SYMBOL(dwc_cc_if_free);
2155 +EXPORT_SYMBOL(dwc_cc_clear);
2156 +EXPORT_SYMBOL(dwc_cc_add);
2157 +EXPORT_SYMBOL(dwc_cc_remove);
2158 +EXPORT_SYMBOL(dwc_cc_change);
2159 +EXPORT_SYMBOL(dwc_cc_data_for_save);
2160 +EXPORT_SYMBOL(dwc_cc_restore_from_data);
2161 +EXPORT_SYMBOL(dwc_cc_match_chid);
2162 +EXPORT_SYMBOL(dwc_cc_match_cdid);
2163 +EXPORT_SYMBOL(dwc_cc_ck);
2164 +EXPORT_SYMBOL(dwc_cc_chid);
2165 +EXPORT_SYMBOL(dwc_cc_cdid);
2166 +EXPORT_SYMBOL(dwc_cc_name);
2167 +
2168 +#ifndef CONFIG_MACH_IPMATE
2169 +/* Modpow */
2170 +EXPORT_SYMBOL(dwc_modpow);
2171 +/* DH */
2172 +EXPORT_SYMBOL(dwc_dh_modpow);
2173 +EXPORT_SYMBOL(dwc_dh_derive_keys);
2174 +EXPORT_SYMBOL(dwc_dh_pk);
2175 +#endif /* CONFIG_MACH_IPMATE  */
2176 +/* Crypto */
2177 +EXPORT_SYMBOL(dwc_wusb_aes_encrypt);
2178 +EXPORT_SYMBOL(dwc_wusb_cmf);
2179 +EXPORT_SYMBOL(dwc_wusb_prf);
2180 +EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);
2181 +EXPORT_SYMBOL(dwc_wusb_gen_nonce);
2182 +EXPORT_SYMBOL(dwc_wusb_gen_key);
2183 +EXPORT_SYMBOL(dwc_wusb_gen_mic);
2184 +
2185 +
2186 +/* Notification */
2187 +EXPORT_SYMBOL(dwc_alloc_notification_manager);
2188 +EXPORT_SYMBOL(dwc_free_notification_manager);
2189 +EXPORT_SYMBOL(dwc_register_notifier);
2190 +EXPORT_SYMBOL(dwc_unregister_notifier);
2191 +EXPORT_SYMBOL(dwc_add_observer);
2192 +EXPORT_SYMBOL(dwc_remove_observer);
2193 +EXPORT_SYMBOL(dwc_notify);
2194 +
2195 +/* Memory Debugging Routines */
2196 +#ifdef DEBUG_MEMORY
2197 +EXPORT_SYMBOL(dwc_alloc_debug);
2198 +EXPORT_SYMBOL(dwc_alloc_atomic_debug);
2199 +EXPORT_SYMBOL(dwc_free_debug);
2200 +EXPORT_SYMBOL(dwc_dma_alloc_debug);
2201 +EXPORT_SYMBOL(dwc_dma_alloc_atomic_debug);
2202 +EXPORT_SYMBOL(dwc_dma_free_debug);
2203 +#endif
2204 +
2205 +/* OS-Level Implementations */
2206 +
2207 +/* This is the Linux kernel implementation of the DWC platform library. */
2208 +#include <linux/kernel.h>
2209 +#include <linux/init.h>
2210 +#include <linux/module.h>
2211 +#include <linux/moduleparam.h>
2212 +#include <linux/ctype.h>
2213 +#include <linux/crypto.h>
2214 +#include <linux/delay.h>
2215 +#include <linux/device.h>
2216 +#include <linux/dma-mapping.h>
2217 +#include <linux/cdev.h>
2218 +#include <linux/errno.h>
2219 +#include <linux/interrupt.h>
2220 +#include <linux/jiffies.h>
2221 +#include <linux/list.h>
2222 +#include <linux/pci.h>
2223 +#include <linux/slab.h>
2224 +#include <linux/stat.h>
2225 +#include <linux/string.h>
2226 +#include <linux/timer.h>
2227 +#include <linux/version.h>
2228 +#include <linux/usb.h>
2229 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
2230 +#include <linux/usb_gadget.h>
2231 +#else
2232 +#include <linux/usb/gadget.h>
2233 +#endif
2234 +#include <linux/random.h>
2235 +#include <asm/io.h>
2236 +#include <asm/page.h>
2237 +#include <asm/uaccess.h>
2238 +#include <asm/unaligned.h>
2239 +#include <asm/page.h>
2240 +#include <linux/scatterlist.h>
2241 +
2242 +/* MISC */
2243 +
2244 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
2245 +{
2246 +       return memset(dest, byte, size);
2247 +}
2248 +EXPORT_SYMBOL(DWC_MEMSET);
2249 +
2250 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
2251 +{
2252 +       return memcpy(dest, src, size);
2253 +}
2254 +EXPORT_SYMBOL(DWC_MEMCPY);
2255 +
2256 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
2257 +{
2258 +       return memmove(dest, src, size);
2259 +}
2260 +EXPORT_SYMBOL(DWC_MEMMOVE);
2261 +
2262 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
2263 +{
2264 +       return memcmp(m1, m2, size);
2265 +}
2266 +EXPORT_SYMBOL(DWC_MEMCMP);
2267 +
2268 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
2269 +{
2270 +       return strncmp(s1, s2, size);
2271 +}
2272 +EXPORT_SYMBOL(DWC_STRNCMP);
2273 +
2274 +int DWC_STRCMP(void *s1, void *s2)
2275 +{
2276 +       return strcmp(s1, s2);
2277 +}
2278 +EXPORT_SYMBOL(DWC_STRCMP);
2279 +
2280 +int DWC_STRLEN(char const *str)
2281 +{
2282 +       return strlen(str);
2283 +}
2284 +EXPORT_SYMBOL(DWC_STRLEN);
2285 +
2286 +char *DWC_STRCPY(char *to, const char *from)
2287 +{
2288 +       return strcpy(to, from);
2289 +}
2290 +EXPORT_SYMBOL(DWC_STRCPY);
2291 +
2292 +char *DWC_STRDUP(char const *str)
2293 +{
2294 +       int len = DWC_STRLEN(str) + 1;
2295 +       char *new = DWC_ALLOC_ATOMIC(len);
2296 +       if (!new) {
2297 +               return NULL;
2298 +       }
2299 +       DWC_MEMCPY(new, str, len);
2300 +       return new;
2301 +}
2302 +EXPORT_SYMBOL(DWC_STRDUP);
2303 +
2304 +int DWC_ATOI(char *str, int32_t *value)
2305 +{
2306 +       char *end = NULL;
2307 +       *value = simple_strtol(str, &end, 0);
2308 +       if (*end == '\0') {
2309 +               return 0;
2310 +       }
2311 +       return -1;
2312 +}
2313 +EXPORT_SYMBOL(DWC_ATOI);
2314 +
2315 +int DWC_ATOUI(char *str, uint32_t *value)
2316 +{
2317 +       char *end = NULL;
2318 +       *value = simple_strtoul(str, &end, 0);
2319 +       if (*end == '\0') {
2320 +               return 0;
2321 +       }
2322 +       return -1;
2323 +}
2324 +EXPORT_SYMBOL(DWC_ATOUI);
2325 +
2326 +
2327 +/* From usbstring.c */
2328 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
2329 +{
2330 +       int     count = 0;
2331 +       u8      c;
2332 +       u16     uchar;
2333 +
2334 +       /* this insists on correct encodings, though not minimal ones.
2335 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
2336 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
2337 +        */
2338 +       while (len != 0 && (c = (u8) *s++) != 0) {
2339 +               if (unlikely(c & 0x80)) {
2340 +                       // 2-byte sequence:
2341 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
2342 +                       if ((c & 0xe0) == 0xc0) {
2343 +                               uchar = (c & 0x1f) << 6;
2344 +
2345 +                               c = (u8) *s++;
2346 +                               if ((c & 0xc0) != 0xc0)
2347 +                                       goto fail;
2348 +                               c &= 0x3f;
2349 +                               uchar |= c;
2350 +
2351 +                       // 3-byte sequence (most CJKV characters):
2352 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
2353 +                       } else if ((c & 0xf0) == 0xe0) {
2354 +                               uchar = (c & 0x0f) << 12;
2355 +
2356 +                               c = (u8) *s++;
2357 +                               if ((c & 0xc0) != 0xc0)
2358 +                                       goto fail;
2359 +                               c &= 0x3f;
2360 +                               uchar |= c << 6;
2361 +
2362 +                               c = (u8) *s++;
2363 +                               if ((c & 0xc0) != 0xc0)
2364 +                                       goto fail;
2365 +                               c &= 0x3f;
2366 +                               uchar |= c;
2367 +
2368 +                               /* no bogus surrogates */
2369 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
2370 +                                       goto fail;
2371 +
2372 +                       // 4-byte sequence (surrogate pairs, currently rare):
2373 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
2374 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
2375 +                       // (uuuuu = wwww + 1)
2376 +                       // FIXME accept the surrogate code points (only)
2377 +
2378 +                       } else
2379 +                               goto fail;
2380 +               } else
2381 +                       uchar = c;
2382 +               put_unaligned (cpu_to_le16 (uchar), cp++);
2383 +               count++;
2384 +               len--;
2385 +       }
2386 +       return count;
2387 +fail:
2388 +       return -1;
2389 +}
2390 +EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);
2391 +
2392 +/* dwc_debug.h */
2393 +
2394 +dwc_bool_t DWC_IN_IRQ(void)
2395 +{
2396 +       return in_irq();
2397 +}
2398 +EXPORT_SYMBOL(DWC_IN_IRQ);
2399 +
2400 +int DWC_IN_BH(void)
2401 +{
2402 +       return in_softirq();
2403 +}
2404 +EXPORT_SYMBOL(DWC_IN_BH);
2405 +
2406 +void DWC_VPRINTF(char *format, va_list args)
2407 +{
2408 +       vprintk(format, args);
2409 +}
2410 +EXPORT_SYMBOL(DWC_VPRINTF);
2411 +
2412 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
2413 +{
2414 +       return vsnprintf(str, size, format, args);
2415 +}
2416 +
2417 +void DWC_PRINTF(char *format, ...)
2418 +{
2419 +       va_list args;
2420 +       va_start(args, format);
2421 +       DWC_VPRINTF(format, args);
2422 +       va_end(args);
2423 +}
2424 +EXPORT_SYMBOL(DWC_PRINTF);
2425 +
2426 +int DWC_SPRINTF(char *buffer, char *format, ...)
2427 +{
2428 +       int retval;
2429 +       va_list args;
2430 +       va_start(args, format);
2431 +       retval = vsprintf(buffer, format, args);
2432 +       va_end(args);
2433 +       return retval;
2434 +}
2435 +EXPORT_SYMBOL(DWC_SPRINTF);
2436 +
2437 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
2438 +{
2439 +       int retval;
2440 +       va_list args;
2441 +       va_start(args, format);
2442 +       retval = vsnprintf(buffer, size, format, args);
2443 +       va_end(args);
2444 +       return retval;
2445 +}
2446 +EXPORT_SYMBOL(DWC_SNPRINTF);
2447 +
2448 +void __DWC_WARN(char *format, ...)
2449 +{
2450 +       va_list args;
2451 +       va_start(args, format);
2452 +       DWC_PRINTF(KERN_WARNING);
2453 +       DWC_VPRINTF(format, args);
2454 +       va_end(args);
2455 +}
2456 +EXPORT_SYMBOL(__DWC_WARN);
2457 +
2458 +void __DWC_ERROR(char *format, ...)
2459 +{
2460 +       va_list args;
2461 +       va_start(args, format);
2462 +       DWC_PRINTF(KERN_ERR);
2463 +       DWC_VPRINTF(format, args);
2464 +       va_end(args);
2465 +}
2466 +EXPORT_SYMBOL(__DWC_ERROR);
2467 +
2468 +void DWC_EXCEPTION(char *format, ...)
2469 +{
2470 +       va_list args;
2471 +       va_start(args, format);
2472 +       DWC_PRINTF(KERN_ERR);
2473 +       DWC_VPRINTF(format, args);
2474 +       va_end(args);
2475 +       BUG_ON(1);
2476 +}
2477 +EXPORT_SYMBOL(DWC_EXCEPTION);
2478 +
2479 +#ifdef DEBUG
2480 +void __DWC_DEBUG(char *format, ...)
2481 +{
2482 +       va_list args;
2483 +       va_start(args, format);
2484 +       DWC_PRINTF(KERN_DEBUG);
2485 +       DWC_VPRINTF(format, args);
2486 +       va_end(args);
2487 +}
2488 +EXPORT_SYMBOL(__DWC_DEBUG);
2489 +#endif
2490 +
2491 +
2492 +
2493 +/* dwc_mem.h */
2494 +
2495 +#if 0
2496 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
2497 +                               uint32_t align,
2498 +                               uint32_t alloc)
2499 +{
2500 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
2501 +                                               size, align, alloc);
2502 +       return (dwc_pool_t *)pool;
2503 +}
2504 +
2505 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
2506 +{
2507 +       dma_pool_destroy((struct dma_pool *)pool);
2508 +}
2509 +
2510 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, U64 *dma_addr)
2511 +{
2512 +       return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
2513 +}
2514 +
2515 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, U64 *dma_addr)
2516 +{
2517 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
2518 +       memset();
2519 +}
2520 +
2521 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
2522 +{
2523 +       dma_pool_free(pool, vaddr, daddr);
2524 +}
2525 +
2526 +#endif
2527 +
2528 +void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr)
2529 +{
2530 +       void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_KERNEL);
2531 +       if (!buf) {
2532 +               return NULL;
2533 +       }
2534 +       memset(buf, 0, (size_t)size);
2535 +       return buf;
2536 +}
2537 +EXPORT_SYMBOL(__DWC_DMA_ALLOC);
2538 +
2539 +void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
2540 +{
2541 +       dma_free_coherent(NULL, size, virt_addr, dma_addr);
2542 +}
2543 +EXPORT_SYMBOL(__DWC_DMA_FREE);
2544 +
2545 +void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr)
2546 +{
2547 +       void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);
2548 +       if (!buf) {
2549 +               return NULL;
2550 +       }
2551 +       memset(buf, 0, (size_t)size);
2552 +       return buf;
2553 +}
2554 +EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
2555 +
2556 +void *__DWC_ALLOC(uint32_t size)
2557 +{
2558 +       return kzalloc(size, GFP_KERNEL);
2559 +}
2560 +EXPORT_SYMBOL(__DWC_ALLOC);
2561 +
2562 +void *__DWC_ALLOC_ATOMIC(uint32_t size)
2563 +{
2564 +       return kzalloc(size, GFP_ATOMIC);
2565 +}
2566 +EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);
2567 +
2568 +void __DWC_FREE(void *addr)
2569 +{
2570 +       kfree(addr);
2571 +}
2572 +EXPORT_SYMBOL(__DWC_FREE);
2573 +
2574 +/* dwc_crypto.h */
2575 +
2576 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
2577 +{
2578 +       get_random_bytes(buffer, length);
2579 +}
2580 +EXPORT_SYMBOL(DWC_RANDOM_BYTES);
2581 +
2582 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
2583 +{
2584 +       struct crypto_blkcipher *tfm;
2585 +       struct blkcipher_desc desc;
2586 +       struct scatterlist sgd;
2587 +       struct scatterlist sgs;
2588 +
2589 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
2590 +       if (tfm == NULL) {
2591 +               printk("failed to load transform for aes CBC\n");
2592 +               return -1;
2593 +       }
2594 +
2595 +       crypto_blkcipher_setkey(tfm, key, keylen);
2596 +       crypto_blkcipher_set_iv(tfm, iv, 16);
2597 +
2598 +       sg_init_one(&sgd, out, messagelen);
2599 +       sg_init_one(&sgs, message, messagelen);
2600 +
2601 +       desc.tfm = tfm;
2602 +       desc.flags = 0;
2603 +
2604 +       if(crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
2605 +               crypto_free_blkcipher(tfm);
2606 +               DWC_ERROR("AES CBC encryption failed");
2607 +               return -1;
2608 +       }
2609 +
2610 +       crypto_free_blkcipher(tfm);
2611 +       return 0;
2612 +}
2613 +EXPORT_SYMBOL(DWC_AES_CBC);
2614 +
2615 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
2616 +{
2617 +       struct crypto_hash *tfm;
2618 +       struct hash_desc desc;
2619 +       struct scatterlist sg;
2620 +
2621 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
2622 +       if (IS_ERR(tfm)) {
2623 +               DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));
2624 +               return 0;
2625 +       }
2626 +       desc.tfm = tfm;
2627 +       desc.flags = 0;
2628 +
2629 +       sg_init_one(&sg, message, len);
2630 +       crypto_hash_digest(&desc, &sg, len, out);
2631 +       crypto_free_hash(tfm);
2632 +
2633 +       return 1;
2634 +}
2635 +EXPORT_SYMBOL(DWC_SHA256);
2636 +
2637 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
2638 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
2639 +{
2640 +       struct crypto_hash *tfm;
2641 +       struct hash_desc desc;
2642 +       struct scatterlist sg;
2643 +
2644 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
2645 +       if (IS_ERR(tfm)) {
2646 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));
2647 +               return 0;
2648 +       }
2649 +       desc.tfm = tfm;
2650 +       desc.flags = 0;
2651 +
2652 +       sg_init_one(&sg, message, messagelen);
2653 +       crypto_hash_setkey(tfm, key, keylen);
2654 +       crypto_hash_digest(&desc, &sg, messagelen, out);
2655 +       crypto_free_hash(tfm);
2656 +
2657 +       return 1;
2658 +}
2659 +EXPORT_SYMBOL(DWC_HMAC_SHA256);
2660 +
2661 +/* Byte Ordering Conversions. */
2662 +uint32_t DWC_CPU_TO_LE32(void *p)
2663 +{
2664 +#ifdef __LITTLE_ENDIAN
2665 +       return *((uint32_t *)p);
2666 +#else
2667 +       uint8_t *u_p = (uint8_t *)p;
2668 +
2669 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
2670 +#endif
2671 +}
2672 +EXPORT_SYMBOL(DWC_CPU_TO_LE32);
2673 +
2674 +uint32_t DWC_CPU_TO_BE32(void *p)
2675 +{
2676 +#ifdef __BIG_ENDIAN
2677 +       return *((uint32_t *)p);
2678 +#else
2679 +       uint8_t *u_p = (uint8_t *)p;
2680 +
2681 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
2682 +#endif
2683 +}
2684 +EXPORT_SYMBOL(DWC_CPU_TO_BE32);
2685 +
2686 +uint32_t DWC_LE32_TO_CPU(void *p)
2687 +{
2688 +#ifdef __LITTLE_ENDIAN
2689 +       return *((uint32_t *)p);
2690 +#else
2691 +       uint8_t *u_p = (uint8_t *)p;
2692 +
2693 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
2694 +
2695 +#endif
2696 +}
2697 +EXPORT_SYMBOL(DWC_LE32_TO_CPU);
2698 +
2699 +uint32_t DWC_BE32_TO_CPU(void *p)
2700 +{
2701 +#ifdef __BIG_ENDIAN
2702 +       return *((uint32_t *)p);
2703 +#else
2704 +       uint8_t *u_p = (uint8_t *)p;
2705 +
2706 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
2707 +#endif
2708 +}
2709 +EXPORT_SYMBOL(DWC_BE32_TO_CPU);
2710 +
2711 +uint16_t DWC_CPU_TO_LE16(void *p)
2712 +{
2713 +#ifdef __LITTLE_ENDIAN
2714 +       return *((uint16_t *)p);
2715 +#else
2716 +       uint8_t *u_p = (uint8_t *)p;
2717 +       return (u_p[1] | (u_p[0] << 8));
2718 +#endif
2719 +}
2720 +EXPORT_SYMBOL(DWC_CPU_TO_LE16);
2721 +
2722 +uint16_t DWC_CPU_TO_BE16(void *p)
2723 +{
2724 +#ifdef __BIG_ENDIAN
2725 +       return *((uint16_t *)p);
2726 +#else
2727 +       uint8_t *u_p = (uint8_t *)p;
2728 +       return (u_p[1] | (u_p[0] << 8));
2729 +#endif
2730 +}
2731 +EXPORT_SYMBOL(DWC_CPU_TO_BE16);
2732 +
2733 +uint16_t DWC_LE16_TO_CPU(void *p)
2734 +{
2735 +#ifdef __LITTLE_ENDIAN
2736 +       return *((uint16_t *)p);
2737 +#else
2738 +       uint8_t *u_p = (uint8_t *)p;
2739 +       return (u_p[1] | (u_p[0] << 8));
2740 +#endif
2741 +}
2742 +EXPORT_SYMBOL(DWC_LE16_TO_CPU);
2743 +
2744 +uint16_t DWC_BE16_TO_CPU(void *p)
2745 +{
2746 +#ifdef __BIG_ENDIAN
2747 +       return *((uint16_t *p)p);
2748 +#else
2749 +       uint8_t *u_p = (uint8_t *)p;
2750 +       return (u_p[1] | (u_p[0] << 8));
2751 +#endif
2752 +}
2753 +EXPORT_SYMBOL(DWC_BE16_TO_CPU);
2754 +
2755 +
2756 +/* Registers */
2757 +
2758 +uint32_t DWC_READ_REG32(uint32_t volatile *reg)
2759 +{
2760 +       return readl(reg);
2761 +}
2762 +EXPORT_SYMBOL(DWC_READ_REG32);
2763 +
2764 +#if 0
2765 +uint64_t DWC_READ_REG64(uint64_t volatile *reg)
2766 +{
2767 +}
2768 +#endif
2769 +
2770 +void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)
2771 +{
2772 +       writel(value, reg);
2773 +}
2774 +EXPORT_SYMBOL(DWC_WRITE_REG32);
2775 +
2776 +#if 0
2777 +void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
2778 +{
2779 +}
2780 +#endif
2781 +
2782 +void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
2783 +{
2784 +       writel( (readl(reg) & ~clear_mask) | set_mask, reg );
2785 +}
2786 +EXPORT_SYMBOL(DWC_MODIFY_REG32);
2787 +
2788 +#if 0
2789 +void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t value)
2790 +{
2791 +}
2792 +#endif
2793 +
2794 +
2795 +
2796 +/* Threading */
2797 +
2798 +typedef struct work_container
2799 +{
2800 +       dwc_work_callback_t cb;
2801 +       void *data;
2802 +       dwc_workq_t *wq;
2803 +       char *name;
2804 +
2805 +#ifdef DEBUG
2806 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
2807 +#endif
2808 +
2809 +       struct delayed_work work;
2810 +} work_container_t;
2811 +
2812 +#ifdef DEBUG
2813 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
2814 +#endif
2815 +
2816 +struct dwc_workq
2817 +{
2818 +       struct workqueue_struct *wq;
2819 +       int pending;
2820 +       dwc_spinlock_t *lock;
2821 +       dwc_waitq_t *waitq;
2822 +
2823 +#ifdef DEBUG
2824 +       struct work_container_queue entries;
2825 +#endif
2826 +};
2827 +
2828 +static void do_work(struct work_struct *work)
2829 +{
2830 +       int64_t flags;
2831 +       struct delayed_work *dw = container_of(work, struct delayed_work, work);
2832 +       work_container_t *container = container_of(dw, struct work_container, work);
2833 +       dwc_workq_t *wq = container->wq;
2834 +
2835 +       container->cb(container->data);
2836 +
2837 +#ifdef DEBUG
2838 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
2839 +#endif
2840 +
2841 +       if (container->name) {
2842 +               DWC_DEBUG("Work done: %s, container=%p",
2843 +                          container->name, container); //GRAYG
2844 +               DWC_FREE(container->name);
2845 +       }
2846 +       DWC_FREE(container);
2847 +
2848 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
2849 +       wq->pending --;
2850 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
2851 +       DWC_WAITQ_TRIGGER(wq->waitq);
2852 +}
2853 +
2854 +static int work_done(void *data)
2855 +{
2856 +       dwc_workq_t *workq = (dwc_workq_t *)data;
2857 +       return workq->pending == 0;
2858 +}
2859 +
2860 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
2861 +{
2862 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
2863 +}
2864 +EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);
2865 +
2866 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
2867 +{
2868 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
2869 +       wq->wq = create_singlethread_workqueue(name);
2870 +       wq->pending = 0;
2871 +       wq->lock = DWC_SPINLOCK_ALLOC();
2872 +       wq->waitq = DWC_WAITQ_ALLOC();
2873 +#ifdef DEBUG
2874 +       DWC_CIRCLEQ_INIT(&wq->entries);
2875 +#endif
2876 +       return wq;
2877 +}
2878 +EXPORT_SYMBOL(DWC_WORKQ_ALLOC);
2879 +
2880 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
2881 +{
2882 +#ifdef DEBUG
2883 +       if (wq->pending != 0) {
2884 +               struct work_container *wc;
2885 +               DWC_ERROR("Destroying work queue with pending work");
2886 +               DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {
2887 +                       DWC_ERROR("Work %s still pending", wc->name);
2888 +               }
2889 +       }
2890 +#endif
2891 +       destroy_workqueue((struct workqueue_struct *)wq->wq);
2892 +       DWC_SPINLOCK_FREE(wq->lock);
2893 +       DWC_WAITQ_FREE(wq->waitq);
2894 +       DWC_FREE(wq);
2895 +}
2896 +EXPORT_SYMBOL(DWC_WORKQ_FREE);
2897 +
2898 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, char *format, ...)
2899 +{
2900 +       int64_t flags;
2901 +       work_container_t *container;
2902 +       static char name[128];
2903 +
2904 +       va_list args;
2905 +       va_start(args, format);
2906 +        if (format)
2907 +               DWC_VSNPRINTF(name, 128, format, args);
2908 +       va_end(args);
2909 +
2910 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
2911 +       wq->pending ++;
2912 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
2913 +       DWC_WAITQ_TRIGGER(wq->waitq);
2914 +
2915 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
2916 +
2917 +       container->data = data;
2918 +       container->cb = work_cb;
2919 +       container->wq = wq;
2920 +        if (format) {
2921 +                container->name = DWC_STRDUP(name);
2922 +                DWC_DEBUG("Queueing work: %s, contianer=%p",
2923 +                          container->name, container);
2924 +        } else
2925 +                container->name = NULL;
2926 +        
2927 +       INIT_WORK(&container->work.work, do_work);
2928 +
2929 +#ifdef DEBUG
2930 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
2931 +#endif
2932 +
2933 +       queue_work(wq->wq, &container->work.work);
2934 +
2935 +}
2936 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);
2937 +
2938 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...)
2939 +{
2940 +       int64_t flags;
2941 +       work_container_t *container;
2942 +       static char name[128];
2943 +
2944 +       va_list args;
2945 +       va_start(args, format);
2946 +        if (format)
2947 +               DWC_VSNPRINTF(name, 128, format, args);
2948 +       va_end(args);
2949 +
2950 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
2951 +       wq->pending ++;
2952 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
2953 +       DWC_WAITQ_TRIGGER(wq->waitq);
2954 +
2955 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
2956 +
2957 +       container->data = data;
2958 +       container->cb = work_cb;
2959 +       container->wq = wq;
2960 +        if (format) { //GRAYG
2961 +               container->name = DWC_STRDUP(name);
2962 +                DWC_DEBUG("Queueing work: %s, contianer=%p",
2963 +                          container->name, container);
2964 +        } else
2965 +           container->name = NULL;
2966 +       INIT_DELAYED_WORK(&container->work, do_work);
2967 +
2968 +#ifdef DEBUG
2969 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
2970 +#endif
2971 +
2972 +       queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));
2973 +
2974 +}
2975 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);
2976 +
2977 +
2978 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
2979 +{
2980 +       return wq->pending;
2981 +}
2982 +EXPORT_SYMBOL(DWC_WORKQ_PENDING);
2983 +
2984 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
2985 +{
2986 +       spinlock_t *sl = (spinlock_t *)1;
2987 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
2988 +       sl = DWC_ALLOC(sizeof(*sl));
2989 +       spin_lock_init(sl);
2990 +#endif
2991 +       return (dwc_spinlock_t *)sl;
2992 +}
2993 +EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);
2994 +
2995 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
2996 +{
2997 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
2998 +       DWC_FREE(lock);
2999 +#endif
3000 +}
3001 +EXPORT_SYMBOL(DWC_SPINLOCK_FREE);
3002 +
3003 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
3004 +{
3005 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
3006 +       spin_lock((spinlock_t *)lock);
3007 +#endif
3008 +}
3009 +EXPORT_SYMBOL(DWC_SPINLOCK);
3010 +
3011 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
3012 +{
3013 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
3014 +       spin_unlock((spinlock_t *)lock);
3015 +#endif
3016 +}
3017 +EXPORT_SYMBOL(DWC_SPINUNLOCK);
3018 +
3019 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags)
3020 +{
3021 +       unsigned long f;
3022 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
3023 +        spin_lock_irqsave((spinlock_t *)lock, f);
3024 +#else
3025 +       local_irq_save(f);
3026 +#endif
3027 +        *flags = f;
3028 +}
3029 +EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);
3030 +
3031 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags)
3032 +{
3033 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
3034 +        spin_unlock_irqrestore((spinlock_t *)lock, flags);
3035 +#else
3036 +        // in kernel 2.6.31, at least, we check for unsigned long
3037 +        local_irq_restore((unsigned long)flags);
3038 +#endif
3039 +}
3040 +EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);
3041 +
3042 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
3043 +{
3044 +       dwc_mutex_t *mutex = (dwc_mutex_t*)DWC_ALLOC(sizeof(struct mutex));
3045 +       struct mutex *m = (struct mutex *)mutex;
3046 +       mutex_init(m);
3047 +       return mutex;
3048 +}
3049 +EXPORT_SYMBOL(DWC_MUTEX_ALLOC);
3050 +
3051 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
3052 +#else
3053 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
3054 +{
3055 +       mutex_destroy((struct mutex *)mutex);
3056 +       DWC_FREE(mutex);
3057 +}
3058 +EXPORT_SYMBOL(DWC_MUTEX_FREE);
3059 +#endif
3060 +
3061 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
3062 +{
3063 +       struct mutex *m = (struct mutex *)mutex;
3064 +       mutex_lock(m);
3065 +}
3066 +EXPORT_SYMBOL(DWC_MUTEX_LOCK);
3067 +
3068 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
3069 +{
3070 +       struct mutex *m = (struct mutex *)mutex;
3071 +       return mutex_trylock(m);
3072 +}
3073 +EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);
3074 +
3075 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
3076 +{
3077 +       struct mutex *m = (struct mutex *)mutex;
3078 +       mutex_unlock(m);
3079 +}
3080 +EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);
3081 +
3082 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data)
3083 +{
3084 +       struct task_struct *thread = kthread_run(thread_function, data, name);
3085 +       if (thread == ERR_PTR(-ENOMEM)) {
3086 +               return NULL;
3087 +       }
3088 +       return (dwc_thread_t *)thread;
3089 +}
3090 +EXPORT_SYMBOL(DWC_THREAD_RUN);
3091 +
3092 +int DWC_THREAD_STOP(dwc_thread_t *thread)
3093 +{
3094 +       return kthread_stop((struct task_struct *)thread);
3095 +}
3096 +EXPORT_SYMBOL(DWC_THREAD_STOP);
3097 +
3098 +dwc_bool_t DWC_THREAD_SHOULD_STOP()
3099 +{
3100 +       return kthread_should_stop();
3101 +}
3102 +EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);
3103 +
3104 +/* Timers */
3105 +
3106 +struct dwc_timer
3107 +{
3108 +       struct timer_list *t;
3109 +       char *name;
3110 +       dwc_timer_callback_t cb;
3111 +       void *data;
3112 +       uint8_t scheduled;
3113 +       dwc_spinlock_t *lock;
3114 +};
3115 +
3116 +static void set_scheduled(dwc_timer_t *t, int s)
3117 +{
3118 +       uint64_t flags;
3119 +       DWC_SPINLOCK_IRQSAVE(t->lock, &flags);
3120 +       t->scheduled = s;
3121 +       DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags);
3122 +}
3123 +
3124 +static int get_scheduled(dwc_timer_t *t)
3125 +{
3126 +       int s;
3127 +       uint64_t flags;
3128 +       DWC_SPINLOCK_IRQSAVE(t->lock, &flags);
3129 +       s = t->scheduled;
3130 +       DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags);
3131 +       return s;
3132 +}
3133 +
3134 +static void timer_callback(unsigned long data)
3135 +{
3136 +       dwc_timer_t *timer = (dwc_timer_t *)data;
3137 +       set_scheduled(timer, 0);
3138 +       DWC_DEBUG("Timer %s callback", timer->name);
3139 +       timer->cb(timer->data);
3140 +}
3141 +
3142 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
3143 +{
3144 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
3145 +       if (!t) {
3146 +               DWC_ERROR("Cannot allocate memory for timer");
3147 +               return NULL;
3148 +       }
3149 +       t->t = DWC_ALLOC(sizeof(*t->t));
3150 +       if (!t->t) {
3151 +               DWC_ERROR("Cannot allocate memory for timer->t");
3152 +               goto no_timer;
3153 +       }
3154 +
3155 +       t->name = DWC_STRDUP(name);
3156 +       if (!t->name) {
3157 +               DWC_ERROR("Cannot allocate memory for timer->name");
3158 +               goto no_name;
3159 +       }
3160 +
3161 +       t->lock = DWC_SPINLOCK_ALLOC();
3162 +       if (!t->lock) {
3163 +               DWC_ERROR("Cannot allocate memory for lock");
3164 +               goto no_lock;
3165 +       }
3166 +       t->scheduled = 0;
3167 +       t->t->base = &boot_tvec_bases;
3168 +       t->t->expires = jiffies;
3169 +       setup_timer(t->t, timer_callback, (unsigned long)t);
3170 +
3171 +       t->cb = cb;
3172 +       t->data = data;
3173 +
3174 +       return t;
3175 +
3176 + no_lock:
3177 +       DWC_FREE(t->name);
3178 + no_name:
3179 +       DWC_FREE(t->t);
3180 + no_timer:
3181 +       DWC_FREE(t);
3182 +       return NULL;
3183 +}
3184 +EXPORT_SYMBOL(DWC_TIMER_ALLOC);
3185 +
3186 +void DWC_TIMER_FREE(dwc_timer_t *timer)
3187 +{
3188 +       if (get_scheduled(timer)) {
3189 +               del_timer(timer->t);
3190 +       }
3191 +
3192 +       DWC_SPINLOCK_FREE(timer->lock);
3193 +       DWC_FREE(timer->t);
3194 +       DWC_FREE(timer->name);
3195 +       DWC_FREE(timer);
3196 +}
3197 +EXPORT_SYMBOL(DWC_TIMER_FREE);
3198 +
3199 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
3200 +{
3201 +       if (!get_scheduled(timer)) {
3202 +               set_scheduled(timer, 1);
3203 +               //cgg: DWC_DEBUG("Scheduling timer %s to expire in +%d msec", timer->name, time);
3204 +               timer->t->expires = jiffies + msecs_to_jiffies(time);
3205 +               add_timer(timer->t);
3206 +       }
3207 +       else {
3208 +                //cgg: DWC_DEBUG("Modifying timer %s to expire in +%d msec", timer->name, time);
3209 +               mod_timer(timer->t, jiffies + msecs_to_jiffies(time));
3210 +       }
3211 +}
3212 +EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);
3213 +
3214 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
3215 +{
3216 +       del_timer(timer->t);
3217 +}
3218 +EXPORT_SYMBOL(DWC_TIMER_CANCEL);
3219 +
3220 +struct dwc_tasklet
3221 +{
3222 +       struct tasklet_struct t;
3223 +       dwc_tasklet_callback_t cb; 
3224 +       void *data;
3225 +};
3226 +
3227 +static void tasklet_callback(unsigned long data)
3228 +{
3229 +       dwc_tasklet_t *t = (dwc_tasklet_t *)data;
3230 +       t->cb(t->data);
3231 +}
3232 +
3233 +dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data)
3234 +{
3235 +       dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));
3236 +       
3237 +       if(t) {
3238 +               t->data = data;
3239 +               t->cb = cb;
3240 +               tasklet_init(&t->t, tasklet_callback, (unsigned long)t);
3241 +       } else {
3242 +               DWC_ERROR("Cannot allocate memory for tasklet\n");
3243 +       }
3244 +       
3245 +       return t;
3246 +}
3247 +EXPORT_SYMBOL(DWC_TASK_ALLOC);
3248 +
3249 +void DWC_TASK_FREE(dwc_tasklet_t *t)
3250 +{
3251 +       DWC_FREE(t);
3252 +}
3253 +EXPORT_SYMBOL(DWC_TASK_FREE);
3254 +
3255 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
3256 +{
3257 +       tasklet_schedule(&task->t);
3258 +}
3259 +EXPORT_SYMBOL(DWC_TASK_SCHEDULE);
3260 +
3261 +/* Timing */
3262 +
3263 +void DWC_UDELAY(uint32_t usecs)
3264 +{
3265 +       udelay(usecs);
3266 +}
3267 +EXPORT_SYMBOL(DWC_UDELAY);
3268 +
3269 +void DWC_MDELAY(uint32_t msecs)
3270 +{
3271 +       mdelay(msecs);
3272 +}
3273 +EXPORT_SYMBOL(DWC_MDELAY);
3274 +
3275 +void DWC_MSLEEP(uint32_t msecs)
3276 +{
3277 +       msleep(msecs);
3278 +}
3279 +EXPORT_SYMBOL(DWC_MSLEEP);
3280 +
3281 +uint32_t DWC_TIME(void)
3282 +{
3283 +       return jiffies_to_msecs(jiffies);
3284 +}
3285 +EXPORT_SYMBOL(DWC_TIME);
3286 +
3287 +
3288 +/* Wait Queues */
3289 +
3290 +struct dwc_waitq
3291 +{
3292 +       wait_queue_head_t queue;
3293 +       int abort;
3294 +};
3295 +
3296 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
3297 +{
3298 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
3299 +       init_waitqueue_head(&wq->queue);
3300 +       wq->abort = 0;
3301 +       return wq;
3302 +}
3303 +EXPORT_SYMBOL(DWC_WAITQ_ALLOC);
3304 +
3305 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
3306 +{
3307 +       DWC_FREE(wq);
3308 +}
3309 +EXPORT_SYMBOL(DWC_WAITQ_FREE);
3310 +
3311 +static int32_t check_result(dwc_waitq_t *wq, int result)
3312 +{      int32_t msecs;
3313 +       if (result > 0) {
3314 +               msecs = jiffies_to_msecs(result);
3315 +               if (!msecs) {
3316 +                       return 1;
3317 +               }
3318 +               return msecs;
3319 +       }
3320 +
3321 +       if (result == 0) {
3322 +               return -DWC_E_TIMEOUT;
3323 +       }
3324 +
3325 +       if ((result == -ERESTARTSYS) || (wq->abort == 1)) {
3326 +               return -DWC_E_ABORT;
3327 +       }
3328 +
3329 +       return -DWC_E_UNKNOWN;
3330 +}
3331 +
3332 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data)
3333 +{
3334 +       int result = wait_event_interruptible(wq->queue,
3335 +                                                 condition(data) || wq->abort);
3336 +       return check_result(wq, result);
3337 +}
3338 +EXPORT_SYMBOL(DWC_WAITQ_WAIT);
3339 +
3340 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition,
3341 +                              void *data, int32_t msecs)
3342 +{
3343 +       int result = wait_event_interruptible_timeout(wq->queue,
3344 +                                                         condition(data) || wq->abort,
3345 +                                                         msecs_to_jiffies(msecs));
3346 +       return check_result(wq, result);
3347 +}
3348 +EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);
3349 +
3350 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
3351 +{
3352 +       wake_up_interruptible(&wq->queue);
3353 +}
3354 +EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);
3355 +
3356 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
3357 +{
3358 +       wq->abort = 1;
3359 +       DWC_WAITQ_TRIGGER(wq);
3360 +}
3361 +EXPORT_SYMBOL(DWC_WAITQ_ABORT);
3362 --- /dev/null
3363 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c
3364 @@ -0,0 +1,306 @@
3365 +/* =========================================================================
3366 + * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_crypto.c $
3367 + * $Revision: #1 $
3368 + * $Date: 2008/12/21 $
3369 + * $Change: 1156609 $
3370 + *
3371 + * Synopsys Portability Library Software and documentation
3372 + * (hereinafter, "Software") is an Unsupported proprietary work of
3373 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
3374 + * between Synopsys and you.
3375 + *
3376 + * The Software IS NOT an item of Licensed Software or Licensed Product
3377 + * under any End User Software License Agreement or Agreement for
3378 + * Licensed Product with Synopsys or any supplement thereto. You are
3379 + * permitted to use and redistribute this Software in source and binary
3380 + * forms, with or without modification, provided that redistributions
3381 + * of source code must retain this notice. You may not view, use,
3382 + * disclose, copy or distribute this file or any information contained
3383 + * herein except pursuant to this license grant from Synopsys. If you
3384 + * do not agree with this notice, including the disclaimer below, then
3385 + * you are not authorized to use the Software.
3386 + *
3387 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
3388 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3389 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
3390 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
3391 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3392 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3393 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3394 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
3395 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3396 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
3397 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
3398 + * DAMAGE.
3399 + * ========================================================================= */
3400 +
3401 +/** @file
3402 + * This file contains the WUSB cryptographic routines.
3403 + */
3404 +
3405 +#include "dwc_crypto.h"
3406 +#include "usb.h"
3407 +
3408 +#ifdef DEBUG
3409 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
3410 +{
3411 +       int i;
3412 +       DWC_PRINTF("%s: ", name);
3413 +       for (i=0; i<len; i++) {
3414 +               DWC_PRINTF("%02x ", bytes[i]);
3415 +       }
3416 +       DWC_PRINTF("\n");
3417 +}
3418 +#else
3419 +#define dump_bytes(x...)
3420 +#endif
3421 +
3422 +/* Display a block */
3423 +void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
3424 +{
3425 +#ifdef DEBUG_CRYPTO
3426 +       int i, blksize = 16;
3427 +
3428 +       DWC_DEBUG("%s", prefix);
3429 +
3430 +       if (suffix == NULL) {
3431 +               suffix = "\n";
3432 +               blksize = a;
3433 +       }
3434 +
3435 +       for (i = 0; i < blksize; i++)
3436 +               DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? "  " : " ");
3437 +       DWC_PRINT(suffix);
3438 +
3439 +#endif
3440 +}
3441 +
3442 +/**
3443 + * Encrypts an array of bytes using the AES encryption engine.
3444 + * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
3445 + * in-place.
3446 + *
3447 + * @return  0 on success, negative error code on error.
3448 + */
3449 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
3450 +{
3451 +       u8 block_t[16];
3452 +       DWC_MEMSET(block_t, 0, 16);
3453 +
3454 +       return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
3455 +}
3456 +
3457 +/**
3458 + * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
3459 + * This function takes a data string and returns the encrypted CBC
3460 + * Counter-mode MIC.
3461 + *
3462 + * @param key     The 128-bit symmetric key.
3463 + * @param nonce   The CCM nonce.
3464 + * @param label   The unique 14-byte ASCII text label.
3465 + * @param bytes   The byte array to be encrypted.
3466 + * @param len     Length of the byte array.
3467 + * @param result  Byte array to receive the 8-byte encrypted MIC.
3468 + */
3469 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
3470 +                 char *label, u8 *bytes, int len, u8 *result)
3471 +{
3472 +       u8 block_m[16];
3473 +       u8 block_x[16];
3474 +       u8 block_t[8];
3475 +       int idx, blkNum;
3476 +       u16 la = (u16)(len + 14);
3477 +
3478 +       /* Set the AES-128 key */
3479 +       //dwc_aes_setkey(tfm, key, 16);
3480 +
3481 +       /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
3482 +       block_m[0] = 0x59;
3483 +       for (idx = 0; idx < 13; idx++)
3484 +               block_m[idx + 1] = nonce[idx];
3485 +       block_m[14] = 0;
3486 +       block_m[15] = 0;
3487 +
3488 +       /* Produce the CBC IV */
3489 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
3490 +       show_block(block_m, "CBC IV in: ", "\n", 0);
3491 +       show_block(block_x, "CBC IV out:", "\n", 0);
3492 +
3493 +       /* Fill block B1 from l(a) = Blen + 14, and A */
3494 +       block_x[0] ^= (u8)(la >> 8);
3495 +       block_x[1] ^= (u8)la;
3496 +       for (idx = 0; idx < 14; idx++)
3497 +               block_x[idx + 2] ^= label[idx];
3498 +       show_block(block_x, "After xor: ", "b1\n", 16);
3499 +
3500 +       dwc_wusb_aes_encrypt(block_x, key, block_x);
3501 +       show_block(block_x, "After AES: ", "b1\n", 16);
3502 +
3503 +       idx = 0;
3504 +       blkNum = 0;
3505 +
3506 +       /* Fill remaining blocks with B */
3507 +       while (len-- > 0) {
3508 +               block_x[idx] ^= *bytes++;
3509 +               if (++idx >= 16) {
3510 +                       idx = 0;
3511 +                       show_block(block_x, "After xor: ", "\n", blkNum);
3512 +                       dwc_wusb_aes_encrypt(block_x, key, block_x);
3513 +                       show_block(block_x, "After AES: ", "\n", blkNum);
3514 +                       blkNum++;
3515 +               }
3516 +       }
3517 +
3518 +       /* Handle partial last block */
3519 +       if (idx > 0) {
3520 +               show_block(block_x, "After xor: ", "\n", blkNum);
3521 +               dwc_wusb_aes_encrypt(block_x, key, block_x);
3522 +               show_block(block_x, "After AES: ", "\n", blkNum);
3523 +       }
3524 +
3525 +       /* Save the MIC tag */
3526 +       DWC_MEMCPY(block_t, block_x, 8);
3527 +       show_block(block_t, "MIC tag  : ", NULL, 8);
3528 +
3529 +       /* Fill block A0 from flags = 0x01, N, and counter = 0 */
3530 +       block_m[0] = 0x01;
3531 +       block_m[14] = 0;
3532 +       block_m[15] = 0;
3533 +
3534 +       /* Encrypt the counter */
3535 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
3536 +       show_block(block_x, "CTR[MIC] : ", NULL, 8);
3537 +
3538 +       /* XOR with MIC tag */
3539 +       for (idx = 0; idx < 8; idx++) {
3540 +               block_t[idx] ^= block_x[idx];
3541 +       }
3542 +
3543 +       /* Return result to caller */
3544 +       DWC_MEMCPY(result, block_t, 8);
3545 +       show_block(result, "CCM-MIC  : ", NULL, 8);
3546 +
3547 +}
3548 +
3549 +/**
3550 + * The PRF function described in section 6.5 of the WUSB spec. This function
3551 + * concatenates MIC values returned from dwc_cmf() to create a value of
3552 + * the requested length.
3553 + *
3554 + * @param prf_len  Length of the PRF function in bits (64, 128, or 256).
3555 + * @param key, nonce, label, bytes, len  Same as for dwc_cmf().
3556 + * @param result   Byte array to receive the result.
3557 + */
3558 +void dwc_wusb_prf(int prf_len, u8 *key,
3559 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
3560 +{
3561 +       int i;
3562 +
3563 +       nonce[0] = 0;
3564 +       for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
3565 +               dwc_wusb_cmf(key, nonce, label, bytes, len, result);
3566 +               result += 8;
3567 +       }
3568 +}
3569 +
3570 +/**
3571 + * Fills in CCM Nonce per the WUSB spec.
3572 + *
3573 + * @param[in] haddr Host address.
3574 + * @param[in] daddr Device address.
3575 + * @param[in] tkid Session Key(PTK) identifier.
3576 + * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
3577 + */
3578 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
3579 +                            uint8_t *nonce)
3580 +{
3581 +
3582 +       DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
3583 +
3584 +       DWC_MEMSET(&nonce[0], 0, 16);
3585 +
3586 +       DWC_MEMCPY(&nonce[6], tkid, 3);
3587 +       nonce[9] = daddr & 0xFF;
3588 +       nonce[10] = (daddr >> 8) & 0xFF;
3589 +       nonce[11] = haddr & 0xFF;
3590 +       nonce[12] = (haddr >> 8) & 0xFF;
3591 +
3592 +       dump_bytes("CCM nonce", nonce, 16);
3593 +}
3594 +
3595 +/**
3596 + * Generates a 16-byte cryptographic-grade random number for the Host/Device
3597 + * Nonce.
3598 + */
3599 +void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
3600 +{
3601 +       uint8_t inonce[16];
3602 +       uint32_t temp[4];
3603 +
3604 +       /* Fill in the Nonce */
3605 +       DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
3606 +       inonce[9] = addr & 0xFF;
3607 +       inonce[10] = (addr >> 8) & 0xFF;
3608 +       inonce[11] = inonce[9];
3609 +       inonce[12] = inonce[10];
3610 +
3611 +       /* Collect "randomness samples" */
3612 +       DWC_RANDOM_BYTES((uint8_t *)temp, 16);
3613 +
3614 +       dwc_wusb_prf_128((uint8_t *)temp, nonce,
3615 +                        "Random Numbers", (uint8_t *)temp, sizeof(temp),
3616 +                        nonce);
3617 +}
3618 +
3619 +/**
3620 + * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
3621 + * WUSB spec.
3622 + *
3623 + * @param[in] ccm_nonce Pointer to CCM Nonce.
3624 + * @param[in] mk Master Key to derive the session from
3625 + * @param[in] hnonce Pointer to Host Nonce.
3626 + * @param[in] dnonce Pointer to Device Nonce.
3627 + * @param[out] kck Pointer to where the KCK output is to be written.
3628 + * @param[out] ptk Pointer to where the PTK output is to be written.
3629 + */
3630 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
3631 +                     uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
3632 +{
3633 +       uint8_t idata[32];
3634 +       uint8_t odata[32];
3635 +
3636 +       dump_bytes("ck", mk, 16);
3637 +       dump_bytes("hnonce", hnonce, 16);
3638 +       dump_bytes("dnonce", dnonce, 16);
3639 +
3640 +       /* The data is the HNonce and DNonce concatenated */
3641 +       DWC_MEMCPY(&idata[0], hnonce, 16);
3642 +       DWC_MEMCPY(&idata[16], dnonce, 16);
3643 +
3644 +       dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
3645 +
3646 +       /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
3647 +       DWC_MEMCPY(kck, &odata[0], 16);
3648 +       DWC_MEMCPY(ptk, &odata[16], 16);
3649 +
3650 +       dump_bytes("kck", kck, 16);
3651 +       dump_bytes("ptk", ptk, 16);
3652 +}
3653 +
3654 +/**
3655 + * Generates the Message Integrity Code over the Handshake data per the
3656 + * WUSB spec.
3657 + *
3658 + * @param ccm_nonce Pointer to CCM Nonce.
3659 + * @param kck   Pointer to Key Confirmation Key.
3660 + * @param data  Pointer to Handshake data to be checked.
3661 + * @param mic   Pointer to where the MIC output is to be written.
3662 + */
3663 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
3664 +                     uint8_t *data, uint8_t *mic)
3665 +{
3666 +
3667 +       dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
3668 +                       data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
3669 +}
3670 +
3671 --- /dev/null
3672 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h
3673 @@ -0,0 +1,103 @@
3674 +/* =========================================================================
3675 + * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_crypto.h $
3676 + * $Revision: #1 $
3677 + * $Date: 2008/12/21 $
3678 + * $Change: 1156609 $
3679 + *
3680 + * Synopsys Portability Library Software and documentation
3681 + * (hereinafter, "Software") is an Unsupported proprietary work of
3682 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
3683 + * between Synopsys and you.
3684 + *
3685 + * The Software IS NOT an item of Licensed Software or Licensed Product
3686 + * under any End User Software License Agreement or Agreement for
3687 + * Licensed Product with Synopsys or any supplement thereto. You are
3688 + * permitted to use and redistribute this Software in source and binary
3689 + * forms, with or without modification, provided that redistributions
3690 + * of source code must retain this notice. You may not view, use,
3691 + * disclose, copy or distribute this file or any information contained
3692 + * herein except pursuant to this license grant from Synopsys. If you
3693 + * do not agree with this notice, including the disclaimer below, then
3694 + * you are not authorized to use the Software.
3695 + *
3696 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
3697 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3698 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
3699 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
3700 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3701 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3702 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3703 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
3704 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3705 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
3706 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
3707 + * DAMAGE.
3708 + * ========================================================================= */
3709 +
3710 +#ifndef _DWC_CRYPTO_H_
3711 +#define _DWC_CRYPTO_H_
3712 +
3713 +/** @file
3714 + *
3715 + * This file contains declarations for the WUSB Cryptographic routines as
3716 + * defined in the WUSB spec.  They are only to be used internally by the DWC UWB
3717 + * modules.
3718 + */
3719 +
3720 +#include "dwc_os.h"
3721 +
3722 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);
3723 +
3724 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
3725 +                 char *label, u8 *bytes, int len, u8 *result);
3726 +void dwc_wusb_prf(int prf_len, u8 *key,
3727 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result);
3728 +
3729 +/**
3730 + * The PRF-64 function described in section 6.5 of the WUSB spec.
3731 + *
3732 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
3733 + */
3734 +static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,
3735 +                                  char *label, u8 *bytes, int len, u8 *result)
3736 +{
3737 +       dwc_wusb_prf(64, key, nonce, label, bytes, len, result);
3738 +}
3739 +
3740 +/**
3741 + * The PRF-128 function described in section 6.5 of the WUSB spec.
3742 + *
3743 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
3744 + */
3745 +static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,
3746 +                                   char *label, u8 *bytes, int len, u8 *result)
3747 +{
3748 +       dwc_wusb_prf(128, key, nonce, label, bytes, len, result);
3749 +}
3750 +
3751 +/**
3752 + * The PRF-256 function described in section 6.5 of the WUSB spec.
3753 + *
3754 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
3755 + */
3756 +static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,
3757 +                                   char *label, u8 *bytes, int len, u8 *result)
3758 +{
3759 +       dwc_wusb_prf(256, key, nonce, label, bytes, len, result);
3760 +}
3761 +
3762 +
3763 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
3764 +                              uint8_t *nonce);
3765 +void dwc_wusb_gen_nonce(uint16_t addr,
3766 +                         uint8_t *nonce);
3767 +
3768 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,
3769 +                       uint8_t *hnonce, uint8_t *dnonce,
3770 +                       uint8_t *kck, uint8_t *ptk);
3771 +
3772 +
3773 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t
3774 +                       *kck, uint8_t *data, uint8_t *mic);
3775 +
3776 +#endif /* _DWC_CRYPTO_H_ */
3777 --- /dev/null
3778 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.c
3779 @@ -0,0 +1,286 @@
3780 +/* =========================================================================
3781 + * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_dh.c $
3782 + * $Revision: #1 $
3783 + * $Date: 2008/12/21 $
3784 + * $Change: 1156609 $
3785 + *
3786 + * Synopsys Portability Library Software and documentation
3787 + * (hereinafter, "Software") is an Unsupported proprietary work of
3788 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
3789 + * between Synopsys and you.
3790 + *
3791 + * The Software IS NOT an item of Licensed Software or Licensed Product
3792 + * under any End User Software License Agreement or Agreement for
3793 + * Licensed Product with Synopsys or any supplement thereto. You are
3794 + * permitted to use and redistribute this Software in source and binary
3795 + * forms, with or without modification, provided that redistributions
3796 + * of source code must retain this notice. You may not view, use,
3797 + * disclose, copy or distribute this file or any information contained
3798 + * herein except pursuant to this license grant from Synopsys. If you
3799 + * do not agree with this notice, including the disclaimer below, then
3800 + * you are not authorized to use the Software.
3801 + *
3802 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
3803 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3804 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
3805 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
3806 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3807 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3808 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3809 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
3810 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3811 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
3812 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
3813 + * DAMAGE.
3814 + * ========================================================================= */
3815 +#ifndef CONFIG_MACH_IPMATE
3816 +#include "dwc_dh.h"
3817 +#include "dwc_modpow.h"
3818 +
3819 +#ifdef DEBUG
3820 +/* This function prints out a buffer in the format described in the Association
3821 + * Model specification. */
3822 +static void dh_dump(char *str, void *_num, int len)
3823 +{
3824 +       uint8_t *num = _num;
3825 +       int i;
3826 +       DWC_PRINTF("%s\n", str);
3827 +       for (i = 0; i < len; i ++) {
3828 +               DWC_PRINTF("%02x", num[i]);
3829 +               if (((i + 1) % 2) == 0) DWC_PRINTF(" ");
3830 +               if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
3831 +       }
3832 +
3833 +       DWC_PRINTF("\n");
3834 +}
3835 +#else
3836 +#define dh_dump(_x...) do {; } while(0)
3837 +#endif
3838 +
3839 +/* Constant g value */
3840 +static __u32 dh_g[] = {
3841 +       0x02000000,
3842 +};
3843 +
3844 +/* Constant p value */
3845 +static __u32 dh_p[] = {
3846 +       0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
3847 +       0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
3848 +       0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
3849 +       0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
3850 +       0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
3851 +       0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
3852 +       0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
3853 +       0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
3854 +       0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
3855 +       0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
3856 +       0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
3857 +       0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
3858 +};
3859 +
3860 +static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
3861 +{
3862 +       uint8_t *in = _in;
3863 +       uint8_t *out = _out;
3864 +       int i;
3865 +       for (i=0; i<len; i++) {
3866 +               out[i] = in[len-1-i];
3867 +       }
3868 +}
3869 +
3870 +/* Computes the modular exponentiation (num^exp % mod).  num, exp, and mod are
3871 + * big endian numbers of size len, in bytes.  Each len value must be a multiple
3872 + * of 4. */
3873 +int dwc_dh_modpow(void *num, uint32_t num_len,
3874 +                        void *exp, uint32_t exp_len,
3875 +                        void *mod, uint32_t mod_len,
3876 +                        void *out)
3877 +{
3878 +       /* modpow() takes little endian numbers.  AM uses big-endian.  This
3879 +        * function swaps bytes of numbers before passing onto modpow. */
3880 +
3881 +       int retval = 0;
3882 +       uint32_t *result;
3883 +
3884 +       uint32_t *bignum_num = DWC_ALLOC(num_len + 4);
3885 +       uint32_t *bignum_exp = DWC_ALLOC(exp_len + 4);
3886 +       uint32_t *bignum_mod = DWC_ALLOC(mod_len + 4);
3887 +
3888 +       dh_swap_bytes(num, &bignum_num[1], num_len);
3889 +       bignum_num[0] = num_len / 4;
3890 +
3891 +       dh_swap_bytes(exp, &bignum_exp[1], exp_len);
3892 +       bignum_exp[0] = exp_len / 4;
3893 +
3894 +       dh_swap_bytes(mod, &bignum_mod[1], mod_len);
3895 +       bignum_mod[0] = mod_len / 4;
3896 +
3897 +       result = dwc_modpow(bignum_num, bignum_exp, bignum_mod);
3898 +       if (!result) {
3899 +               retval = -1;
3900 +               goto dh_modpow_nomem;
3901 +       }
3902 +
3903 +       dh_swap_bytes(&result[1], out, result[0] * 4);
3904 +       DWC_FREE(result);
3905 +
3906 + dh_modpow_nomem:
3907 +       DWC_FREE(bignum_num);
3908 +       DWC_FREE(bignum_exp);
3909 +       DWC_FREE(bignum_mod);
3910 +       return retval;
3911 +}
3912 +
3913 +
3914 +int dwc_dh_pk(uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
3915 +{
3916 +       int retval;
3917 +       uint8_t m3[385];
3918 +
3919 +#ifndef DH_TEST_VECTORS
3920 +       DWC_RANDOM_BYTES(exp, 32);
3921 +#endif
3922 +
3923 +       /* Compute the pkd */
3924 +       if ((retval = dwc_dh_modpow(dh_g, 4,
3925 +                                         exp, 32,
3926 +                                         dh_p, 384, pk))) {
3927 +               return retval;
3928 +       }
3929 +
3930 +       m3[384] = nd;
3931 +       DWC_MEMCPY(&m3[0], pk, 384);
3932 +       DWC_SHA256(m3, 385, hash);
3933 +
3934 +       dh_dump("PK", pk, 384);
3935 +       dh_dump("SHA-256(M3)", hash, 32);
3936 +       return 0;
3937 +}
3938 +
3939 +int dwc_dh_derive_keys(uint8_t nd, uint8_t *pkh, uint8_t *pkd,
3940 +                            uint8_t *exp, int is_host,
3941 +                            char *dd, uint8_t *ck, uint8_t *kdk)
3942 +{
3943 +       int retval;
3944 +       uint8_t mv[784];
3945 +       uint8_t sha_result[32];
3946 +       uint8_t dhkey[384];
3947 +       uint8_t shared_secret[384];
3948 +       char *message;
3949 +       uint32_t vd;
3950 +
3951 +       uint8_t *pk;
3952 +
3953 +       if (is_host) {
3954 +               pk = pkd;
3955 +       }
3956 +       else {
3957 +               pk = pkh;
3958 +       }
3959 +
3960 +       if ((retval = dwc_dh_modpow(pk, 384,
3961 +                                         exp, 32,
3962 +                                         dh_p, 384, shared_secret))) {
3963 +               return retval;
3964 +       }
3965 +       dh_dump("Shared Secret", shared_secret, 384);
3966 +
3967 +       DWC_SHA256(shared_secret, 384, dhkey);
3968 +       dh_dump("DHKEY", dhkey, 384);
3969 +
3970 +       DWC_MEMCPY(&mv[0], pkd, 384);
3971 +       DWC_MEMCPY(&mv[384], pkh, 384);
3972 +       DWC_MEMCPY(&mv[768], "displayed digest", 16);
3973 +       dh_dump("MV", mv, 784);
3974 +
3975 +       DWC_SHA256(mv, 784, sha_result);
3976 +       dh_dump("SHA-256(MV)", sha_result, 32);
3977 +       dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
3978 +
3979 +       dh_swap_bytes(sha_result, &vd, 4);
3980 +#ifdef DEBUG
3981 +       DWC_PRINTF("Vd (decimal) = %d\n", vd);
3982 +#endif
3983 +
3984 +       switch (nd) {
3985 +       case 2:
3986 +               vd = vd % 100;
3987 +               DWC_SPRINTF(dd, "%02d", vd);
3988 +               break;
3989 +       case 3:
3990 +               vd = vd % 1000;
3991 +               DWC_SPRINTF(dd, "%03d", vd);
3992 +               break;
3993 +       case 4:
3994 +               vd = vd % 10000;
3995 +               DWC_SPRINTF(dd, "%04d", vd);
3996 +               break;
3997 +       }
3998 +#ifdef DEBUG
3999 +       DWC_PRINTF("Display Digits: %s\n", dd);
4000 +#endif
4001 +
4002 +       message = "connection key";
4003 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
4004 +       dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
4005 +       DWC_MEMCPY(ck, sha_result, 16);
4006 +
4007 +       message = "key derivation key";
4008 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
4009 +       dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
4010 +       DWC_MEMCPY(kdk, sha_result, 32);
4011 +
4012 +       return 0;
4013 +}
4014 +
4015 +
4016 +#ifdef DH_TEST_VECTORS
4017 +
4018 +static __u8 dh_a[] = {
4019 +       0x44, 0x00, 0x51, 0xd6,
4020 +       0xf0, 0xb5, 0x5e, 0xa9,
4021 +       0x67, 0xab, 0x31, 0xc6,
4022 +       0x8a, 0x8b, 0x5e, 0x37,
4023 +       0xd9, 0x10, 0xda, 0xe0,
4024 +       0xe2, 0xd4, 0x59, 0xa4,
4025 +       0x86, 0x45, 0x9c, 0xaa,
4026 +       0xdf, 0x36, 0x75, 0x16,
4027 +};
4028 +
4029 +static __u8 dh_b[] = {
4030 +       0x5d, 0xae, 0xc7, 0x86,
4031 +       0x79, 0x80, 0xa3, 0x24,
4032 +       0x8c, 0xe3, 0x57, 0x8f,
4033 +       0xc7, 0x5f, 0x1b, 0x0f,
4034 +       0x2d, 0xf8, 0x9d, 0x30,
4035 +       0x6f, 0xa4, 0x52, 0xcd,
4036 +       0xe0, 0x7a, 0x04, 0x8a,
4037 +       0xde, 0xd9, 0x26, 0x56,
4038 +};
4039 +
4040 +void dwc_run_dh_test_vectors(void)
4041 +{
4042 +       uint8_t pkd[384];
4043 +       uint8_t pkh[384];
4044 +       uint8_t hashd[32];
4045 +       uint8_t hashh[32];
4046 +       uint8_t ck[16];
4047 +       uint8_t kdk[32];
4048 +       char dd[5];
4049 +
4050 +       DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
4051 +
4052 +       /* compute the PKd and SHA-256(PKd || Nd) */
4053 +       DWC_PRINTF("Computing PKd\n");
4054 +       dwc_dh_pk(2, dh_a, pkd, hashd);
4055 +
4056 +       /* compute the PKd and SHA-256(PKh || Nd) */
4057 +       DWC_PRINTF("Computing PKh\n");
4058 +       dwc_dh_pk(2, dh_b, pkh, hashh);
4059 +
4060 +       /* compute the dhkey */
4061 +       dwc_dh_derive_keys(2, pkh, pkd, dh_a, 0, dd, ck, kdk);
4062 +}
4063 +#endif /* DH_TEST_VECTORS */
4064 +
4065 +#endif /* CONFIG_IPMATE_MACH */
4066 --- /dev/null
4067 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.h
4068 @@ -0,0 +1,98 @@
4069 +/* =========================================================================
4070 + * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_dh.h $
4071 + * $Revision: #1 $
4072 + * $Date: 2008/12/21 $
4073 + * $Change: 1156609 $
4074 + *
4075 + * Synopsys Portability Library Software and documentation
4076 + * (hereinafter, "Software") is an Unsupported proprietary work of
4077 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
4078 + * between Synopsys and you.
4079 + *
4080 + * The Software IS NOT an item of Licensed Software or Licensed Product
4081 + * under any End User Software License Agreement or Agreement for
4082 + * Licensed Product with Synopsys or any supplement thereto. You are
4083 + * permitted to use and redistribute this Software in source and binary
4084 + * forms, with or without modification, provided that redistributions
4085 + * of source code must retain this notice. You may not view, use,
4086 + * disclose, copy or distribute this file or any information contained
4087 + * herein except pursuant to this license grant from Synopsys. If you
4088 + * do not agree with this notice, including the disclaimer below, then
4089 + * you are not authorized to use the Software.
4090 + *
4091 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
4092 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4093 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
4094 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
4095 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4096 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4097 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4098 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
4099 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4100 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4101 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
4102 + * DAMAGE.
4103 + * ========================================================================= */
4104 +#ifndef _DWC_DH_H_
4105 +#define _DWC_DH_H_
4106 +
4107 +#include "dwc_os.h"
4108 +
4109 +/** @file
4110 + *
4111 + * This file defines the common functions on device and host for performing
4112 + * numeric association as defined in the WUSB spec.  They are only to be
4113 + * used internally by the DWC UWB modules. */
4114 +
4115 +extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);
4116 +extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,
4117 +                                    uint8_t *key, uint32_t keylen,
4118 +                                    uint8_t *out);
4119 +extern int dwc_dh_modpow(void *num, uint32_t num_len,
4120 +                              void *exp, uint32_t exp_len,
4121 +                              void *mod, uint32_t mod_len,
4122 +                              void *out);
4123 +
4124 +/** Computes PKD or PKH, and SHA-256(PKd || Nd)
4125 + *
4126 + * PK = g^exp mod p.
4127 + *
4128 + * Input:
4129 + * Nd = Number of digits on the device.
4130 + *
4131 + * Output:
4132 + * exp = A 32-byte buffer to be filled with a randomly generated number.
4133 + *       used as either A or B.
4134 + * pk = A 384-byte buffer to be filled with the PKH or PKD.
4135 + * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).
4136 + */
4137 +extern int dwc_dh_pk(uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);
4138 +
4139 +/** Computes the DHKEY, and VD.
4140 + *
4141 + * If called from host, then it will comput DHKEY=PKD^exp % p.
4142 + * If called from device, then it will comput DHKEY=PKH^exp % p.
4143 + *
4144 + * Input:
4145 + * pkd = The PKD value.
4146 + * pkh = The PKH value.
4147 + * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.
4148 + * is_host = Set to non zero if a WUSB host is calling this function.
4149 + *
4150 + * Output:
4151 +
4152 + * dd = A pointer to an buffer to be set to the displayed digits string to be shown
4153 + *      to the user.  This buffer should be at 5 bytes long to hold 4 digits plus a
4154 + *      null termination character.  This buffer can be used directly for display.
4155 + * ck = A 16-byte buffer to be filled with the CK.
4156 + * kdk = A 32-byte buffer to be filled with the KDK.
4157 + */
4158 +extern int dwc_dh_derive_keys(uint8_t nd, uint8_t *pkh, uint8_t *pkd,
4159 +                             uint8_t *exp, int is_host,
4160 +                             char *dd, uint8_t *ck, uint8_t *kdk);
4161 +
4162 +#ifdef DH_TEST_VECTORS
4163 +extern void dwc_run_dh_test_vectors(void);
4164 +#endif
4165 +
4166 +#endif /* _DWC_DH_H_ */
4167 --- /dev/null
4168 +++ b/drivers/usb/host/dwc_common_port/dwc_list.h
4169 @@ -0,0 +1,616 @@
4170 +/*     $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $       */
4171 +/*     $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $       */
4172 +
4173 +/*
4174 + * Copyright (c) 1991, 1993
4175 + *     The Regents of the University of California.  All rights reserved.
4176 + *
4177 + * Redistribution and use in source and binary forms, with or without
4178 + * modification, are permitted provided that the following conditions
4179 + * are met:
4180 + * 1. Redistributions of source code must retain the above copyright
4181 + *    notice, this list of conditions and the following disclaimer.
4182 + * 2. Redistributions in binary form must reproduce the above copyright
4183 + *    notice, this list of conditions and the following disclaimer in the
4184 + *    documentation and/or other materials provided with the distribution.
4185 + * 3. Neither the name of the University nor the names of its contributors
4186 + *    may be used to endorse or promote products derived from this software
4187 + *    without specific prior written permission.
4188 + *
4189 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4190 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4191 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4192 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4193 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4194 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4195 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4196 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4197 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4198 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4199 + * SUCH DAMAGE.
4200 + *
4201 + *     @(#)queue.h     8.5 (Berkeley) 8/20/94
4202 + */
4203 +
4204 +#ifndef        _SYS_QUEUE_H_
4205 +#define        _SYS_QUEUE_H_
4206 +
4207 +
4208 +/** @file
4209 + *
4210 + * This file defines linked list operations.  It is derived from BSD with
4211 + * only the MACRO names being prefixed with DWC_.  This is because a few of
4212 + * these names conflict with those on Linux.  For documentation on use, see the
4213 + * inline comments in the source code.  The original license for this source
4214 + * code applies and is preserved in the dwc_list.h source file.
4215 + */
4216 +
4217 +/*
4218 + * This file defines five types of data structures: singly-linked lists, 
4219 + * lists, simple queues, tail queues, and circular queues.
4220 + *
4221 + *
4222 + * A singly-linked list is headed by a single forward pointer. The elements
4223 + * are singly linked for minimum space and pointer manipulation overhead at
4224 + * the expense of O(n) removal for arbitrary elements. New elements can be
4225 + * added to the list after an existing element or at the head of the list.
4226 + * Elements being removed from the head of the list should use the explicit
4227 + * macro for this purpose for optimum efficiency. A singly-linked list may
4228 + * only be traversed in the forward direction.  Singly-linked lists are ideal
4229 + * for applications with large datasets and few or no removals or for
4230 + * implementing a LIFO queue.
4231 + *
4232 + * A list is headed by a single forward pointer (or an array of forward
4233 + * pointers for a hash table header). The elements are doubly linked
4234 + * so that an arbitrary element can be removed without a need to
4235 + * traverse the list. New elements can be added to the list before
4236 + * or after an existing element or at the head of the list. A list
4237 + * may only be traversed in the forward direction.
4238 + *
4239 + * A simple queue is headed by a pair of pointers, one the head of the
4240 + * list and the other to the tail of the list. The elements are singly
4241 + * linked to save space, so elements can only be removed from the
4242 + * head of the list. New elements can be added to the list before or after
4243 + * an existing element, at the head of the list, or at the end of the
4244 + * list. A simple queue may only be traversed in the forward direction.
4245 + * 
4246 + * A tail queue is headed by a pair of pointers, one to the head of the
4247 + * list and the other to the tail of the list. The elements are doubly
4248 + * linked so that an arbitrary element can be removed without a need to
4249 + * traverse the list. New elements can be added to the list before or
4250 + * after an existing element, at the head of the list, or at the end of
4251 + * the list. A tail queue may be traversed in either direction.
4252 + *
4253 + * A circle queue is headed by a pair of pointers, one to the head of the
4254 + * list and the other to the tail of the list. The elements are doubly
4255 + * linked so that an arbitrary element can be removed without a need to
4256 + * traverse the list. New elements can be added to the list before or after
4257 + * an existing element, at the head of the list, or at the end of the list.
4258 + * A circle queue may be traversed in either direction, but has a more
4259 + * complex end of list detection.
4260 + *
4261 + * For details on the use of these macros, see the queue(3) manual page.
4262 + */
4263 +
4264 +/*
4265 + * Double-linked List.
4266 + */
4267 +
4268 +typedef struct dwc_list_link {
4269 +       struct dwc_list_link *next;
4270 +       struct dwc_list_link *prev;
4271 +} dwc_list_link_t;
4272 +
4273 +#define DWC_LIST_INIT(link) do{                \
4274 +       (link)->next = (link);          \
4275 +       (link)->prev = (link);          \
4276 +} while(0)
4277 +
4278 +#define DWC_LIST_FIRST(link)   ((link)->next)
4279 +#define DWC_LIST_LAST(link)    ((link)->prev)
4280 +#define DWC_LIST_END(link)     (link)
4281 +#define DWC_LIST_NEXT(link)    ((link)->next)
4282 +#define DWC_LIST_PREV(link)    ((link)->prev)
4283 +#define DWC_LIST_EMPTY(link)   \
4284 +       (DWC_LIST_FIRST(link) == DWC_LIST_END(link))
4285 +#define DWC_LIST_ENTRY(link, type, field) (type *)             \
4286 +       ((uint8_t *)(link) - (size_t)(&((type *)0)->field))
4287 +
4288 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
4289 +       (link)->next = (list)->next;                            \
4290 +       (link)->prev = (list);                                  \
4291 +       (list)->next->prev = link;                              \
4292 +       (list)->next = link;                                    \
4293 +} while(0)
4294 +
4295 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
4296 +       (link)->next = list;                                    \
4297 +       (link)->prev = (list)->prev;                            \
4298 +       (list)->prev->next = link;                              \
4299 +       (list)->prev = link;                                    \
4300 +} while(0)
4301 +
4302 +#define DWC_LIST_REMOVE(link) do {                             \
4303 +       (link)->next->prev = (link)->prev;                      \
4304 +       (link)->prev->next = (link)->next;                      \
4305 +} while(0)
4306 +
4307 +#define DWC_LIST_REMOVE_INIT(link) do {                                \
4308 +       DWC_LIST_REMOVE(link);                                  \
4309 +       DWC_LIST_INIT(link);                                    \
4310 +} while(0)
4311 +
4312 +#define DWC_LIST_MOVE_HEAD(list, link) do {                    \
4313 +       DWC_LIST_REMOVE(link);                                  \
4314 +       DWC_LIST_INSERT_HEAD(list, link);                       \
4315 +} while(0)
4316 +
4317 +#define DWC_LIST_MOVE_TAIL(list, link) do {                    \
4318 +       DWC_LIST_REMOVE(link);                                  \
4319 +       DWC_LIST_INSERT_TAIL(list, link);                       \
4320 +} while(0)
4321 +
4322 +#define DWC_LIST_FOREACH(var, list)                            \
4323 +       for((var) = DWC_LIST_FIRST(list);                       \
4324 +           (var) != DWC_LIST_END(list);                        \
4325 +           (var) = DWC_LIST_NEXT(var))
4326 +
4327 +#define DWC_LIST_FOREACH_SAFE(var, var2, list)                 \
4328 +       for((var) = DWC_LIST_FIRST(list), var2 = DWC_LIST_NEXT(var);    \
4329 +           (var) != DWC_LIST_END(list);                        \
4330 +           (var) = (var2), var2 = DWC_LIST_NEXT(var2))
4331 +
4332 +#define DWC_LIST_FOREACH_REVERSE(var, list)                    \
4333 +       for((var) = DWC_LIST_LAST(list);                        \
4334 +           (var) != DWC_LIST_END(list);                        \
4335 +           (var) = DWC_LIST_PREV(var))
4336 +
4337 +/*
4338 + * Singly-linked List definitions.
4339 + */
4340 +#define DWC_SLIST_HEAD(name, type)                                     \
4341 +struct name {                                                          \
4342 +       struct type *slh_first; /* first element */                     \
4343 +}
4344
4345 +#define        DWC_SLIST_HEAD_INITIALIZER(head)                                        \
4346 +       { NULL }
4347
4348 +#define DWC_SLIST_ENTRY(type)                                          \
4349 +struct {                                                               \
4350 +       struct type *sle_next;  /* next element */                      \
4351 +}
4352
4353 +/*
4354 + * Singly-linked List access methods.
4355 + */
4356 +#define DWC_SLIST_FIRST(head)  ((head)->slh_first)
4357 +#define DWC_SLIST_END(head)            NULL
4358 +#define DWC_SLIST_EMPTY(head)  (SLIST_FIRST(head) == SLIST_END(head))
4359 +#define DWC_SLIST_NEXT(elm, field)     ((elm)->field.sle_next)
4360 +
4361 +#define DWC_SLIST_FOREACH(var, head, field)                                    \
4362 +       for((var) = SLIST_FIRST(head);                                  \
4363 +           (var) != SLIST_END(head);                                   \
4364 +           (var) = SLIST_NEXT(var, field))
4365 +
4366 +#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field)                      \
4367 +       for ((varp) = &SLIST_FIRST((head));                             \
4368 +           ((var) = *(varp)) != SLIST_END(head);                       \
4369 +           (varp) = &SLIST_NEXT((var), field))
4370 +
4371 +/*
4372 + * Singly-linked List functions.
4373 + */
4374 +#define DWC_SLIST_INIT(head) {                                         \
4375 +       SLIST_FIRST(head) = SLIST_END(head);                            \
4376 +}
4377 +
4378 +#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do {                      \
4379 +       (elm)->field.sle_next = (slistelm)->field.sle_next;             \
4380 +       (slistelm)->field.sle_next = (elm);                             \
4381 +} while (0)
4382 +
4383 +#define DWC_SLIST_INSERT_HEAD(head, elm, field) do {                   \
4384 +       (elm)->field.sle_next = (head)->slh_first;                      \
4385 +       (head)->slh_first = (elm);                                      \
4386 +} while (0)
4387 +
4388 +#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do {                   \
4389 +       (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
4390 +} while (0)
4391 +
4392 +#define DWC_SLIST_REMOVE_HEAD(head, field) do {                                \
4393 +       (head)->slh_first = (head)->slh_first->field.sle_next;          \
4394 +} while (0)
4395 +
4396 +#define DWC_SLIST_REMOVE(head, elm, type, field) do {                  \
4397 +       if ((head)->slh_first == (elm)) {                               \
4398 +               SLIST_REMOVE_HEAD((head), field);                       \
4399 +       }                                                               \
4400 +       else {                                                          \
4401 +               struct type *curelm = (head)->slh_first;                \
4402 +               while( curelm->field.sle_next != (elm) )                \
4403 +                       curelm = curelm->field.sle_next;                \
4404 +               curelm->field.sle_next =                                \
4405 +                   curelm->field.sle_next->field.sle_next;             \
4406 +       }                                                               \
4407 +} while (0)
4408 +
4409 +#if 0
4410 +
4411 +/*
4412 + * List definitions.
4413 + */
4414 +#define DWC_LIST_HEAD(name, type)                                              \
4415 +struct name {                                                          \
4416 +       struct type *lh_first;  /* first element */                     \
4417 +}
4418 +
4419 +#define DWC_LIST_HEAD_INITIALIZER(head)                                        \
4420 +       { NULL }
4421 +
4422 +#define DWC_LIST_ENTRY(type)                                           \
4423 +struct {                                                               \
4424 +       struct type *le_next;   /* next element */                      \
4425 +       struct type **le_prev;  /* address of previous next element */  \
4426 +}
4427 +
4428 +/*
4429 + * List access methods
4430 + */
4431 +#define DWC_LIST_FIRST(head)           ((head)->lh_first)
4432 +#define DWC_LIST_END(head)                     NULL
4433 +#define DWC_LIST_EMPTY(head)           (DWC_LIST_FIRST(head) == DWC_LIST_END(head))
4434 +#define DWC_LIST_NEXT(elm, field)              ((elm)->field.le_next)
4435 +
4436 +#define DWC_LIST_FOREACH(var, head, field)                                     \
4437 +       for((var) = DWC_LIST_FIRST(head);                                       \
4438 +           (var)!= DWC_LIST_END(head);                                 \
4439 +           (var) = DWC_LIST_NEXT(var, field))
4440 +#define DWC_LIST_FOREACH_SAFE(var, var2, head, field)                          \
4441 +       for((var) = DWC_LIST_FIRST(head), var2 = DWC_LIST_NEXT(var, field);                             \
4442 +           (var) != DWC_LIST_END(head);                                        \
4443 +           (var) = var2, var2 = DWC_LIST_NEXT(var, field))
4444 +
4445 +/*
4446 + * List functions.
4447 + */
4448 +#define DWC_LIST_INIT(head) do {                                               \
4449 +       DWC_LIST_FIRST(head) = DWC_LIST_END(head);                              \
4450 +} while (0)
4451 +
4452 +#define DWC_LIST_INSERT_AFTER(listelm, elm, field) do {                        \
4453 +       if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
4454 +               (listelm)->field.le_next->field.le_prev =               \
4455 +                   &(elm)->field.le_next;                              \
4456 +       (listelm)->field.le_next = (elm);                               \
4457 +       (elm)->field.le_prev = &(listelm)->field.le_next;               \
4458 +} while (0)
4459 +
4460 +#define DWC_LIST_INSERT_BEFORE(listelm, elm, field) do {                       \
4461 +       (elm)->field.le_prev = (listelm)->field.le_prev;                \
4462 +       (elm)->field.le_next = (listelm);                               \
4463 +       *(listelm)->field.le_prev = (elm);                              \
4464 +       (listelm)->field.le_prev = &(elm)->field.le_next;               \
4465 +} while (0)
4466 +
4467 +#define DWC_LIST_INSERT_HEAD(head, elm, field) do {                            \
4468 +       if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
4469 +               (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
4470 +       (head)->lh_first = (elm);                                       \
4471 +       (elm)->field.le_prev = &(head)->lh_first;                       \
4472 +} while (0)
4473 +
4474 +#define DWC_LIST_REMOVE(elm, field) do {                                       \
4475 +       if ((elm)->field.le_next != NULL)                               \
4476 +               (elm)->field.le_next->field.le_prev =                   \
4477 +                   (elm)->field.le_prev;                               \
4478 +       *(elm)->field.le_prev = (elm)->field.le_next;                   \
4479 +} while (0)
4480 +
4481 +#define DWC_LIST_REPLACE(elm, elm2, field) do {                                \
4482 +       if (((elm2)->field.le_next = (elm)->field.le_next) != NULL)     \
4483 +               (elm2)->field.le_next->field.le_prev =                  \
4484 +                   &(elm2)->field.le_next;                             \
4485 +       (elm2)->field.le_prev = (elm)->field.le_prev;                   \
4486 +       *(elm2)->field.le_prev = (elm2);                                \
4487 +} while (0)
4488 +
4489 +#endif
4490 +
4491 +/*
4492 + * Simple queue definitions.
4493 + */
4494 +#define DWC_SIMPLEQ_HEAD(name, type)                                   \
4495 +struct name {                                                          \
4496 +       struct type *sqh_first; /* first element */                     \
4497 +       struct type **sqh_last; /* addr of last next element */         \
4498 +}
4499 +
4500 +#define DWC_SIMPLEQ_HEAD_INITIALIZER(head)                                     \
4501 +       { NULL, &(head).sqh_first }
4502 +
4503 +#define DWC_SIMPLEQ_ENTRY(type)                                                \
4504 +struct {                                                               \
4505 +       struct type *sqe_next;  /* next element */                      \
4506 +}
4507 +
4508 +/*
4509 + * Simple queue access methods.
4510 + */
4511 +#define DWC_SIMPLEQ_FIRST(head)            ((head)->sqh_first)
4512 +#define DWC_SIMPLEQ_END(head)      NULL
4513 +#define DWC_SIMPLEQ_EMPTY(head)            (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
4514 +#define DWC_SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
4515 +
4516 +#define DWC_SIMPLEQ_FOREACH(var, head, field)                          \
4517 +       for((var) = SIMPLEQ_FIRST(head);                                \
4518 +           (var) != SIMPLEQ_END(head);                                 \
4519 +           (var) = SIMPLEQ_NEXT(var, field))
4520 +
4521 +/*
4522 + * Simple queue functions.
4523 + */
4524 +#define DWC_SIMPLEQ_INIT(head) do {                                            \
4525 +       (head)->sqh_first = NULL;                                       \
4526 +       (head)->sqh_last = &(head)->sqh_first;                          \
4527 +} while (0)
4528 +
4529 +#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do {                 \
4530 +       if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)        \
4531 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
4532 +       (head)->sqh_first = (elm);                                      \
4533 +} while (0)
4534 +
4535 +#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do {                 \
4536 +       (elm)->field.sqe_next = NULL;                                   \
4537 +       *(head)->sqh_last = (elm);                                      \
4538 +       (head)->sqh_last = &(elm)->field.sqe_next;                      \
4539 +} while (0)
4540 +
4541 +#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {               \
4542 +       if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
4543 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
4544 +       (listelm)->field.sqe_next = (elm);                              \
4545 +} while (0)
4546 +
4547 +#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do {                      \
4548 +       if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
4549 +               (head)->sqh_last = &(head)->sqh_first;                  \
4550 +} while (0)
4551 +
4552 +/*
4553 + * Tail queue definitions.
4554 + */
4555 +#define DWC_TAILQ_HEAD(name, type)                                             \
4556 +struct name {                                                          \
4557 +       struct type *tqh_first; /* first element */                     \
4558 +       struct type **tqh_last; /* addr of last next element */         \
4559 +}
4560 +
4561 +#define DWC_TAILQ_HEAD_INITIALIZER(head)                                       \
4562 +       { NULL, &(head).tqh_first }
4563 +
4564 +#define DWC_TAILQ_ENTRY(type)                                          \
4565 +struct {                                                               \
4566 +       struct type *tqe_next;  /* next element */                      \
4567 +       struct type **tqe_prev; /* address of previous next element */  \
4568 +}
4569 +
4570 +/* 
4571 + * tail queue access methods 
4572 + */
4573 +#define DWC_TAILQ_FIRST(head)          ((head)->tqh_first)
4574 +#define DWC_TAILQ_END(head)                    NULL
4575 +#define DWC_TAILQ_NEXT(elm, field)             ((elm)->field.tqe_next)
4576 +#define DWC_TAILQ_LAST(head, headname)                                 \
4577 +       (*(((struct headname *)((head)->tqh_last))->tqh_last))
4578 +/* XXX */
4579 +#define DWC_TAILQ_PREV(elm, headname, field)                           \
4580 +       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
4581 +#define DWC_TAILQ_EMPTY(head)                                          \
4582 +       (TAILQ_FIRST(head) == TAILQ_END(head))
4583 +
4584 +#define DWC_TAILQ_FOREACH(var, head, field)                                    \
4585 +       for((var) = TAILQ_FIRST(head);                                  \
4586 +           (var) != TAILQ_END(head);                                   \
4587 +           (var) = TAILQ_NEXT(var, field))
4588 +
4589 +#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field)          \
4590 +       for((var) = TAILQ_LAST(head, headname);                         \
4591 +           (var) != TAILQ_END(head);                                   \
4592 +           (var) = TAILQ_PREV(var, headname, field))
4593 +
4594 +/*
4595 + * Tail queue functions.
4596 + */
4597 +#define DWC_TAILQ_INIT(head) do {                                              \
4598 +       (head)->tqh_first = NULL;                                       \
4599 +       (head)->tqh_last = &(head)->tqh_first;                          \
4600 +} while (0)
4601 +
4602 +#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do {                   \
4603 +       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
4604 +               (head)->tqh_first->field.tqe_prev =                     \
4605 +                   &(elm)->field.tqe_next;                             \
4606 +       else                                                            \
4607 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
4608 +       (head)->tqh_first = (elm);                                      \
4609 +       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
4610 +} while (0)
4611 +
4612 +#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do {                   \
4613 +       (elm)->field.tqe_next = NULL;                                   \
4614 +       (elm)->field.tqe_prev = (head)->tqh_last;                       \
4615 +       *(head)->tqh_last = (elm);                                      \
4616 +       (head)->tqh_last = &(elm)->field.tqe_next;                      \
4617 +} while (0)
4618 +
4619 +#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {         \
4620 +       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
4621 +               (elm)->field.tqe_next->field.tqe_prev =                 \
4622 +                   &(elm)->field.tqe_next;                             \
4623 +       else                                                            \
4624 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
4625 +       (listelm)->field.tqe_next = (elm);                              \
4626 +       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
4627 +} while (0)
4628 +
4629 +#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do {                      \
4630 +       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
4631 +       (elm)->field.tqe_next = (listelm);                              \
4632 +       *(listelm)->field.tqe_prev = (elm);                             \
4633 +       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
4634 +} while (0)
4635 +
4636 +#define DWC_TAILQ_REMOVE(head, elm, field) do {                                \
4637 +       if (((elm)->field.tqe_next) != NULL)                            \
4638 +               (elm)->field.tqe_next->field.tqe_prev =                 \
4639 +                   (elm)->field.tqe_prev;                              \
4640 +       else                                                            \
4641 +               (head)->tqh_last = (elm)->field.tqe_prev;               \
4642 +       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
4643 +} while (0)
4644 +
4645 +#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do {                 \
4646 +       if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   \
4647 +               (elm2)->field.tqe_next->field.tqe_prev =                \
4648 +                   &(elm2)->field.tqe_next;                            \
4649 +       else                                                            \
4650 +               (head)->tqh_last = &(elm2)->field.tqe_next;             \
4651 +       (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 \
4652 +       *(elm2)->field.tqe_prev = (elm2);                               \
4653 +} while (0)
4654 +
4655 +/*
4656 + * Circular queue definitions.
4657 + */
4658 +#define DWC_CIRCLEQ_HEAD(name, type)                                   \
4659 +struct name {                                                          \
4660 +       struct type *cqh_first;         /* first element */             \
4661 +       struct type *cqh_last;          /* last element */              \
4662 +}
4663 +
4664 +#define DWC_CIRCLEQ_HEAD_INITIALIZER(head)                                     \
4665 +       { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }
4666 +
4667 +#define DWC_CIRCLEQ_ENTRY(type)                                                \
4668 +struct {                                                               \
4669 +       struct type *cqe_next;          /* next element */              \
4670 +       struct type *cqe_prev;          /* previous element */          \
4671 +}
4672 +
4673 +/*
4674 + * Circular queue access methods 
4675 + */
4676 +#define DWC_CIRCLEQ_FIRST(head)                ((head)->cqh_first)
4677 +#define DWC_CIRCLEQ_LAST(head)         ((head)->cqh_last)
4678 +#define DWC_CIRCLEQ_END(head)          ((void *)(head))
4679 +#define DWC_CIRCLEQ_NEXT(elm, field)   ((elm)->field.cqe_next)
4680 +#define DWC_CIRCLEQ_PREV(elm, field)   ((elm)->field.cqe_prev)
4681 +#define DWC_CIRCLEQ_EMPTY(head)                                                \
4682 +       (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))
4683 +
4684 +#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))
4685 +
4686 +#define DWC_CIRCLEQ_FOREACH(var, head, field)                          \
4687 +       for((var) = DWC_CIRCLEQ_FIRST(head);                            \
4688 +           (var) != DWC_CIRCLEQ_END(head);                                     \
4689 +           (var) = DWC_CIRCLEQ_NEXT(var, field))
4690 +
4691 +#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field)                               \
4692 +       for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field);                               \
4693 +           (var) != DWC_CIRCLEQ_END(head);                                     \
4694 +           (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))
4695 +
4696 +#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field)                  \
4697 +       for((var) = DWC_CIRCLEQ_LAST(head);                                     \
4698 +           (var) != DWC_CIRCLEQ_END(head);                                     \
4699 +           (var) = DWC_CIRCLEQ_PREV(var, field))
4700 +
4701 +/*
4702 + * Circular queue functions.
4703 + */
4704 +#define DWC_CIRCLEQ_INIT(head) do {                                            \
4705 +       (head)->cqh_first = DWC_CIRCLEQ_END(head);                              \
4706 +       (head)->cqh_last = DWC_CIRCLEQ_END(head);                               \
4707 +} while (0)
4708 +
4709 +#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \
4710 +       (elm)->field.cqe_next = NULL; \
4711 +       (elm)->field.cqe_prev = NULL; \
4712 +} while (0)
4713 +
4714 +#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {               \
4715 +       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
4716 +       (elm)->field.cqe_prev = (listelm);                              \
4717 +       if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head))         \
4718 +               (head)->cqh_last = (elm);                               \
4719 +       else                                                            \
4720 +               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
4721 +       (listelm)->field.cqe_next = (elm);                              \
4722 +} while (0)
4723 +
4724 +#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {              \
4725 +       (elm)->field.cqe_next = (listelm);                              \
4726 +       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
4727 +       if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head))         \
4728 +               (head)->cqh_first = (elm);                              \
4729 +       else                                                            \
4730 +               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
4731 +       (listelm)->field.cqe_prev = (elm);                              \
4732 +} while (0)
4733 +
4734 +#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do {                 \
4735 +       (elm)->field.cqe_next = (head)->cqh_first;                      \
4736 +       (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head);                  \
4737 +       if ((head)->cqh_last == DWC_CIRCLEQ_END(head))                  \
4738 +               (head)->cqh_last = (elm);                               \
4739 +       else                                                            \
4740 +               (head)->cqh_first->field.cqe_prev = (elm);              \
4741 +       (head)->cqh_first = (elm);                                      \
4742 +} while (0)
4743 +
4744 +#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do {                 \
4745 +       (elm)->field.cqe_next = DWC_CIRCLEQ_END(head);                  \
4746 +       (elm)->field.cqe_prev = (head)->cqh_last;                       \
4747 +       if ((head)->cqh_first == DWC_CIRCLEQ_END(head))                 \
4748 +               (head)->cqh_first = (elm);                              \
4749 +       else                                                            \
4750 +               (head)->cqh_last->field.cqe_next = (elm);               \
4751 +       (head)->cqh_last = (elm);                                       \
4752 +} while (0)
4753 +
4754 +#define DWC_CIRCLEQ_REMOVE(head, elm, field) do {                              \
4755 +       if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head))                     \
4756 +               (head)->cqh_last = (elm)->field.cqe_prev;               \
4757 +       else                                                            \
4758 +               (elm)->field.cqe_next->field.cqe_prev =                 \
4759 +                   (elm)->field.cqe_prev;                              \
4760 +       if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head))                     \
4761 +               (head)->cqh_first = (elm)->field.cqe_next;              \
4762 +       else                                                            \
4763 +               (elm)->field.cqe_prev->field.cqe_next =                 \
4764 +                   (elm)->field.cqe_next;                              \
4765 +} while (0)
4766 +
4767 +#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \
4768 +       DWC_CIRCLEQ_REMOVE(head, elm, field); \
4769 +       DWC_CIRCLEQ_INIT_ENTRY(elm, field); \
4770 +} while (0)
4771 +
4772 +#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do {                       \
4773 +       if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==         \
4774 +           DWC_CIRCLEQ_END(head))                                              \
4775 +               (head).cqh_last = (elm2);                               \
4776 +       else                                                            \
4777 +               (elm2)->field.cqe_next->field.cqe_prev = (elm2);        \
4778 +       if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==         \
4779 +           DWC_CIRCLEQ_END(head))                                              \
4780 +               (head).cqh_first = (elm2);                              \
4781 +       else                                                            \
4782 +               (elm2)->field.cqe_prev->field.cqe_next = (elm2);        \
4783 +} while (0)
4784 +
4785 +#endif /* !_SYS_QUEUE_H_ */
4786 --- /dev/null
4787 +++ b/drivers/usb/host/dwc_common_port/dwc_mem.c
4788 @@ -0,0 +1,172 @@
4789 +#include "dwc_os.h"
4790 +#include "dwc_list.h"
4791 +
4792 +/* Memory Debugging */
4793 +#ifdef DEBUG_MEMORY
4794 +
4795 +struct allocation
4796 +{
4797 +       void *addr;
4798 +       char *func;
4799 +       int line;
4800 +       uint32_t size;
4801 +       int dma;
4802 +       DWC_CIRCLEQ_ENTRY(allocation) entry;
4803 +};
4804 +
4805 +DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
4806 +
4807 +struct allocation_manager
4808 +{
4809 +       struct allocation_queue allocations;
4810 +
4811 +       /* statistics */
4812 +       int num;
4813 +       int num_freed;
4814 +       int num_active;
4815 +       uint32_t total;
4816 +       uint32_t current;
4817 +       uint32_t max;
4818 +};
4819 +
4820 +
4821 +static struct allocation_manager *manager = NULL;
4822 +
4823 +static void add_allocation(uint32_t size, char const* func, int line, void *addr, int dma)
4824 +{
4825 +       struct allocation *a = __DWC_ALLOC_ATOMIC(sizeof(*a));
4826 +       a->func = __DWC_ALLOC_ATOMIC(DWC_STRLEN(func)+1);
4827 +       DWC_MEMCPY(a->func, func, DWC_STRLEN(func)+1);
4828 +       a->line = line;
4829 +       a->size = size;
4830 +       a->addr = addr;
4831 +       a->dma = dma;
4832 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
4833 +
4834 +       /* Update stats */
4835 +       manager->num ++;
4836 +       manager->num_active ++;
4837 +       manager->total += size;
4838 +       manager->current += size;
4839 +       if (manager->max < manager->current) {
4840 +               manager->max = manager->current;
4841 +       }
4842 +}
4843 +
4844 +static struct allocation *find_allocation(void *addr)
4845 +{
4846 +       struct allocation *a;
4847 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
4848 +               if (a->addr == addr) {
4849 +                       return a;
4850 +               }
4851 +       }
4852 +       return NULL;
4853 +}
4854 +
4855 +static void free_allocation(void *addr, char const* func, int line)
4856 +{
4857 +       struct allocation *a = find_allocation(addr);
4858 +       if (!a && func && (line >= 0)) {
4859 +               DWC_ASSERT(0, "Free of address %p that was never allocated or already freed %s:%d", addr, func, line);
4860 +               return;
4861 +       }
4862 +       DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
4863 +
4864 +       manager->num_active --;
4865 +       manager->num_freed ++;
4866 +       manager->current -= a->size;
4867 +       __DWC_FREE(a->func);
4868 +       __DWC_FREE(a);
4869 +}
4870 +
4871 +void dwc_memory_debug_start(void)
4872 +{
4873 +       DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
4874 +       if (manager == NULL) {
4875 +               manager = __DWC_ALLOC(sizeof(*manager));
4876 +       }
4877 +
4878 +       DWC_CIRCLEQ_INIT(&manager->allocations);
4879 +       manager->num = 0;
4880 +       manager->num_freed = 0;
4881 +       manager->num_active = 0;
4882 +       manager->total = 0;
4883 +       manager->current = 0;
4884 +       manager->max = 0;
4885 +}
4886 +
4887 +void dwc_memory_debug_stop(void)
4888 +{
4889 +       struct allocation *a;
4890 +       dwc_memory_debug_report();
4891 +
4892 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
4893 +               DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
4894 +               free_allocation(a->addr, NULL, -1);
4895 +       }
4896 +
4897 +       __DWC_FREE(manager);
4898 +}
4899 +
4900 +void dwc_memory_debug_report(void)
4901 +{
4902 +       struct allocation *a;
4903 +       DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
4904 +       DWC_PRINTF("Num Allocations = %d\n", manager->num);
4905 +       DWC_PRINTF("Freed = %d\n", manager->num_freed);
4906 +       DWC_PRINTF("Active = %d\n", manager->num_active);
4907 +       DWC_PRINTF("Current Memory Used = %d\n", manager->current);
4908 +       DWC_PRINTF("Total Memory Used = %d\n", manager->total);
4909 +       DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
4910 +       DWC_PRINTF("Unfreed allocations:\n");
4911 +
4912 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
4913 +               DWC_PRINTF("    addr=%p, size=%d from %s:%d, DMA=%d\n", a->addr, a->size, a->func, a->line, a->dma);
4914 +       }
4915 +}
4916 +
4917 +
4918 +
4919 +/* The replacement functions */
4920 +void *dwc_alloc_debug(uint32_t size, char const* func, int line)
4921 +{
4922 +       void *addr = __DWC_ALLOC(size);
4923 +       add_allocation(size, func, line, addr, 0);
4924 +       return addr;
4925 +}
4926 +
4927 +void *dwc_alloc_atomic_debug(uint32_t size, char const* func, int line)
4928 +{
4929 +       void *addr = __DWC_ALLOC_ATOMIC(size);
4930 +       add_allocation(size, func, line, addr, 0);
4931 +       return addr;
4932 +}
4933 +
4934 +void dwc_free_debug(void *addr, char const* func, int line)
4935 +{
4936 +       free_allocation(addr, func, line);
4937 +       __DWC_FREE(addr);
4938 +}
4939 +
4940 +void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line)
4941 +{
4942 +       void *addr = __DWC_DMA_ALLOC(size, dma_addr);
4943 +       add_allocation(size, func, line, addr, 1);
4944 +       return addr;
4945 +}
4946 +
4947 +void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line)
4948 +{
4949 +       void *addr = __DWC_DMA_ALLOC_ATOMIC(size, dma_addr);
4950 +       add_allocation(size, func, line, addr, 1);
4951 +       return addr;
4952 +}
4953 +
4954 +void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line)
4955 +{
4956 +       free_allocation(virt_addr, func, line);
4957 +       __DWC_DMA_FREE(size, virt_addr, dma_addr);
4958 +}
4959 +
4960 +#endif /* DEBUG_MEMORY */
4961 --- /dev/null
4962 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c
4963 @@ -0,0 +1,622 @@
4964 +/* Bignum routines adapted from PUTTY sources.  PuTTY copyright notice follows.
4965 + *
4966 + * PuTTY is copyright 1997-2007 Simon Tatham.
4967 + *
4968 + * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
4969 + * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
4970 + * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
4971 + * Kuhn, and CORE SDI S.A.
4972 + *
4973 + * Permission is hereby granted, free of charge, to any person
4974 + * obtaining a copy of this software and associated documentation files
4975 + * (the "Software"), to deal in the Software without restriction,
4976 + * including without limitation the rights to use, copy, modify, merge,
4977 + * publish, distribute, sublicense, and/or sell copies of the Software,
4978 + * and to permit persons to whom the Software is furnished to do so,
4979 + * subject to the following conditions:
4980 + *
4981 + * The above copyright notice and this permission notice shall be
4982 + * included in all copies or substantial portions of the Software.
4983 +
4984 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4985 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4986 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
4987 + * NONINFRINGEMENT.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
4988 + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
4989 + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
4990 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4991 + *
4992 + */
4993 +
4994 +#ifndef CONFIG_MACH_IPMATE
4995 +
4996 +
4997 +#include "dwc_modpow.h"
4998 +
4999 +#define BIGNUM_INT_MASK  0xFFFFFFFFUL
5000 +#define BIGNUM_TOP_BIT   0x80000000UL
5001 +#define BIGNUM_INT_BITS  32
5002 +
5003 +
5004 +static void *snmalloc(size_t n, size_t size)
5005 +{
5006 +    void *p;
5007 +    size *= n;
5008 +    if (size == 0) size = 1;
5009 +    p = DWC_ALLOC(size);
5010 +    return p;
5011 +}
5012 +
5013 +#define snewn(n, type) ((type *)snmalloc((n), sizeof(type)))
5014 +#define sfree DWC_FREE
5015 +
5016 +/*
5017 + * Usage notes:
5018 + *  * Do not call the DIVMOD_WORD macro with expressions such as array
5019 + *    subscripts, as some implementations object to this (see below).
5020 + *  * Note that none of the division methods below will cope if the
5021 + *    quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
5022 + *    to avoid this case.
5023 + *    If this condition occurs, in the case of the x86 DIV instruction,
5024 + *    an overflow exception will occur, which (according to a correspondent)
5025 + *    will manifest on Windows as something like
5026 + *      0xC0000095: Integer overflow
5027 + *    The C variant won't give the right answer, either.
5028 + */
5029 +
5030 +#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
5031 +
5032 +#if defined __GNUC__ && defined __i386__
5033 +#define DIVMOD_WORD(q, r, hi, lo, w) \
5034 +    __asm__("div %2" : \
5035 +           "=d" (r), "=a" (q) : \
5036 +           "r" (w), "d" (hi), "a" (lo))
5037 +#else
5038 +#define DIVMOD_WORD(q, r, hi, lo, w) do { \
5039 +    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
5040 +    q = n / w; \
5041 +    r = n % w; \
5042 +} while (0)
5043 +#endif
5044 +
5045 +//    q = n / w;                                
5046 +//    r = n % w;                                
5047 +
5048 +#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
5049 +
5050 +#define BIGNUM_INTERNAL
5051 +
5052 +static Bignum newbn(int length)
5053 +{
5054 +    Bignum b = snewn(length + 1, BignumInt);
5055 +    //if (!b)
5056 +    //abort();                /* FIXME */
5057 +    DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));
5058 +    b[0] = length;
5059 +    return b;
5060 +}
5061 +
5062 +void freebn(Bignum b)
5063 +{
5064 +    /*
5065 +     * Burn the evidence, just in case.
5066 +     */
5067 +    DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));
5068 +    sfree(b);
5069 +}
5070 +
5071 +/*
5072 + * Compute c = a * b.
5073 + * Input is in the first len words of a and b.
5074 + * Result is returned in the first 2*len words of c.
5075 + */
5076 +static void internal_mul(BignumInt *a, BignumInt *b,
5077 +                        BignumInt *c, int len)
5078 +{
5079 +    int i, j;
5080 +    BignumDblInt t;
5081 +
5082 +    for (j = 0; j < 2 * len; j++)
5083 +       c[j] = 0;
5084 +
5085 +    for (i = len - 1; i >= 0; i--) {
5086 +       t = 0;
5087 +       for (j = len - 1; j >= 0; j--) {
5088 +           t += MUL_WORD(a[i], (BignumDblInt) b[j]);
5089 +           t += (BignumDblInt) c[i + j + 1];
5090 +           c[i + j + 1] = (BignumInt) t;
5091 +           t = t >> BIGNUM_INT_BITS;
5092 +       }
5093 +       c[i] = (BignumInt) t;
5094 +    }
5095 +}
5096 +
5097 +static void internal_add_shifted(BignumInt *number,
5098 +                                unsigned n, int shift)
5099 +{
5100 +    int word = 1 + (shift / BIGNUM_INT_BITS);
5101 +    int bshift = shift % BIGNUM_INT_BITS;
5102 +    BignumDblInt addend;
5103 +
5104 +    addend = (BignumDblInt)n << bshift;
5105 +
5106 +    while (addend) {
5107 +       addend += number[word];
5108 +       number[word] = (BignumInt) addend & BIGNUM_INT_MASK;
5109 +       addend >>= BIGNUM_INT_BITS;
5110 +       word++;
5111 +    }
5112 +}
5113 +
5114 +/*
5115 + * Compute a = a % m.
5116 + * Input in first alen words of a and first mlen words of m.
5117 + * Output in first alen words of a
5118 + * (of which first alen-mlen words will be zero).
5119 + * The MSW of m MUST have its high bit set.
5120 + * Quotient is accumulated in the `quotient' array, which is a Bignum
5121 + * rather than the internal bigendian format. Quotient parts are shifted
5122 + * left by `qshift' before adding into quot.
5123 + */
5124 +static void internal_mod(BignumInt *a, int alen,
5125 +                        BignumInt *m, int mlen,
5126 +                        BignumInt *quot, int qshift)
5127 +{
5128 +    BignumInt m0, m1;
5129 +    unsigned int h;
5130 +    int i, k;
5131 +
5132 +    m0 = m[0];
5133 +    if (mlen > 1)
5134 +       m1 = m[1];
5135 +    else
5136 +       m1 = 0;
5137 +
5138 +    for (i = 0; i <= alen - mlen; i++) {
5139 +       BignumDblInt t;
5140 +       unsigned int q, r, c, ai1;
5141 +
5142 +       if (i == 0) {
5143 +           h = 0;
5144 +       } else {
5145 +           h = a[i - 1];
5146 +           a[i - 1] = 0;
5147 +       }
5148 +
5149 +       if (i == alen - 1)
5150 +           ai1 = 0;
5151 +       else
5152 +           ai1 = a[i + 1];
5153 +
5154 +       /* Find q = h:a[i] / m0 */
5155 +       if (h >= m0) {
5156 +           /*
5157 +            * Special case.
5158 +            * 
5159 +            * To illustrate it, suppose a BignumInt is 8 bits, and
5160 +            * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then
5161 +            * our initial division will be 0xA123 / 0xA1, which
5162 +            * will give a quotient of 0x100 and a divide overflow.
5163 +            * However, the invariants in this division algorithm
5164 +            * are not violated, since the full number A1:23:... is
5165 +            * _less_ than the quotient prefix A1:B2:... and so the
5166 +            * following correction loop would have sorted it out.
5167 +            * 
5168 +            * In this situation we set q to be the largest
5169 +            * quotient we _can_ stomach (0xFF, of course).
5170 +            */
5171 +           q = BIGNUM_INT_MASK;
5172 +       } else {
5173 +           /* Macro doesn't want an array subscript expression passed
5174 +            * into it (see definition), so use a temporary. */
5175 +           BignumInt tmplo = a[i];
5176 +           DIVMOD_WORD(q, r, h, tmplo, m0);
5177 +
5178 +           /* Refine our estimate of q by looking at
5179 +            h:a[i]:a[i+1] / m0:m1 */
5180 +           t = MUL_WORD(m1, q);
5181 +           if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {
5182 +               q--;
5183 +               t -= m1;
5184 +               r = (r + m0) & BIGNUM_INT_MASK;     /* overflow? */
5185 +               if (r >= (BignumDblInt) m0 &&
5186 +                   t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;
5187 +           }
5188 +       }
5189 +
5190 +       /* Subtract q * m from a[i...] */
5191 +       c = 0;
5192 +       for (k = mlen - 1; k >= 0; k--) {
5193 +           t = MUL_WORD(q, m[k]);
5194 +           t += c;
5195 +           c = (unsigned)(t >> BIGNUM_INT_BITS);
5196 +           if ((BignumInt) t > a[i + k])
5197 +               c++;
5198 +           a[i + k] -= (BignumInt) t;
5199 +       }
5200 +
5201 +       /* Add back m in case of borrow */
5202 +       if (c != h) {
5203 +           t = 0;
5204 +           for (k = mlen - 1; k >= 0; k--) {
5205 +               t += m[k];
5206 +               t += a[i + k];
5207 +               a[i + k] = (BignumInt) t;
5208 +               t = t >> BIGNUM_INT_BITS;
5209 +           }
5210 +           q--;
5211 +       }
5212 +       if (quot)
5213 +           internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));
5214 +    }
5215 +}
5216 +
5217 +/*
5218 + * Compute p % mod.
5219 + * The most significant word of mod MUST be non-zero.
5220 + * We assume that the result array is the same size as the mod array.
5221 + * We optionally write out a quotient if `quotient' is non-NULL.
5222 + * We can avoid writing out the result if `result' is NULL.
5223 + */
5224 +void bigdivmod(Bignum p, Bignum mod, Bignum result, Bignum quotient)
5225 +{
5226 +    BignumInt *n, *m;
5227 +    int mshift;
5228 +    int plen, mlen, i, j;
5229 +
5230 +    /* Allocate m of size mlen, copy mod to m */
5231 +    /* We use big endian internally */
5232 +    mlen = mod[0];
5233 +    m = snewn(mlen, BignumInt);
5234 +    for (j = 0; j < mlen; j++)
5235 +       m[j] = mod[mod[0] - j];
5236 +
5237 +    /* Shift m left to make msb bit set */
5238 +    for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)
5239 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
5240 +           break;
5241 +    if (mshift) {
5242 +       for (i = 0; i < mlen - 1; i++)
5243 +           m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));
5244 +       m[mlen - 1] = m[mlen - 1] << mshift;
5245 +    }
5246 +
5247 +    plen = p[0];
5248 +    /* Ensure plen > mlen */
5249 +    if (plen <= mlen)
5250 +       plen = mlen + 1;
5251 +
5252 +    /* Allocate n of size plen, copy p to n */
5253 +    n = snewn(plen, BignumInt);
5254 +    for (j = 0; j < plen; j++)
5255 +       n[j] = 0;
5256 +    for (j = 1; j <= (int)p[0]; j++)
5257 +       n[plen - j] = p[j];
5258 +
5259 +    /* Main computation */
5260 +    internal_mod(n, plen, m, mlen, quotient, mshift);
5261 +
5262 +    /* Fixup result in case the modulus was shifted */
5263 +    if (mshift) {
5264 +       for (i = plen - mlen - 1; i < plen - 1; i++)
5265 +           n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));
5266 +       n[plen - 1] = n[plen - 1] << mshift;
5267 +       internal_mod(n, plen, m, mlen, quotient, 0);
5268 +       for (i = plen - 1; i >= plen - mlen; i--)
5269 +           n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));
5270 +    }
5271 +
5272 +    /* Copy result to buffer */
5273 +    if (result) {
5274 +       for (i = 1; i <= (int)result[0]; i++) {
5275 +           int j = plen - i;
5276 +           result[i] = j >= 0 ? n[j] : 0;
5277 +       }
5278 +    }
5279 +
5280 +    /* Free temporary arrays */
5281 +    for (i = 0; i < mlen; i++)
5282 +       m[i] = 0;
5283 +    sfree(m);
5284 +    for (i = 0; i < plen; i++)
5285 +       n[i] = 0;
5286 +    sfree(n);
5287 +}
5288 +
5289 +/*
5290 + * Simple remainder.
5291 + */
5292 +Bignum bigmod(Bignum a, Bignum b)
5293 +{
5294 +    Bignum r = newbn(b[0]);
5295 +    bigdivmod(a, b, r, NULL);
5296 +    return r;
5297 +}
5298 +
5299 +/*
5300 + * Compute (base ^ exp) % mod.
5301 + */
5302 +Bignum dwc_modpow(Bignum base_in, Bignum exp, Bignum mod)
5303 +{
5304 +    BignumInt *a, *b, *n, *m;
5305 +    int mshift;
5306 +    int mlen, i, j;
5307 +    Bignum base, result;
5308 +
5309 +    /*
5310 +     * The most significant word of mod needs to be non-zero. It
5311 +     * should already be, but let's make sure.
5312 +     */
5313 +    //assert(mod[mod[0]] != 0);
5314 +
5315 +    /*
5316 +     * Make sure the base is smaller than the modulus, by reducing
5317 +     * it modulo the modulus if not.
5318 +     */
5319 +    base = bigmod(base_in, mod);
5320 +
5321 +    /* Allocate m of size mlen, copy mod to m */
5322 +    /* We use big endian internally */
5323 +    mlen = mod[0];
5324 +    m = snewn(mlen, BignumInt);
5325 +    for (j = 0; j < mlen; j++)
5326 +       m[j] = mod[mod[0] - j];
5327 +
5328 +    /* Shift m left to make msb bit set */
5329 +    for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)
5330 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
5331 +           break;
5332 +    if (mshift) {
5333 +       for (i = 0; i < mlen - 1; i++)
5334 +           m[i] =
5335 +               (m[i] << mshift) | (m[i + 1] >>
5336 +                                   (BIGNUM_INT_BITS - mshift));
5337 +       m[mlen - 1] = m[mlen - 1] << mshift;
5338 +    }
5339 +
5340 +    /* Allocate n of size mlen, copy base to n */
5341 +    n = snewn(mlen, BignumInt);
5342 +    i = mlen - base[0];
5343 +    for (j = 0; j < i; j++)
5344 +       n[j] = 0;
5345 +    for (j = 0; j < base[0]; j++)
5346 +       n[i + j] = base[base[0] - j];
5347 +
5348 +    /* Allocate a and b of size 2*mlen. Set a = 1 */
5349 +    a = snewn(2 * mlen, BignumInt);
5350 +    b = snewn(2 * mlen, BignumInt);
5351 +    for (i = 0; i < 2 * mlen; i++)
5352 +       a[i] = 0;
5353 +    a[2 * mlen - 1] = 1;
5354 +
5355 +    /* Skip leading zero bits of exp. */
5356 +    i = 0;
5357 +    j = BIGNUM_INT_BITS - 1;
5358 +    while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
5359 +       j--;
5360 +       if (j < 0) {
5361 +           i++;
5362 +           j = BIGNUM_INT_BITS - 1;
5363 +       }
5364 +    }
5365 +
5366 +    /* Main computation */
5367 +    while (i < exp[0]) {
5368 +       while (j >= 0) {
5369 +           internal_mul(a + mlen, a + mlen, b, mlen);
5370 +           internal_mod(b, mlen * 2, m, mlen, NULL, 0);
5371 +           if ((exp[exp[0] - i] & (1 << j)) != 0) {
5372 +               internal_mul(b + mlen, n, a, mlen);
5373 +               internal_mod(a, mlen * 2, m, mlen, NULL, 0);
5374 +           } else {
5375 +               BignumInt *t;
5376 +               t = a;
5377 +               a = b;
5378 +               b = t;
5379 +           }
5380 +           j--;
5381 +       }
5382 +       i++;
5383 +       j = BIGNUM_INT_BITS - 1;
5384 +    }
5385 +
5386 +    /* Fixup result in case the modulus was shifted */
5387 +    if (mshift) {
5388 +       for (i = mlen - 1; i < 2 * mlen - 1; i++)
5389 +           a[i] =
5390 +               (a[i] << mshift) | (a[i + 1] >>
5391 +                                   (BIGNUM_INT_BITS - mshift));
5392 +       a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;
5393 +       internal_mod(a, mlen * 2, m, mlen, NULL, 0);
5394 +       for (i = 2 * mlen - 1; i >= mlen; i--)
5395 +           a[i] =
5396 +               (a[i] >> mshift) | (a[i - 1] <<
5397 +                                   (BIGNUM_INT_BITS - mshift));
5398 +    }
5399 +
5400 +    /* Copy result to buffer */
5401 +    result = newbn(mod[0]);
5402 +    for (i = 0; i < mlen; i++)
5403 +       result[result[0] - i] = a[i + mlen];
5404 +    while (result[0] > 1 && result[result[0]] == 0)
5405 +       result[0]--;
5406 +
5407 +    /* Free temporary arrays */
5408 +    for (i = 0; i < 2 * mlen; i++)
5409 +       a[i] = 0;
5410 +    sfree(a);
5411 +    for (i = 0; i < 2 * mlen; i++)
5412 +       b[i] = 0;
5413 +    sfree(b);
5414 +    for (i = 0; i < mlen; i++)
5415 +       m[i] = 0;
5416 +    sfree(m);
5417 +    for (i = 0; i < mlen; i++)
5418 +       n[i] = 0;
5419 +    sfree(n);
5420 +
5421 +    freebn(base);
5422 +
5423 +    return result;
5424 +}
5425 +
5426 +
5427 +#ifdef UNITTEST
5428 +
5429 +static __u32 dh_p[] = {
5430 +       96,
5431 +       0xFFFFFFFF,
5432 +       0xFFFFFFFF,
5433 +       0xA93AD2CA,
5434 +       0x4B82D120,
5435 +       0xE0FD108E,
5436 +       0x43DB5BFC,
5437 +       0x74E5AB31,
5438 +       0x08E24FA0,
5439 +       0xBAD946E2,
5440 +       0x770988C0,
5441 +       0x7A615D6C,
5442 +       0xBBE11757,
5443 +       0x177B200C,
5444 +       0x521F2B18,
5445 +       0x3EC86A64,
5446 +       0xD8760273,
5447 +       0xD98A0864,
5448 +       0xF12FFA06,
5449 +       0x1AD2EE6B,
5450 +       0xCEE3D226,
5451 +       0x4A25619D,
5452 +       0x1E8C94E0,
5453 +       0xDB0933D7,
5454 +       0xABF5AE8C,
5455 +       0xA6E1E4C7,
5456 +       0xB3970F85,
5457 +       0x5D060C7D,
5458 +       0x8AEA7157,
5459 +       0x58DBEF0A,
5460 +       0xECFB8504,
5461 +       0xDF1CBA64,
5462 +       0xA85521AB,
5463 +       0x04507A33,
5464 +       0xAD33170D,
5465 +       0x8AAAC42D,
5466 +       0x15728E5A,
5467 +       0x98FA0510,
5468 +       0x15D22618,
5469 +       0xEA956AE5,
5470 +       0x3995497C,
5471 +       0x95581718,
5472 +       0xDE2BCBF6,
5473 +       0x6F4C52C9,
5474 +       0xB5C55DF0,
5475 +       0xEC07A28F,
5476 +       0x9B2783A2,
5477 +       0x180E8603,
5478 +       0xE39E772C,
5479 +       0x2E36CE3B,
5480 +       0x32905E46,
5481 +       0xCA18217C,
5482 +       0xF1746C08,
5483 +       0x4ABC9804,
5484 +       0x670C354E,
5485 +       0x7096966D,
5486 +       0x9ED52907,
5487 +       0x208552BB,
5488 +       0x1C62F356,
5489 +       0xDCA3AD96,
5490 +       0x83655D23,
5491 +       0xFD24CF5F,
5492 +       0x69163FA8,
5493 +       0x1C55D39A,
5494 +       0x98DA4836,
5495 +       0xA163BF05,
5496 +       0xC2007CB8,
5497 +       0xECE45B3D,
5498 +       0x49286651,
5499 +       0x7C4B1FE6,
5500 +       0xAE9F2411,
5501 +       0x5A899FA5,
5502 +       0xEE386BFB,
5503 +       0xF406B7ED,
5504 +       0x0BFF5CB6,
5505 +       0xA637ED6B,
5506 +       0xF44C42E9,
5507 +       0x625E7EC6,
5508 +       0xE485B576,
5509 +       0x6D51C245,
5510 +       0x4FE1356D,
5511 +       0xF25F1437,
5512 +       0x302B0A6D,
5513 +       0xCD3A431B,
5514 +       0xEF9519B3,
5515 +       0x8E3404DD,
5516 +       0x514A0879,
5517 +       0x3B139B22,
5518 +       0x020BBEA6,
5519 +       0x8A67CC74,
5520 +       0x29024E08,
5521 +       0x80DC1CD1,
5522 +       0xC4C6628B,
5523 +       0x2168C234,
5524 +       0xC90FDAA2,
5525 +       0xFFFFFFFF,
5526 +       0xFFFFFFFF,
5527 +};
5528 +
5529 +static __u32 dh_a[] = {
5530 +       8,
5531 +       0xdf367516,
5532 +       0x86459caa,
5533 +       0xe2d459a4,
5534 +       0xd910dae0,
5535 +       0x8a8b5e37,
5536 +       0x67ab31c6,
5537 +       0xf0b55ea9,
5538 +       0x440051d6,
5539 +};
5540 +
5541 +static __u32 dh_b[] = {
5542 +       8,
5543 +       0xded92656,
5544 +       0xe07a048a,
5545 +       0x6fa452cd,
5546 +       0x2df89d30,
5547 +       0xc75f1b0f,
5548 +       0x8ce3578f, 
5549 +       0x7980a324,
5550 +       0x5daec786,
5551 +};
5552 +
5553 +static __u32 dh_g[] = {
5554 +       1,
5555 +       2,
5556 +};
5557 +
5558 +int main(void)
5559 +{
5560 +       int i;
5561 +       __u32 *k;
5562 +       k = modpow(dh_g, dh_a, dh_p);
5563 +
5564 +       printf("\n\n");
5565 +       for (i=0; i<k[0]; i++) {
5566 +               __u32 word32 = k[k[0] - i];
5567 +               __u16 l = word32 & 0xffff;
5568 +               __u16 m = (word32 & 0xffff0000) >> 16;
5569 +               printf("%04x %04x ", m, l);
5570 +               if (!((i + 1)%13)) printf("\n");
5571 +       }
5572 +       printf("\n\n");
5573 +
5574 +       if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {
5575 +               printf("PASS\n\n");
5576 +       }
5577 +       else {
5578 +               printf("FAIL\n\n");
5579 +       }
5580 +
5581 +}
5582 +
5583 +#endif /* UNITTEST */
5584 +
5585 +#endif /* CONFIG_MACH_IPMATE */
5586 --- /dev/null
5587 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h
5588 @@ -0,0 +1,26 @@
5589 +/*
5590 + * dwc_modpow.h
5591 + * See dwc_modpow.c for license and changes
5592 + */
5593 +#ifndef _DWC_MODPOW_H
5594 +#define _DWC_MODPOW_H
5595 +
5596 +#include "dwc_os.h"
5597 +
5598 +/** @file
5599 + *
5600 + * This file defines the module exponentiation function which is only used
5601 + * internally by the DWC UWB modules for calculation of PKs during numeric
5602 + * association.  The routine is taken from the PUTTY, an open source terminal
5603 + * emulator.  The PUTTY License is preserved in the dwc_modpow.c file.
5604 + *
5605 + */
5606 +
5607 +typedef uint32_t BignumInt;
5608 +typedef uint64_t BignumDblInt;
5609 +typedef BignumInt *Bignum;
5610 +
5611 +/* Compute modular exponentiaion */
5612 +extern Bignum dwc_modpow(Bignum base_in, Bignum exp, Bignum mod);
5613 +
5614 +#endif /* _LINUX_BIGNUM_H */
5615 --- /dev/null
5616 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c
5617 @@ -0,0 +1,256 @@
5618 +#include "dwc_notifier.h"
5619 +#include "dwc_list.h"
5620 +
5621 +typedef struct dwc_observer
5622 +{
5623 +       void *observer;
5624 +       dwc_notifier_callback_t callback;
5625 +       void *data;
5626 +       char *notification;
5627 +       DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;
5628 +} observer_t;
5629 +
5630 +DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);
5631 +
5632 +typedef struct dwc_notifier
5633 +{
5634 +       void *object;
5635 +       struct observer_queue observers;
5636 +       DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;
5637 +} notifier_t;
5638 +
5639 +DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);
5640 +
5641 +typedef struct manager
5642 +{
5643 +       dwc_workq_t *wq;
5644 +       dwc_mutex_t *mutex;
5645 +       struct notifier_queue notifiers;
5646 +} manager_t;
5647 +
5648 +static manager_t *manager = NULL;
5649 +
5650 +static void create_manager(void)
5651 +{
5652 +       manager = DWC_ALLOC(sizeof(manager_t));
5653 +       DWC_CIRCLEQ_INIT(&manager->notifiers);
5654 +       manager->wq = DWC_WORKQ_ALLOC("DWC Notification WorkQ");
5655 +}
5656 +
5657 +static void free_manager(void)
5658 +{
5659 +       DWC_WORKQ_FREE(manager->wq);
5660 +       /* All notifiers must have unregistered themselves before this module
5661 +        * can be removed.  Hitting this assertion indicates a programmer
5662 +        * error. */
5663 +       DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), "Notification manager being freed before all notifiers have been removed");
5664 +       DWC_FREE(manager);
5665 +}
5666 +
5667 +#ifdef DEBUG
5668 +static void dump_manager(void)
5669 +{
5670 +       notifier_t *n;
5671 +       observer_t *o;
5672 +       DWC_ASSERT(manager, "Notification manager not found");
5673 +       DWC_DEBUG("List of all notifiers and observers:");
5674 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
5675 +               DWC_DEBUG("Notifier %p has observers:", n->object);
5676 +               DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {
5677 +                       DWC_DEBUG("    %p watching %s", o->observer, o->notification);
5678 +               }
5679 +       }
5680 +}
5681 +#else
5682 +#define dump_manager(...)
5683 +#endif
5684 +
5685 +static observer_t *alloc_observer(void *observer, char *notification, dwc_notifier_callback_t callback, void *data)
5686 +{
5687 +       observer_t *new_observer = DWC_ALLOC(sizeof(observer_t));
5688 +       DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);
5689 +       new_observer->observer = observer;
5690 +       new_observer->notification = notification;
5691 +       new_observer->callback = callback;
5692 +       new_observer->data = data;
5693 +       return new_observer;
5694 +}
5695 +
5696 +static void free_observer(observer_t *observer)
5697 +{
5698 +       DWC_FREE(observer);
5699 +}
5700 +
5701 +static notifier_t *alloc_notifier(void *object)
5702 +{
5703 +       notifier_t *notifier;
5704 +
5705 +       if (!object) {
5706 +               return NULL;
5707 +       }
5708 +
5709 +       notifier = DWC_ALLOC(sizeof(notifier_t));
5710 +       DWC_CIRCLEQ_INIT(&notifier->observers);
5711 +       DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);
5712 +
5713 +       notifier->object = object;
5714 +       return notifier;
5715 +}
5716 +
5717 +static void free_notifier(notifier_t *notifier)
5718 +{
5719 +       observer_t *observer;
5720 +       DWC_CIRCLEQ_FOREACH(observer, &notifier->observers, list_entry) {
5721 +               free_observer(observer);
5722 +       }
5723 +       DWC_FREE(notifier);
5724 +}
5725 +
5726 +static notifier_t *find_notifier(void *object)
5727 +{
5728 +       notifier_t *notifier;
5729 +       if (!object) {
5730 +               return NULL;
5731 +       }
5732 +       DWC_ASSERT(manager, "Notification manager not found");
5733 +       DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {
5734 +               if (notifier->object == object) {
5735 +                       return notifier;
5736 +               }
5737 +       }
5738 +       return NULL;
5739 +}
5740 +
5741 +void dwc_alloc_notification_manager(void)
5742 +{
5743 +       create_manager();
5744 +}
5745 +
5746 +void dwc_free_notification_manager(void)
5747 +{
5748 +       free_manager();
5749 +}
5750 +
5751 +dwc_notifier_t *dwc_register_notifier(void *object)
5752 +{
5753 +       notifier_t *notifier = find_notifier(object);
5754 +       DWC_ASSERT(manager, "Notification manager not found");
5755 +       if (notifier) {
5756 +               DWC_ERROR("Notifier %p is already registered", object);
5757 +               return NULL;
5758 +       }
5759 +
5760 +       notifier = alloc_notifier(object);
5761 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);
5762 +
5763 +
5764 +       DWC_INFO("Notifier %p registered", object);
5765 +       dump_manager();
5766 +
5767 +       return notifier;
5768 +}
5769 +
5770 +void dwc_unregister_notifier(dwc_notifier_t *notifier)
5771 +{
5772 +       DWC_ASSERT(manager, "Notification manager not found");
5773 +       if (!DWC_CIRCLEQ_EMPTY(&notifier->observers)) {
5774 +               observer_t *o;
5775 +               DWC_ERROR("Notifier %p has active observers when removing", notifier->object);
5776 +               DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
5777 +                       DWC_DEBUG("    %p watching %s", o->observer, o->notification);
5778 +               }
5779 +               DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&notifier->observers), "Notifier %p has active observers when removing", notifier);
5780 +       }
5781 +
5782 +       DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);
5783 +       free_notifier(notifier);
5784 +
5785 +       DWC_INFO("Notifier unregistered");
5786 +       dump_manager();
5787 +}
5788 +
5789 +/* Add an observer to observe the notifier for a particular state, event, or notification. */
5790 +int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *data)
5791 +{
5792 +       notifier_t *notifier = find_notifier(object);
5793 +       observer_t *new_observer;
5794 +       if (!notifier) {
5795 +               DWC_ERROR("Notifier %p is not found when adding observer", object);
5796 +               return -1;
5797 +       }
5798 +
5799 +       new_observer = alloc_observer(observer, notification, callback, data);
5800 +
5801 +       DWC_CIRCLEQ_INSERT_TAIL(&notifier->observers, new_observer, list_entry);
5802 +
5803 +       DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",
5804 +                observer, object, notification, callback, data);
5805 +
5806 +       dump_manager();
5807 +       return 0;
5808 +}
5809 +
5810 +int dwc_remove_observer(void *observer)
5811 +{
5812 +       notifier_t *n;
5813 +       DWC_ASSERT(manager, "Notification manager not found");
5814 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
5815 +               observer_t *o;
5816 +               observer_t *o2;
5817 +               DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {
5818 +                       if (o->observer == observer) {
5819 +                               DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);
5820 +                               DWC_INFO("Removing observer %p from notifier %p watching notification %s:",
5821 +                                        o->observer, n->object, o->notification);
5822 +                               free_observer(o);
5823 +                       }
5824 +               }
5825 +       }
5826 +
5827 +       dump_manager();
5828 +       return 0;
5829 +}
5830 +
5831 +typedef struct callback_data
5832 +{
5833 +       dwc_notifier_callback_t cb;
5834 +       void *observer;
5835 +       void *data;
5836 +       void *object;
5837 +       void *notification;
5838 +       void *notification_data;
5839 +} cb_data_t;
5840 +
5841 +static void cb_task(void *data)
5842 +{
5843 +       cb_data_t *cb = (cb_data_t *)data;
5844 +       cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);
5845 +       DWC_FREE(cb);
5846 +}
5847 +
5848 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)
5849 +{
5850 +       observer_t *o;
5851 +       DWC_ASSERT(manager, "Notification manager not found");
5852 +       DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
5853 +               int len = DWC_STRLEN(notification);
5854 +               if (DWC_STRLEN(o->notification) != len) {
5855 +                       continue;
5856 +               }
5857 +
5858 +               if (DWC_STRNCMP(o->notification, notification, len) == 0) {
5859 +                       cb_data_t *cb_data = DWC_ALLOC(sizeof(cb_data_t));
5860 +                       cb_data->cb = o->callback;
5861 +                       cb_data->observer = o->observer;
5862 +                       cb_data->data = o->data;
5863 +                       cb_data->object = notifier->object;
5864 +                       cb_data->notification = notification;
5865 +                       cb_data->notification_data = notification_data;
5866 +                       DWC_DEBUG("Observer found %p for notification %s", o->observer, notification);
5867 +                       DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,
5868 +                                          "Notify callback from %p for Notification %s, to observer %p",
5869 +                                          cb_data->object, notification, cb_data->observer);
5870 +               }
5871 +       }
5872 +}
5873 +
5874 --- /dev/null
5875 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h
5876 @@ -0,0 +1,112 @@
5877 +
5878 +#ifndef __DWC_NOTIFIER_H__
5879 +#define __DWC_NOTIFIER_H__
5880 +
5881 +#include "dwc_os.h"
5882 +
5883 +/** @file
5884 + *
5885 + * A simple implementation of the Observer pattern.  Any "module" can
5886 + * register as an observer or notifier.  The notion of "module" is abstract and
5887 + * can mean anything used to identify either an observer or notifier.  Usually
5888 + * it will be a pointer to a data structure which contains some state, ie an
5889 + * object.
5890 + *
5891 + * Before any notifiers can be added, the global notification manager must be
5892 + * brought up with dwc_alloc_notification_manager().
5893 + * dwc_free_notification_manager() will bring it down and free all resources.
5894 + * These would typically be called upon module load and unload.  The
5895 + * notification manager is a single global instance that handles all registered
5896 + * observable modules and observers so this should be done only once.
5897 + *
5898 + * A module can be observable by using Notifications to publicize some general
5899 + * information about it's state or operation.  It does not care who listens, or
5900 + * even if anyone listens, or what they do with the information.  The observable
5901 + * modules do not need to know any information about it's observers or their
5902 + * interface, or their state or data.
5903 + *
5904 + * Any module can register to emit Notifications.  It should publish a list of
5905 + * notifications that it can emit and their behavior, such as when they will get
5906 + * triggered, and what information will be provided to the observer.  Then it
5907 + * should register itself as an observable module. See dwc_register_notifier().
5908 + *
5909 + * Any module can observe any observable, registered module, provided it has a
5910 + * handle to the other module and knows what notifications to observe.  See
5911 + * dwc_add_observer().
5912 + *
5913 + * A function of type dwc_notifier_callback_t is called whenever a notification
5914 + * is triggered with one or more observers observing it.  This function is
5915 + * called in it's own process so it may sleep or block if needed.  It is
5916 + * guaranteed to be called sometime after the notification has occurred and will
5917 + * be called once per each time the notification is triggered.  It will NOT be
5918 + * called in the same process context used to trigger the notification.
5919 + *
5920 + * @section Limitiations
5921 + *
5922 + * Keep in mind that Notifications that can be triggered in rapid sucession may
5923 + * schedule too many processes too handle.  Be aware of this limitation when
5924 + * designing to use notifications, and only add notifications for appropriate
5925 + * observable information.
5926 + *
5927 + * Also Notification callbacks are not synchronous.  If you need to synchronize
5928 + * the behavior between module/observer you must use other means.  And perhaps
5929 + * that will mean Notifications are not the proper solution.
5930 + */
5931 +
5932 +struct dwc_notifier;
5933 +typedef struct dwc_notifier dwc_notifier_t;
5934 +
5935 +/** The callback function must be of this type.
5936 + *
5937 + * @param object This is the object that is being observed.
5938 + * @param notification This is the notification that was triggered.
5939 + * @param observer This is the observer
5940 + * @param notification_data This is notification-specific data that the notifier
5941 + * has included in this notification.  The value of this should be published in
5942 + * the documentation of the observable module with the notifications.
5943 + * @param user_data This is any custom data that the observer provided when
5944 + * adding itself as an observer to the notification. */
5945 +typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, void *notification_data, void *user_data);
5946 +
5947 +/** Brings up the notification manager. */
5948 +extern void dwc_alloc_notification_manager(void);
5949 +/** Brings down the notification manager. */
5950 +extern void dwc_free_notification_manager(void);
5951 +
5952 +/** This function register an observable module.  A dwc_notifier_t object is
5953 + * returned to the observable module.  This is an opaque object that is used by
5954 + * the observable module to trigger notifications.  This object should only be
5955 + * accessible to functions that are authorized to trigger notifications for this
5956 + * module.  Observers do not need this object. */
5957 +extern dwc_notifier_t *dwc_register_notifier(void *object);
5958 +
5959 +/** This function unregister an observable module.  All observers have to be
5960 + * removed prior to unregistration. */
5961 +extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
5962 +
5963 +/** Add a module as an observer to the observable module.  The observable module
5964 + * needs to have previously registered with the notification manager.
5965 + *
5966 + * @param observer The observer module
5967 + * @param object The module to observe
5968 + * @param notification The notification to observe
5969 + * @param callback The callback function to call
5970 + * @param user_data Any additional user data to pass into the callback function */
5971 +extern int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *user_data);
5972 +
5973 +/** Removes the specified observer from all notifications that it is currently
5974 + * observing. */
5975 +extern int dwc_remove_observer(void *observer);
5976 +
5977 +/** This function triggers a Notification.  It should be called by the
5978 + * observable module, or any module or library which the observable module
5979 + * allows to trigger notification on it's behalf.  Such as the dwc_cc_t.
5980 + *
5981 + * dwc_notify is a non-blocking function.  Callbacks are scheduled called in
5982 + * their own process context for each trigger.  Callbacks can be blocking.
5983 + * dwc_notify can be called from interrupt context if needed.
5984 + *
5985 + */
5986 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
5987 +
5988 +#endif /* __DWC_NOTIFIER_H__ */
5989 --- /dev/null
5990 +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
5991 @@ -0,0 +1,924 @@
5992 +/* =========================================================================
5993 + * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_os.h $
5994 + * $Revision: #2 $
5995 + * $Date: 2009/04/02 $
5996 + * $Change: 1224130 $
5997 + *
5998 + * Synopsys Portability Library Software and documentation
5999 + * (hereinafter, "Software") is an Unsupported proprietary work of
6000 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
6001 + * between Synopsys and you.
6002 + *
6003 + * The Software IS NOT an item of Licensed Software or Licensed Product
6004 + * under any End User Software License Agreement or Agreement for
6005 + * Licensed Product with Synopsys or any supplement thereto. You are
6006 + * permitted to use and redistribute this Software in source and binary
6007 + * forms, with or without modification, provided that redistributions
6008 + * of source code must retain this notice. You may not view, use,
6009 + * disclose, copy or distribute this file or any information contained
6010 + * herein except pursuant to this license grant from Synopsys. If you
6011 + * do not agree with this notice, including the disclaimer below, then
6012 + * you are not authorized to use the Software.
6013 + *
6014 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
6015 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6016 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
6017 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
6018 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
6019 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
6020 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
6021 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
6022 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6023 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
6024 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
6025 + * DAMAGE.
6026 + * ========================================================================= */
6027 +#ifndef _DWC_OS_H_
6028 +#define _DWC_OS_H_
6029 +
6030 +/** @file
6031 + *
6032 + * DWC portability library, low level os-wrapper functions
6033 + *
6034 + */
6035 +
6036 +/* These basic types need to be defined by some OS header file or custom header
6037 + * file for your specific target architecture.
6038 + *
6039 + * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
6040 + *
6041 + * Any custom or alternate header file must be added and enabled here.
6042 + */
6043 +
6044 +#ifdef DWC_LINUX
6045 +#  include <linux/types.h>
6046 +#  ifdef CONFIG_DEBUG_MUTEXES
6047 +#    include <linux/mutex.h>
6048 +#  endif
6049 +#else
6050 +#  include <stdint.h>
6051 +#endif
6052 +
6053 +
6054 +/** @name Primitive Types and Values */
6055 +
6056 +/** We define a boolean type for consistency.  Can be either YES or NO */
6057 +typedef uint8_t dwc_bool_t;
6058 +#define YES  1
6059 +#define NO   0
6060 +
6061 +/** @todo make them positive and return the negative error code */
6062 +/** @name Error Codes */
6063 +#define DWC_E_INVALID         1001
6064 +#define DWC_E_NO_MEMORY       1002
6065 +#define DWC_E_NO_DEVICE       1003
6066 +#define DWC_E_NOT_SUPPORTED   1004
6067 +#define DWC_E_TIMEOUT         1005
6068 +#define DWC_E_BUSY            1006
6069 +#define DWC_E_AGAIN           1007
6070 +#define DWC_E_RESTART         1008
6071 +#define DWC_E_ABORT           1009
6072 +#define DWC_E_SHUTDOWN        1010
6073 +#define DWC_E_NO_DATA         1011
6074 +#define DWC_E_DISCONNECT      2000
6075 +#define DWC_E_UNKNOWN         3000
6076 +#define DWC_E_NO_STREAM_RES   4001
6077 +#define DWC_E_COMMUNICATION   4002
6078 +#define DWC_E_OVERFLOW        4003
6079 +#define DWC_E_PROTOCOL        4004
6080 +#define DWC_E_IN_PROGRESS     4005
6081 +#define DWC_E_PIPE            4006
6082 +#define DWC_E_IO              4007
6083 +#define DWC_E_NO_SPACE        4008
6084 +
6085 +/** @name Tracing/Logging Functions
6086 + *
6087 + * These function provide the capability to add tracing, debugging, and error
6088 + * messages, as well exceptions as assertions.  The WUDEV uses these
6089 + * extensively.  These could be logged to the main console, the serial port, an
6090 + * internal buffer, etc.  These functions could also be no-op if they are too
6091 + * expensive on your system.  By default undefining the DEBUG macro already
6092 + * no-ops some of these functions. */
6093 +
6094 +#include <stdarg.h>
6095 +
6096 +/** Returns non-zero if in interrupt context. */
6097 +extern dwc_bool_t DWC_IN_IRQ(void);
6098 +#define dwc_in_irq DWC_IN_IRQ
6099 +
6100 +/** Returns "IRQ" if DWC_IN_IRQ is true. */
6101 +static inline char *dwc_irq(void) {
6102 +       return DWC_IN_IRQ() ? "IRQ" : "";
6103 +}
6104 +
6105 +/**
6106 + * A vprintf() clone.  Just call vprintf if you've got it.
6107 + */
6108 +extern void DWC_VPRINTF(char *format, va_list args);
6109 +#define dwc_vprintf DWC_VPRINTF
6110 +
6111 +/**
6112 + * A vsnprintf() clone.  Just call vprintf if you've got it.
6113 + */
6114 +extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
6115 +#define dwc_vsnprintf DWC_VSNPRINTF
6116 +
6117 +/**
6118 + * printf() clone.  Just call printf if you've go it.
6119 + */
6120 +extern void DWC_PRINTF(char *format, ...)
6121 +/* This provides compiler level static checking of the parameters if you're
6122 + * using GCC. */
6123 +#ifdef __GNUC__
6124 +       __attribute__ ((format(printf, 1, 2)));
6125 +#else
6126 +  ;
6127 +#endif
6128 +#define dwc_printf DWC_PRINTF
6129 +
6130 +/**
6131 + * sprintf() clone.  Just call sprintf if you've got it.
6132 + */
6133 +extern int DWC_SPRINTF(char *string, char *format, ...)
6134 +#ifdef __GNUC__
6135 +     __attribute__ ((format(printf, 2, 3)));
6136 +#else
6137 +     ;
6138 +#endif
6139 +#define dwc_sprintf DWC_SPRINTF
6140 +
6141 +/**
6142 + * snprintf() clone.  Just call snprintf if you've got it.
6143 + */
6144 +extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
6145 +#ifdef __GNUC__
6146 +     __attribute__ ((format(printf, 3, 4)));
6147 +#else
6148 +     ;
6149 +#endif
6150 +#define dwc_snprintf DWC_SNPRINTF
6151 +
6152 +/**
6153 + * Prints a WARNING message.  On systems that don't differentiate between
6154 + * warnings and regular log messages, just print it.  Indicates that something
6155 + * may be wrong with the driver.  Works like printf().
6156 + *
6157 + * Use the DWC_WARN macro to call this function.
6158 + */
6159 +extern void __DWC_WARN(char *format, ...)
6160 +#ifdef __GNUC__
6161 +     __attribute__ ((format(printf, 1, 2)));
6162 +#else
6163 +     ;
6164 +#endif
6165 +
6166 +/**
6167 + * Prints an error message.  On systems that don't differentiate between errors
6168 + * and regular log messages, just print it.  Indicates that something went wrong
6169 + * with the driver, but it can be recovered from.  Works like printf().
6170 + *
6171 + * Use the DWC_ERROR macro to call this function.
6172 + */
6173 +extern void __DWC_ERROR(char *format, ...)
6174 +#ifdef __GNUC__
6175 +     __attribute__ ((format(printf, 1, 2)));
6176 +#else
6177 +     ;
6178 +#endif
6179 +
6180 +/**
6181 + * Prints an exception error message and takes some user-defined action such as
6182 + * print out a backtrace or trigger a breakpoint.  Indicates that something went
6183 + * abnormally wrong with the driver such as programmer error, or other
6184 + * exceptional condition.  It should not be ignored so even on systems without
6185 + * printing capability, some action should be taken to notify the developer of
6186 + * it.  Works like printf().
6187 + */
6188 +extern void DWC_EXCEPTION(char *format, ...)
6189 +#ifdef __GNUC__
6190 +     __attribute__ ((format(printf, 1, 2)));
6191 +#else
6192 +     ;
6193 +#endif
6194 +#define dwc_exception DWC_EXCEPTION
6195 +
6196 +#ifdef DEBUG
6197 +/**
6198 + * Prints out a debug message.  Used for logging/trace messages.
6199 + *
6200 + * Use the DWC_DEBUG macro to call this function
6201 + */
6202 +extern void __DWC_DEBUG(char *format, ...)
6203 +#ifdef __GNUC__
6204 +     __attribute__ ((format(printf, 1, 2)));
6205 +#else
6206 +     ;
6207 +#endif
6208 +#else
6209 +#define __DWC_DEBUG printk
6210 +#endif
6211 +
6212 +/**
6213 + * Prints out a Debug message.
6214 + */
6215 +#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", __func__, dwc_irq(), ## _args)
6216 +#define dwc_debug DWC_DEBUG
6217 +/**
6218 + * Prints out an informative message.
6219 + */
6220 +#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", dwc_irq(), ## _args)
6221 +#define dwc_info DWC_INFO
6222 +/**
6223 + * Prints out a warning message.
6224 + */
6225 +#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args)
6226 +#define dwc_warn DWC_WARN
6227 +/**
6228 + * Prints out an error message.
6229 + */
6230 +#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args)
6231 +#define dwc_error DWC_ERROR
6232 +
6233 +#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args)
6234 +#define dwc_proto_error DWC_PROTO_ERROR
6235 +
6236 +#ifdef DEBUG
6237 +/** Prints out a exception error message if the _expr expression fails.  Disabled
6238 + * if DEBUG is not enabled. */
6239 +#define DWC_ASSERT(_expr, _format, _args...) if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), __FILE__, __LINE__, ## _args); }
6240 +#else
6241 +#define DWC_ASSERT(_x...)
6242 +#endif
6243 +#define dwc_assert DWC_ASSERT
6244 +
6245 +/** @name Byter Ordering
6246 + * The following functions are for conversions between processor's byte ordering
6247 + * and specific ordering you want.
6248 + */
6249 +
6250 +/** Converts 32 bit data in CPU byte ordering to little endian. */
6251 +extern uint32_t DWC_CPU_TO_LE32(void *p);
6252 +#define dwc_cpu_to_le32 DWC_CPU_TO_LE32
6253 +/** Converts 32 bit data in CPU byte orderint to big endian. */
6254 +extern uint32_t DWC_CPU_TO_BE32(void *p);
6255 +#define dwc_cpu_to_be32 DWC_CPU_TO_BE32
6256 +
6257 +/** Converts 32 bit little endian data to CPU byte ordering. */
6258 +extern uint32_t DWC_LE32_TO_CPU(void *p);
6259 +#define dwc_le32_to_cpu DWC_LE32_TO_CPU
6260 +/** Converts 32 bit big endian data to CPU byte ordering. */
6261 +extern uint32_t DWC_BE32_TO_CPU(void *p);
6262 +#define dwc_be32_to_cpu DWC_BE32_TO_CPU
6263 +
6264 +/** Converts 16 bit data in CPU byte ordering to little endian. */
6265 +extern uint16_t DWC_CPU_TO_LE16(void *p);
6266 +#define dwc_cpu_to_le16 DWC_CPU_TO_LE16
6267 +/** Converts 16 bit data in CPU byte orderint to big endian. */
6268 +extern uint16_t DWC_CPU_TO_BE16(void *p);
6269 +#define dwc_cpu_to_be16 DWC_CPU_TO_BE16
6270 +
6271 +/** Converts 16 bit little endian data to CPU byte ordering. */
6272 +extern uint16_t DWC_LE16_TO_CPU(void *p);
6273 +#define dwc_le16_to_cpu DWC_LE16_TO_CPU
6274 +/** Converts 16 bit bi endian data to CPU byte ordering. */
6275 +extern uint16_t DWC_BE16_TO_CPU(void *p);
6276 +#define dwc_be16_to_cpu DWC_BE16_TO_CPU
6277 +
6278 +/** @name Register Read/Write
6279 + *
6280 + * The following five functions should be implemented to read/write registers of
6281 + * 32-bit and 64-bit sizes.  All modules use this to read/write register values.
6282 + * The reg value is a pointer to the register calculated from the void *base
6283 + * variable passed into the driver when it is started.  */
6284 +
6285 +/** Reads the content of a 32-bit register. */
6286 +extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
6287 +#define dwc_read_reg32 DWC_READ_REG32
6288 +/** Reads the content of a 64-bit register. */
6289 +extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
6290 +#define dwc_read_reg64 DWC_READ_REG64
6291 +/** Writes to a 32-bit register. */
6292 +extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
6293 +#define dwc_write_reg32 DWC_WRITE_REG32
6294 +/** Writes to a 64-bit register. */
6295 +extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
6296 +#define dwc_write_reg64 DWC_WRITE_REG64
6297 +/**  
6298 + * Modify bit values in a register.  Using the
6299 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
6300 + */
6301 +extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
6302 +#define dwc_modify_reg32 DWC_MODIFY_REG32
6303 +
6304 +/** @cond */
6305 +
6306 +/** @name Some convenience MACROS used internally.  Define DEBUG_REGS to log the
6307 + * register writes. */
6308 +
6309 +#ifdef DEBUG_REGS
6310 +
6311 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
6312 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
6313 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
6314 +} \
6315 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
6316 +        DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, &(((uint32_t*)container->regs->_reg)[num]), data); \
6317 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
6318 +}
6319 +
6320 +#define dwc_define_read_write_reg(_reg,_container_type) \
6321 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
6322 +       return DWC_READ_REG32(&container->regs->_reg); \
6323 +} \
6324 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
6325 +        DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
6326 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
6327 +}
6328 +
6329 +#else
6330 +
6331 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
6332 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
6333 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
6334 +} \
6335 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
6336 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
6337 +}
6338 +
6339 +#define dwc_define_read_write_reg(_reg,_container_type) \
6340 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
6341 +       return DWC_READ_REG32(&container->regs->_reg); \
6342 +} \
6343 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
6344 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
6345 +}
6346 +
6347 +#endif
6348 +
6349 +/** @endcond */
6350 +
6351 +
6352 +/** @name Crypto Functions
6353 + *
6354 + * These are the low-level cryptographic functions used by the driver. */
6355 +
6356 +/** Perform AES CBC */
6357 +extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
6358 +#define dwc_aes_cbc DWC_AES_CBC
6359 +/** Fill the provided buffer with random bytes.  These should be cryptographic grade random numbers. */
6360 +extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
6361 +#define dwc_random_bytes DWC_RANDOM_BYTES
6362 +/** Perform the SHA-256 hash function */
6363 +extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
6364 +#define dwc_sha256 DWC_SHA256
6365 +/** Calculated the HMAC-SHA256 */
6366 +extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
6367 +#define dwc_hmac_sha256 DWC_HMAC_SHA256
6368 +
6369 +
6370 +/** @name Memory Allocation
6371 + *
6372 + * These function provide access to memory allocation.  There are only 2 DMA
6373 + * functions and 3 Regular memory functions that need to be implemented.  None
6374 + * of the memory debugging routines need to be implemented.  The allocation
6375 + * routines all ZERO the contents of the memory.
6376 + *
6377 + * Defining DEBUG_MEMORY turns on memory debugging and statistic gathering.
6378 + * This checks for memory leaks, keeping track of alloc/free pairs.  It also
6379 + * keeps track of how much memory the driver is using at any given time. */
6380 +
6381 +#define DWC_PAGE_SIZE 4096
6382 +#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
6383 +#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
6384 +
6385 +#define DWC_INVALID_DMA_ADDR 0x0
6386 +
6387 +typedef uint32_t dwc_dma_t;
6388 +
6389 +/** @todo these functions will be added in the future */
6390 +#if 0
6391 +/**
6392 + * Creates a DMA pool from which you can allocate DMA buffers.  Buffers
6393 + * allocated from this pool will be guaranteed to meet the size, alignment, and
6394 + * boundary requirements specified.
6395 + *
6396 + * @param[in] size Specifies the size of the buffers that will be allocated from
6397 + * this pool.
6398 + * @param[in] align Specifies the byte alignment requirements of the buffers
6399 + * allocated from this pool.  Must be a power of 2.
6400 + * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
6401 + * this pool must not cross.
6402 + *
6403 + * @returns A pointer to an internal opaque structure which is not to be
6404 + * accessed outside of these library functions.  Use this handle to specify
6405 + * which pools to allocate/free DMA buffers from and also to destroy the pool,
6406 + * when you are done with it.
6407 + */
6408 +extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
6409 +/**
6410 + * Destroy a DMA pool.  All buffers allocated from that pool must be freed first.
6411 + */
6412 +extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
6413 +/**
6414 + * Allocate a buffer from the specified DMA pool and zeros its contents.
6415 + */
6416 +extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
6417 +/**
6418 + * Free a previously allocated buffer from the DMA pool.
6419 + */
6420 +extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
6421 +#endif
6422 +
6423 +
6424 +/** Allocates a DMA capable buffer and zeroes its contents. */
6425 +extern void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr);
6426 +
6427 +/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
6428 +extern void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr);
6429 +
6430 +/** Frees a previosly allocated buffer. */
6431 +extern void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
6432 +
6433 +/** Allocates a block of memory and zeroes its contents. */
6434 +extern void *__DWC_ALLOC(uint32_t size);
6435 +
6436 +/** Allocates a block of memory and zeroes its contents, in an atomic manner
6437 + * which can be used inside interrupt context.  The size should be sufficiently
6438 + * small, a few KB at most, such that failures are not likely to occur.  Can just call
6439 + * __DWC_ALLOC if it is atomic. */
6440 +extern void *__DWC_ALLOC_ATOMIC(uint32_t size);
6441 +
6442 +/** Frees a previously allocated buffer. */
6443 +extern void __DWC_FREE(void *addr);
6444 +
6445 +#ifndef DEBUG_MEMORY
6446 +
6447 +#define DWC_ALLOC(_size_) __DWC_ALLOC(_size_)
6448 +#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(_size_)
6449 +#define DWC_FREE(_addr_) __DWC_FREE(_addr_)
6450 +#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(_size_,_dma_)
6451 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(_size_,_dma_)
6452 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(_size_,_virt_,_dma_)
6453 +
6454 +#else
6455 +
6456 +extern void *dwc_alloc_debug(uint32_t size, char const *func, int line);
6457 +extern void *dwc_alloc_atomic_debug(uint32_t size, char const *func, int line);
6458 +extern void dwc_free_debug(void *addr, char const *func, int line);
6459 +extern void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
6460 +extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
6461 +extern void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line);
6462 +
6463 +extern void dwc_memory_debug_start(void);
6464 +extern void dwc_memory_debug_stop(void);
6465 +extern void dwc_memory_debug_report(void);
6466 +
6467 +#define DWC_ALLOC(_size_) (dwc_alloc_debug(_size_, __func__, __LINE__))
6468 +#define DWC_ALLOC_ATOMIC(_size_) (dwc_alloc_atomic_debug(_size_, __func__, __LINE__))
6469 +#define DWC_FREE(_addr_) (dwc_free_debug(_addr_, __func__, __LINE__))
6470 +#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(_size_, _dma_, __func__, __LINE__)
6471 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(_size_, _dma_, __func__, __LINE__)
6472 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(_size_, _virt_, _dma_, __func__, __LINE__)
6473 +
6474 +#endif /* DEBUG_MEMORY */
6475 +
6476 +#define dwc_alloc DWC_ALLOC
6477 +#define dwc_alloc_atomic DWC_ALLOC_ATOMIC
6478 +#define dwc_free DWC_FREE
6479 +#define dwc_dma_alloc DWC_DMA_ALLOC
6480 +#define dwc_dma_alloc_atomic DWC_DMA_ALLOC_ATOMIC
6481 +#define dwc_dma_free DWC_DMA_FREE
6482 +
6483 +
6484 +/** @name Memory and String Processing */
6485 +
6486 +/** memset() clone */
6487 +extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
6488 +#define dwc_memset DWC_MEMSET
6489 +/** memcpy() clone */
6490 +extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
6491 +#define dwc_memcpy DWC_MEMCPY
6492 +/** memmove() clone */
6493 +extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
6494 +#define dwc_memmove DWC_MEMMOVE
6495 +/** memcmp() clone */
6496 +extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
6497 +#define dwc_memcmp DWC_MEMCMP
6498 +/** strcmp() clone */
6499 +extern int DWC_STRCMP(void *s1, void *s2);
6500 +#define dwc_strcmp DWC_STRCMP
6501 +/** strncmp() clone */
6502 +extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
6503 +#define dwc_strncmp DWC_STRNCMP
6504 +/** strlen() clone, for NULL terminated ASCII strings */
6505 +extern int DWC_STRLEN(char const *str);
6506 +#define dwc_strlen DWC_STRLEN
6507 +/** strcpy() clone, for NULL terminated ASCII strings */
6508 +extern char *DWC_STRCPY(char *to, const char *from);
6509 +#define dwc_strcpy DWC_STRCPY
6510 +
6511 +/** strdup() clone.  If you wish to use memory allocation debugging, this
6512 + * implementation of strdup should use the DWC_* memory routines instead of
6513 + * calling a predefined strdup.  Otherwise the memory allocated by this routine
6514 + * will not be seen by the debugging routines. */
6515 +extern char *DWC_STRDUP(char const *str);
6516 +#define dwc_strdup DWC_STRDUP
6517 +
6518 +/** NOT an atoi() clone.  Read the description carefully.  Returns an integer
6519 + * converted from the string str in base 10 unless the string begins with a "0x"
6520 + * in which case it is base 16.  String must be a NULL terminated sequence of
6521 + * ASCII characters and may optionally begin with whitespace, a + or -, and a
6522 + * "0x" prefix if base 16.  The remaining characters must be valid digits for
6523 + * the number and end with a NULL character.  If any invalid characters are
6524 + * encountered or it returns with a negative error code and the results of the
6525 + * conversion are undefined.  On sucess it returns 0.  Overflow conditions are
6526 + * undefined.  An example implementation using atoi() can be referenced from the
6527 + * Linux implementation. */
6528 +extern int DWC_ATOI(char *str, int32_t *value);
6529 +#define dwc_atoi DWC_ATOI
6530 +/** Same as above but for unsigned. */
6531 +extern int DWC_ATOUI(char *str, uint32_t *value);
6532 +#define dwc_atoui DWC_ATOUI
6533 +/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
6534 +extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
6535 +#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
6536 +
6537 +/** @name Wait queues
6538 + *
6539 + * Wait queues provide a means of synchronizing between threads or processes.  A
6540 + * process can block on a waitq if some condition is not true, waiting for it to
6541 + * become true.  When the waitq is triggered all waiting process will get
6542 + * unblocked and the condition will be check again.  Waitqs should be triggered
6543 + * every time a condition can potentially change.*/
6544 +struct dwc_waitq;
6545 +typedef struct dwc_waitq dwc_waitq_t;
6546 +
6547 +/** The type of waitq condition callback function.  This is called every time
6548 + * condition is evaluated. */
6549 +typedef int (*dwc_waitq_condition_t)(void *data);
6550 +
6551 +/** Allocate a waitq */
6552 +extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
6553 +#define dwc_waitq_alloc DWC_WAITQ_ALLOC
6554 +/** Free a waitq */
6555 +extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
6556 +#define dwc_waitq_free DWC_WAITQ_FREE
6557 +
6558 +/** Check the condition and if it is false, block on the waitq.  When unblocked, check the
6559 + * condition again.  The function returns when the condition becomes true.  The return value
6560 + * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
6561 +extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data);
6562 +#define dwc_waitq_wait DWC_WAITQ_WAIT;
6563 +/** Check the condition and if it is false, block on the waitq.  When unblocked,
6564 + * check the condition again.  The function returns when the condition become
6565 + * true or the timeout has passed.  The return value is 0 on condition true or
6566 + * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
6567 + * error. */
6568 +extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data, int32_t msecs);
6569 +#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
6570 +/** Trigger a waitq, unblocking all processes.  This should be called whenever a condition
6571 + * has potentially changed. */
6572 +extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
6573 +#define dwc_waitq_trigger DWC_WAITQ_TRIGGER
6574 +/** Unblock all processes waiting on the waitq with an ABORTED result. */
6575 +extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
6576 +#define dwc_waitq_abort DWC_WAITQ_ABORT
6577 +
6578 +/** @name Threads
6579 + *
6580 + * A thread must be explicitly stopped.  It must check DWC_THREAD_SHOULD_STOP
6581 + * whenever it is woken up, and then return.  The DWC_THREAD_STOP function
6582 + * returns the value from the thread.
6583 + */
6584 +
6585 +struct dwc_thread;
6586 +typedef struct dwc_thread dwc_thread_t;
6587 +
6588 +/** The thread function */
6589 +typedef int (*dwc_thread_function_t)(void *data);
6590 +
6591 +/** Create a thread and start it running the thread_function.  Returns a handle
6592 + * to the thread */
6593 +extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data);
6594 +#define dwc_thread_run DWC_THREAD_RUN
6595 +/** Stops a thread.  Return the value returned by the thread.  Or will return
6596 + * DWC_ABORT if the thread never started. */
6597 +extern int DWC_THREAD_STOP(dwc_thread_t *thread);
6598 +#define dwc_thread_stop DWC_THREAD_STOP
6599 +/** Signifies to the thread that it must stop. */
6600 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
6601 +#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
6602 +
6603 +/** @name Work queues
6604 + *
6605 + * Workqs are used to queue a callback function to be called at some later time,
6606 + * in another thread. */
6607 +struct dwc_workq;
6608 +typedef struct dwc_workq dwc_workq_t;
6609 +
6610 +/** The type of the callback function to be called. */
6611 +typedef void (*dwc_work_callback_t)(void *data);
6612 +
6613 +/** Allocate a workq */
6614 +extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
6615 +#define dwc_workq_alloc DWC_WORKQ_ALLOC
6616 +/** Free a workq.  All work must be completed before being freed. */
6617 +extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
6618 +#define dwc_workq_free DWC_WORKQ_FREE
6619 +/** Schedule a callback on the workq, passing in data.  The function will be
6620 + * scheduled at some later time. */
6621 +extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, char *format, ...)
6622 +#ifdef __GNUC__
6623 +       __attribute__ ((format(printf, 4, 5)));
6624 +#else
6625 +  ;
6626 +#endif
6627 +#define dwc_workq_schedule DWC_WORKQ_SCHEDULE
6628 +
6629 +/** Schedule a callback on the workq, that will be called until at least 
6630 + * given number miliseconds have passed. */
6631 +extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...)
6632 +#ifdef __GNUC__
6633 +       __attribute__ ((format(printf, 5, 6)));
6634 +#else
6635 +  ;
6636 +#endif
6637 +#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
6638 +
6639 +/** The number of processes in the workq */
6640 +extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
6641 +#define dwc_workq_pending DWC_WORKQ_PENDING
6642 +/** Blocks until all the work in the workq is complete or timed out.  Returns <
6643 + * 0 on timeout. */
6644 +extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
6645 +#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
6646 +
6647 +
6648 +/** @name Tasklets
6649 + *
6650 + */
6651 +struct dwc_tasklet;
6652 +typedef struct dwc_tasklet dwc_tasklet_t;
6653 +
6654 +typedef void (*dwc_tasklet_callback_t)(void *data);
6655 +
6656 +extern dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data);
6657 +#define dwc_task_alloc DWC_TASK_ALLOC
6658 +extern void DWC_TASK_FREE(dwc_tasklet_t *t);
6659 +#define dwc_task_free DWC_TASK_FREE
6660 +extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
6661 +#define dwc_task_schedule DWC_TASK_SCHEDULE
6662 +
6663 +
6664 +/** @name Timer
6665 + *
6666 + * Callbacks must be small and atomic.
6667 + */
6668 +struct dwc_timer;
6669 +typedef struct dwc_timer dwc_timer_t;
6670 +
6671 +typedef void (*dwc_timer_callback_t)(void *data);
6672 +
6673 +extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
6674 +#define dwc_timer_alloc DWC_TIMER_ALLOC
6675 +extern void DWC_TIMER_FREE(dwc_timer_t *timer);
6676 +#define dwc_timer_free DWC_TIMER_FREE
6677 +
6678 +/** Schedules the timer to run at time ms from now.  And will repeat at every
6679 + * repeat_interval msec therafter
6680 + *
6681 + * Modifies a timer that is still awaiting execution to a new expiration time.
6682 + * The mod_time is added to the old time.  */
6683 +extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
6684 +#define dwc_timer_schedule DWC_TIMER_SCHEDULE
6685 +
6686 +/** Disables the timer from execution. */
6687 +extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
6688 +#define dwc_timer_cancel DWC_TIMER_CANCEL
6689 +
6690 +
6691 +
6692 +/** @name Spinlocks
6693 + *
6694 + * These locks are used when the work between the lock/unlock is atomic and
6695 + * short.  Interrupts are also disabled during the lock/unlock and thus they are
6696 + * suitable to lock between interrupt/non-interrupt context.  They also lock
6697 + * between processes if you have multiple CPUs or Preemption.  If you don't have
6698 + * multiple CPUS or Preemption, then the you can simply implement the
6699 + * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts.  Because
6700 + * the work between the lock/unlock is atomic, the process context will never
6701 + * change, and so you never have to lock between processes.  */
6702 +
6703 +struct dwc_spinlock;
6704 +typedef struct dwc_spinlock dwc_spinlock_t;
6705 +
6706 +/** Returns an initialized lock variable.  This function should allocate and
6707 + * initialize the OS-specific data structure used for locking.  This data
6708 + * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
6709 + * be freed by the DWC_FREE_LOCK when it is no longer used. */
6710 +extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
6711 +#define dwc_spinlock_alloc DWC_SPINLOCK_ALLOC
6712 +
6713 +/** Frees an initialized lock variable. */
6714 +extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
6715 +#define dwc_spinlock_free DWC_SPINLOCK_FREE
6716 +
6717 +/** Disables interrupts and blocks until it acquires the lock.
6718 + *
6719 + * @param lock Pointer to the spinlock.
6720 + * @param flags Unsigned long for irq flags storage.
6721 + */
6722 +extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags);
6723 +#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
6724 +
6725 +/** Re-enables the interrupt and releases the lock.
6726 + *
6727 + * @param lock Pointer to the spinlock.
6728 + * @param flags Unsigned long for irq flags storage.  Must be the same as was
6729 + * passed into DWC_LOCK.
6730 + */
6731 +extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags);
6732 +#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
6733 +
6734 +/** Blocks until it acquires the lock.
6735 + *
6736 + * @param lock Pointer to the spinlock.
6737 + */
6738 +extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
6739 +#define dwc_spinlock DWC_SPINLOCK
6740 +
6741 +/** Releases the lock.
6742 + *
6743 + * @param lock Pointer to the spinlock.
6744 + */
6745 +extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
6746 +#define dwc_spinunlock DWC_SPINUNLOCK
6747 +
6748 +/** @name Mutexes
6749 + *
6750 + * Unlike spinlocks Mutexes lock only between processes and the work between the
6751 + * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
6752 + */
6753 +
6754 +struct dwc_mutex;
6755 +typedef struct dwc_mutex dwc_mutex_t;
6756 +
6757 +
6758 +/* For Linux Mutex Debugging make it inline because the debugging routines use
6759 + * the symbol to determine recursive locking.  This makes it falsely think
6760 + * recursive locking occurs. */
6761 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
6762 +#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
6763 +       __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
6764 +       mutex_init((struct mutex *)__mutexp); \
6765 +})
6766 +#endif
6767 +extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
6768 +#define dwc_mutex_alloc DWC_MUTEX_ALLOC
6769 +
6770 +/* For memory leak debugging when using Linux Mutex Debugging */
6771 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
6772 +#define DWC_MUTEX_FREE(__mutexp) do { \
6773 +       mutex_destroy((struct mutex *)__mutexp); \
6774 +       DWC_FREE(__mutexp); \
6775 +} while(0)
6776 +#else
6777 +extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
6778 +#define dwc_mutex_free DWC_MUTEX_FREE
6779 +#endif
6780 +
6781 +extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
6782 +#define dwc_mutex_lock DWC_MUTEX_LOCK
6783 +/** Non-blocking lock returns 1 on successful lock. */
6784 +extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
6785 +#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
6786 +extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
6787 +#define dwc_mutex_unlock DWC_MUTEX_UNLOCK
6788 +
6789 +
6790 +
6791 +
6792 +/** @name Time */
6793 +
6794 +/** Microsecond delay.
6795 + *
6796 + * @param usecs  Microseconds to delay.
6797 + */
6798 +extern void DWC_UDELAY(uint32_t usecs);
6799 +#define dwc_udelay DWC_UDELAY
6800 +
6801 +/** Millisecond delay.
6802 + *
6803 + * @param msecs  Milliseconds to delay.
6804 + */
6805 +extern void DWC_MDELAY(uint32_t msecs);
6806 +#define dwc_mdelay DWC_MDELAY
6807 +
6808 +/** Non-busy waiting.
6809 + * Sleeps for specified number of milliseconds.
6810 + *
6811 + * @param msecs Milliseconds to sleep.
6812 + */
6813 +extern void DWC_MSLEEP(uint32_t msecs);
6814 +#define dwc_msleep DWC_MSLEEP
6815 +
6816 +extern uint32_t DWC_TIME(void);
6817 +#define dwc_time DWC_TIME
6818 +
6819 +#endif // _DWC_OS_H_
6820 +
6821 +
6822 +
6823 +
6824 +/** @mainpage DWC Portability and Common Library
6825 + *
6826 + * This is the documentation for the DWC Portability and Common Library.
6827 + *
6828 + * @section intro Introduction
6829 + *
6830 + * The DWC Portability library consists of wrapper calls and data structures to
6831 + * all low-level functions which are typically provided by the OS.  The WUDEV
6832 + * driver uses only these functions.  In order to port the WUDEV driver, only
6833 + * the functions in this library need to be re-implemented, with the same
6834 + * behavior as documented here.
6835 + *
6836 + * The Common library consists of higher level functions, which rely only on
6837 + * calling the functions from the DWC Portability library.  These common
6838 + * routines are shared across modules.  Some of the common libraries need to be
6839 + * used directly by the driver programmer when porting WUDEV.  Such as the
6840 + * parameter and notification libraries.
6841 + *
6842 + * @section low Portability Library OS Wrapper Functions
6843 + *
6844 + * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
6845 + * needs to be implemented when porting, for example DWC_MUTEX_ALLOC().  All of
6846 + * these functions are included in the dwc_os.h file.
6847 + *
6848 + * There are many functions here covering a wide array of OS services.  Please
6849 + * see dwc_os.h for details, and implementation notes for each function.
6850 + *
6851 + * @section common Common Library Functions
6852 + *
6853 + * Any function starting with dwc and in all lowercase is a common library
6854 + * routine.  These functions have a portable implementation and do not need to
6855 + * be reimplemented when porting.  The common routines can be used by any
6856 + * driver, and some must be used by the end user to control the drivers.  For
6857 + * example, you must use the Parameter common library in order to set the
6858 + * parameters in the WUDEV module.
6859 + *
6860 + * The common libraries consist of the following:
6861 + *
6862 + * - Connection Contexts - Used internally and can be used by end-user.  See dwc_cc.h
6863 + * - Parameters - Used internally and can be used by end-user.  See dwc_params.h
6864 + * - Notifications - Used internally and can be used by end-user.  See dwc_notifier.h
6865 + * - Lists - Used internally and can be used by end-user.  See dwc_list.h
6866 + * - Memory Debugging - Used internally and can be used by end-user.  See dwc_os.h
6867 + * - Modpow - Used internally only.  See dwc_modpow.h
6868 + * - DH - Used internally only.  See dwc_dh.h
6869 + * - Crypto - Used internally only.  See dwc_crypto.h
6870 + *
6871 + *
6872 + * @section prereq Prerequistes For dwc_os.h
6873 + * @subsection types Data Types
6874 + *
6875 + * The dwc_os.h file assumes that several low-level data types are pre defined for the
6876 + * compilation environment.  These data types are:
6877 + *
6878 + * - uint8_t - unsigned 8-bit data type
6879 + * - int8_t - signed 8-bit data type
6880 + * - uint16_t - unsigned 16-bit data type
6881 + * - int16_t - signed 16-bit data type
6882 + * - uint32_t - unsigned 32-bit data type
6883 + * - int32_t - signed 32-bit data type
6884 + * - uint64_t - unsigned 64-bit data type
6885 + * - int64_t - signed 64-bit data type
6886 + *
6887 + * Ensure that these are defined before using dwc_os.h.  The easiest way to do
6888 + * that is to modify the top of the file to include the appropriate header.
6889 + * This is already done for the Linux environment.  If the DWC_LINUX macro is
6890 + * defined, the correct header will be added.  A standard header <stdint.h> is
6891 + * also used for environments where standard C headers are available.
6892 + *
6893 + * @subsection stdarg Variable Arguments
6894 + *
6895 + * Variable arguments are provided by a standard C header <stdarg.h>.  it is
6896 + * available in Both the Linux and ANSI C enviornment.  An equivalent must be
6897 + * provided in your enviornment in order to use dwc_os.h with the debug and
6898 + * tracing message functionality.
6899 + *
6900 + * @subsection thread Threading
6901 + *
6902 + * WUDEV Core must be run on an operating system that provides for multiple
6903 + * threads/processes.  Threading can be implemented in many ways, even in
6904 + * embedded systems without an operating system.  At the bare minimum, the
6905 + * system should be able to start any number of processes at any time to handle
6906 + * special work.  It need not be a pre-emptive system.  Process context can
6907 + * change upon a call to a blocking function.  The hardware interrupt context
6908 + * that calls the module's ISR() function must be differentiable from process
6909 + * context, even if your processes are impemented via a hardware interrupt.
6910 + * Further locking mechanism between process must exist (or be implemented), and
6911 + * process context must have a way to disable interrupts for a period of time to
6912 + * lock them out.  If all of this exists, the functions in dwc_os.h related to
6913 + * threading should be able to be implemented with the defined behavior.
6914 + *
6915 + */
6916 --- /dev/null
6917 +++ b/drivers/usb/host/dwc_common_port/usb.h
6918 @@ -0,0 +1,850 @@
6919 +/*
6920 + * Copyright (c) 1998 The NetBSD Foundation, Inc.
6921 + * All rights reserved.
6922 + *
6923 + * This code is derived from software contributed to The NetBSD Foundation
6924 + * by Lennart Augustsson (lennart@augustsson.net) at
6925 + * Carlstedt Research & Technology.
6926 + *
6927 + * Redistribution and use in source and binary forms, with or without
6928 + * modification, are permitted provided that the following conditions
6929 + * are met:
6930 + * 1. Redistributions of source code must retain the above copyright
6931 + *    notice, this list of conditions and the following disclaimer.
6932 + * 2. Redistributions in binary form must reproduce the above copyright
6933 + *    notice, this list of conditions and the following disclaimer in the
6934 + *    documentation and/or other materials provided with the distribution.
6935 + * 3. All advertising materials mentioning features or use of this software
6936 + *    must display the following acknowledgement:
6937 + *        This product includes software developed by the NetBSD
6938 + *        Foundation, Inc. and its contributors.
6939 + * 4. Neither the name of The NetBSD Foundation nor the names of its
6940 + *    contributors may be used to endorse or promote products derived
6941 + *    from this software without specific prior written permission.
6942 + *
6943 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
6944 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
6945 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
6946 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
6947 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
6948 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
6949 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
6950 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
6951 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
6952 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
6953 + * POSSIBILITY OF SUCH DAMAGE.
6954 + */
6955 +
6956 +/* Modified by Synopsys, Inc, 12/12/2007 */
6957 +
6958 +
6959 +#ifndef _USB_H_
6960 +#define _USB_H_
6961 +
6962 +#include "dwc_os.h"
6963 +
6964 +/*
6965 + * The USB records contain some unaligned little-endian word
6966 + * components.  The U[SG]ETW macros take care of both the alignment
6967 + * and endian problem and should always be used to access non-byte
6968 + * values.
6969 + */
6970 +typedef u_int8_t uByte;
6971 +typedef u_int8_t uWord[2];
6972 +typedef u_int8_t uDWord[4];
6973 +
6974 +#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
6975 +
6976 +#if 1
6977 +#define UGETW(w) ((w)[0] | ((w)[1] << 8))
6978 +#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
6979 +#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
6980 +#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
6981 +                    (w)[1] = (u_int8_t)((v) >> 8), \
6982 +                    (w)[2] = (u_int8_t)((v) >> 16), \
6983 +                    (w)[3] = (u_int8_t)((v) >> 24))
6984 +#else
6985 +/*
6986 + * On little-endian machines that can handle unanliged accesses
6987 + * (e.g. i386) these macros can be replaced by the following.
6988 + */
6989 +#define UGETW(w) (*(u_int16_t *)(w))
6990 +#define USETW(w,v) (*(u_int16_t *)(w) = (v))
6991 +#define UGETDW(w) (*(u_int32_t *)(w))
6992 +#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
6993 +#endif
6994 +
6995 +#define UPACKED __attribute__((__packed__))
6996 +
6997 +typedef struct {
6998 +       uByte           bmRequestType;
6999 +       uByte           bRequest;
7000 +       uWord           wValue;
7001 +       uWord           wIndex;
7002 +       uWord           wLength;
7003 +} UPACKED usb_device_request_t;
7004 +
7005 +#define UT_GET_DIR(a) ((a) & 0x80)
7006 +#define UT_WRITE               0x00
7007 +#define UT_READ                        0x80
7008 +
7009 +#define UT_GET_TYPE(a) ((a) & 0x60)
7010 +#define UT_STANDARD            0x00
7011 +#define UT_CLASS               0x20
7012 +#define UT_VENDOR              0x40
7013 +
7014 +#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
7015 +#define UT_DEVICE              0x00
7016 +#define UT_INTERFACE           0x01
7017 +#define UT_ENDPOINT            0x02
7018 +#define UT_OTHER               0x03
7019 +
7020 +#define UT_READ_DEVICE         (UT_READ  | UT_STANDARD | UT_DEVICE)
7021 +#define UT_READ_INTERFACE      (UT_READ  | UT_STANDARD | UT_INTERFACE)
7022 +#define UT_READ_ENDPOINT       (UT_READ  | UT_STANDARD | UT_ENDPOINT)
7023 +#define UT_WRITE_DEVICE                (UT_WRITE | UT_STANDARD | UT_DEVICE)
7024 +#define UT_WRITE_INTERFACE     (UT_WRITE | UT_STANDARD | UT_INTERFACE)
7025 +#define UT_WRITE_ENDPOINT      (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
7026 +#define UT_READ_CLASS_DEVICE   (UT_READ  | UT_CLASS | UT_DEVICE)
7027 +#define UT_READ_CLASS_INTERFACE        (UT_READ  | UT_CLASS | UT_INTERFACE)
7028 +#define UT_READ_CLASS_OTHER    (UT_READ  | UT_CLASS | UT_OTHER)
7029 +#define UT_READ_CLASS_ENDPOINT (UT_READ  | UT_CLASS | UT_ENDPOINT)
7030 +#define UT_WRITE_CLASS_DEVICE  (UT_WRITE | UT_CLASS | UT_DEVICE)
7031 +#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
7032 +#define UT_WRITE_CLASS_OTHER   (UT_WRITE | UT_CLASS | UT_OTHER)
7033 +#define UT_WRITE_CLASS_ENDPOINT        (UT_WRITE | UT_CLASS | UT_ENDPOINT)
7034 +#define UT_READ_VENDOR_DEVICE  (UT_READ  | UT_VENDOR | UT_DEVICE)
7035 +#define UT_READ_VENDOR_INTERFACE (UT_READ  | UT_VENDOR | UT_INTERFACE)
7036 +#define UT_READ_VENDOR_OTHER   (UT_READ  | UT_VENDOR | UT_OTHER)
7037 +#define UT_READ_VENDOR_ENDPOINT        (UT_READ  | UT_VENDOR | UT_ENDPOINT)
7038 +#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE)
7039 +#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
7040 +#define UT_WRITE_VENDOR_OTHER  (UT_WRITE | UT_VENDOR | UT_OTHER)
7041 +#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
7042 +
7043 +/* Requests */
7044 +#define UR_GET_STATUS          0x00
7045 +#define  USTAT_STANDARD_STATUS  0x00
7046 +#define  WUSTAT_WUSB_FEATURE    0x01
7047 +#define  WUSTAT_CHANNEL_INFO    0x02
7048 +#define  WUSTAT_RECEIVED_DATA   0x03
7049 +#define  WUSTAT_MAS_AVAILABILITY 0x04
7050 +#define  WUSTAT_CURRENT_TRANSMIT_POWER 0x05
7051 +#define UR_CLEAR_FEATURE       0x01
7052 +#define UR_SET_FEATURE         0x03
7053 +#define UR_SET_AND_TEST_FEATURE 0x0c
7054 +#define UR_SET_ADDRESS         0x05
7055 +#define UR_GET_DESCRIPTOR      0x06
7056 +#define  UDESC_DEVICE          0x01
7057 +#define  UDESC_CONFIG          0x02
7058 +#define  UDESC_STRING          0x03
7059 +#define  UDESC_INTERFACE       0x04
7060 +#define  UDESC_ENDPOINT                0x05
7061 +#define  UDESC_DEVICE_QUALIFIER        0x06
7062 +#define  UDESC_OTHER_SPEED_CONFIGURATION 0x07
7063 +#define  UDESC_INTERFACE_POWER 0x08
7064 +#define  UDESC_OTG             0x09
7065 +#define  WUDESC_SECURITY       0x0c
7066 +#define  WUDESC_KEY            0x0d
7067 +#define   WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)
7068 +#define   WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)
7069 +#define    WUD_KEY_TYPE_ASSOC    0x01
7070 +#define    WUD_KEY_TYPE_GTK      0x02
7071 +#define   WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)
7072 +#define    WUD_KEY_ORIGIN_HOST   0x00
7073 +#define    WUD_KEY_ORIGIN_DEVICE 0x01
7074 +#define  WUDESC_ENCRYPTION_TYPE        0x0e
7075 +#define  WUDESC_BOS            0x0f
7076 +#define  WUDESC_DEVICE_CAPABILITY 0x10
7077 +#define  WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11
7078 +#define  UDESC_CS_DEVICE       0x21    /* class specific */
7079 +#define  UDESC_CS_CONFIG       0x22
7080 +#define  UDESC_CS_STRING       0x23
7081 +#define  UDESC_CS_INTERFACE    0x24
7082 +#define  UDESC_CS_ENDPOINT     0x25
7083 +#define  UDESC_HUB             0x29
7084 +#define UR_SET_DESCRIPTOR      0x07
7085 +#define UR_GET_CONFIG          0x08
7086 +#define UR_SET_CONFIG          0x09
7087 +#define UR_GET_INTERFACE       0x0a
7088 +#define UR_SET_INTERFACE       0x0b
7089 +#define UR_SYNCH_FRAME         0x0c
7090 +#define WUR_SET_ENCRYPTION      0x0d
7091 +#define WUR_GET_ENCRYPTION     0x0e
7092 +#define WUR_SET_HANDSHAKE      0x0f
7093 +#define WUR_GET_HANDSHAKE      0x10
7094 +#define WUR_SET_CONNECTION     0x11
7095 +#define WUR_SET_SECURITY_DATA  0x12
7096 +#define WUR_GET_SECURITY_DATA  0x13
7097 +#define WUR_SET_WUSB_DATA      0x14
7098 +#define  WUDATA_DRPIE_INFO  0x01
7099 +#define  WUDATA_TRANSMIT_DATA 0x02
7100 +#define  WUDATA_TRANSMIT_PARAMS 0x03
7101 +#define  WUDATA_RECEIVE_PARAMS 0x04
7102 +#define  WUDATA_TRANSMIT_POWER 0x05
7103 +#define WUR_LOOPBACK_DATA_WRITE        0x15
7104 +#define WUR_LOOPBACK_DATA_READ 0x16
7105 +#define WUR_SET_INTERFACE_DS   0x17
7106 +
7107 +/* Feature numbers */
7108 +#define UF_ENDPOINT_HALT       0
7109 +#define UF_DEVICE_REMOTE_WAKEUP        1
7110 +#define UF_TEST_MODE           2
7111 +#define UF_DEVICE_B_HNP_ENABLE 3
7112 +#define UF_DEVICE_A_HNP_SUPPORT        4
7113 +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
7114 +#define WUF_WUSB                3
7115 +#define  WUF_TX_DRPIE           0x0
7116 +#define  WUF_DEV_XMIT_PACKET    0x1
7117 +#define  WUF_COUNT_PACKETS      0x2
7118 +#define  WUF_CAPTURE_PACKETS    0x3
7119 +
7120 +/* Class requests from the USB 2.0 hub spec, table 11-15 */
7121 +#define UCR_CLEAR_HUB_FEATURE          (0x2000 | UR_CLEAR_FEATURE)
7122 +#define UCR_CLEAR_PORT_FEATURE         (0x2300 | UR_CLEAR_FEATURE)
7123 +#define UCR_GET_HUB_DESCRIPTOR         (0xa000 | UR_GET_DESCRIPTOR)
7124 +#define UCR_GET_HUB_STATUS             (0xa000 | UR_GET_STATUS)
7125 +#define UCR_GET_PORT_STATUS            (0xa300 | UR_GET_STATUS)
7126 +#define UCR_SET_HUB_FEATURE            (0x2000 | UR_SET_FEATURE)
7127 +#define UCR_SET_PORT_FEATURE           (0x2300 | UR_SET_FEATURE)
7128 +#define UCR_SET_AND_TEST_PORT_FEATURE  (0xa300 | UR_SET_AND_TEST_FEATURE)
7129 +
7130 +typedef struct {
7131 +       uByte           bLength;
7132 +       uByte           bDescriptorType;
7133 +       uByte           bDescriptorSubtype;
7134 +} UPACKED usb_descriptor_t;
7135 +
7136 +typedef struct {
7137 +       uByte           bLength;
7138 +       uByte           bDescriptorType;
7139 +       uWord           bcdUSB;
7140 +#define UD_USB_2_0             0x0200
7141 +#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
7142 +       uByte           bDeviceClass;
7143 +       uByte           bDeviceSubClass;
7144 +       uByte           bDeviceProtocol;
7145 +       uByte           bMaxPacketSize;
7146 +       /* The fields below are not part of the initial descriptor. */
7147 +       uWord           idVendor;
7148 +       uWord           idProduct;
7149 +       uWord           bcdDevice;
7150 +       uByte           iManufacturer;
7151 +       uByte           iProduct;
7152 +       uByte           iSerialNumber;
7153 +       uByte           bNumConfigurations;
7154 +} UPACKED usb_device_descriptor_t;
7155 +#define USB_DEVICE_DESCRIPTOR_SIZE 18
7156 +
7157 +typedef struct {
7158 +       uByte           bLength;
7159 +       uByte           bDescriptorType;
7160 +       uWord           wTotalLength;
7161 +       uByte           bNumInterface;
7162 +       uByte           bConfigurationValue;
7163 +       uByte           iConfiguration;
7164 +       uByte           bmAttributes;
7165 +#define UC_BUS_POWERED         0x80
7166 +#define UC_SELF_POWERED                0x40
7167 +#define UC_REMOTE_WAKEUP       0x20
7168 +       uByte           bMaxPower; /* max current in 2 mA units */
7169 +#define UC_POWER_FACTOR 2
7170 +} UPACKED usb_config_descriptor_t;
7171 +#define USB_CONFIG_DESCRIPTOR_SIZE 9
7172 +
7173 +typedef struct {
7174 +       uByte           bLength;
7175 +       uByte           bDescriptorType;
7176 +       uByte           bInterfaceNumber;
7177 +       uByte           bAlternateSetting;
7178 +       uByte           bNumEndpoints;
7179 +       uByte           bInterfaceClass;
7180 +       uByte           bInterfaceSubClass;
7181 +       uByte           bInterfaceProtocol;
7182 +       uByte           iInterface;
7183 +} UPACKED usb_interface_descriptor_t;
7184 +#define USB_INTERFACE_DESCRIPTOR_SIZE 9
7185 +
7186 +typedef struct {
7187 +       uByte           bLength;
7188 +       uByte           bDescriptorType;
7189 +       uByte           bEndpointAddress;
7190 +#define UE_GET_DIR(a)  ((a) & 0x80)
7191 +#define UE_SET_DIR(a,d)        ((a) | (((d)&1) << 7))
7192 +#define UE_DIR_IN      0x80
7193 +#define UE_DIR_OUT     0x00
7194 +#define UE_ADDR                0x0f
7195 +#define UE_GET_ADDR(a) ((a) & UE_ADDR)
7196 +       uByte           bmAttributes;
7197 +#define UE_XFERTYPE    0x03
7198 +#define  UE_CONTROL    0x00
7199 +#define  UE_ISOCHRONOUS        0x01
7200 +#define  UE_BULK       0x02
7201 +#define  UE_INTERRUPT  0x03
7202 +#define UE_GET_XFERTYPE(a)     ((a) & UE_XFERTYPE)
7203 +#define UE_ISO_TYPE    0x0c
7204 +#define  UE_ISO_ASYNC  0x04
7205 +#define  UE_ISO_ADAPT  0x08
7206 +#define  UE_ISO_SYNC   0x0c
7207 +#define UE_GET_ISO_TYPE(a)     ((a) & UE_ISO_TYPE)
7208 +       uWord           wMaxPacketSize;
7209 +       uByte           bInterval;
7210 +} UPACKED usb_endpoint_descriptor_t;
7211 +#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
7212 +
7213 +typedef struct {
7214 +       uByte           bLength;
7215 +       uByte           bDescriptorType;
7216 +       uWord           bString[127];
7217 +} UPACKED usb_string_descriptor_t;
7218 +#define USB_MAX_STRING_LEN 128
7219 +#define USB_LANGUAGE_TABLE 0   /* # of the string language id table */
7220 +
7221 +/* Hub specific request */
7222 +#define UR_GET_BUS_STATE       0x02
7223 +#define UR_CLEAR_TT_BUFFER     0x08
7224 +#define UR_RESET_TT            0x09
7225 +#define UR_GET_TT_STATE                0x0a
7226 +#define UR_STOP_TT             0x0b
7227 +
7228 +/* Hub features */
7229 +#define UHF_C_HUB_LOCAL_POWER  0
7230 +#define UHF_C_HUB_OVER_CURRENT 1
7231 +#define UHF_PORT_CONNECTION    0
7232 +#define UHF_PORT_ENABLE                1
7233 +#define UHF_PORT_SUSPEND       2
7234 +#define UHF_PORT_OVER_CURRENT  3
7235 +#define UHF_PORT_RESET         4
7236 +#define UHF_PORT_L1            5
7237 +#define UHF_PORT_POWER         8
7238 +#define UHF_PORT_LOW_SPEED     9
7239 +#define UHF_PORT_HIGH_SPEED    10
7240 +#define UHF_C_PORT_CONNECTION  16
7241 +#define UHF_C_PORT_ENABLE      17
7242 +#define UHF_C_PORT_SUSPEND     18
7243 +#define UHF_C_PORT_OVER_CURRENT        19
7244 +#define UHF_C_PORT_RESET       20
7245 +#define UHF_C_PORT_L1          23
7246 +#define UHF_PORT_TEST          21
7247 +#define UHF_PORT_INDICATOR     22
7248 +
7249 +typedef struct {
7250 +       uByte           bDescLength;
7251 +       uByte           bDescriptorType;
7252 +       uByte           bNbrPorts;
7253 +       uWord           wHubCharacteristics;
7254 +#define UHD_PWR                        0x0003
7255 +#define  UHD_PWR_GANGED                0x0000
7256 +#define  UHD_PWR_INDIVIDUAL    0x0001
7257 +#define  UHD_PWR_NO_SWITCH     0x0002
7258 +#define UHD_COMPOUND           0x0004
7259 +#define UHD_OC                 0x0018
7260 +#define  UHD_OC_GLOBAL         0x0000
7261 +#define  UHD_OC_INDIVIDUAL     0x0008
7262 +#define  UHD_OC_NONE           0x0010
7263 +#define UHD_TT_THINK           0x0060
7264 +#define  UHD_TT_THINK_8                0x0000
7265 +#define  UHD_TT_THINK_16       0x0020
7266 +#define  UHD_TT_THINK_24       0x0040
7267 +#define  UHD_TT_THINK_32       0x0060
7268 +#define UHD_PORT_IND           0x0080
7269 +       uByte           bPwrOn2PwrGood; /* delay in 2 ms units */
7270 +#define UHD_PWRON_FACTOR 2
7271 +       uByte           bHubContrCurrent;
7272 +       uByte           DeviceRemovable[32]; /* max 255 ports */
7273 +#define UHD_NOT_REMOV(desc, i) \
7274 +    (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
7275 +       /* deprecated */ uByte          PortPowerCtrlMask[1];
7276 +} UPACKED usb_hub_descriptor_t;
7277 +#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
7278 +
7279 +typedef struct {
7280 +       uByte           bLength;
7281 +       uByte           bDescriptorType;
7282 +       uWord           bcdUSB;
7283 +       uByte           bDeviceClass;
7284 +       uByte           bDeviceSubClass;
7285 +       uByte           bDeviceProtocol;
7286 +       uByte           bMaxPacketSize0;
7287 +       uByte           bNumConfigurations;
7288 +       uByte           bReserved;
7289 +} UPACKED usb_device_qualifier_t;
7290 +#define USB_DEVICE_QUALIFIER_SIZE 10
7291 +
7292 +typedef struct {
7293 +       uByte           bLength;
7294 +       uByte           bDescriptorType;
7295 +       uByte           bmAttributes;
7296 +#define UOTG_SRP       0x01
7297 +#define UOTG_HNP       0x02
7298 +} UPACKED usb_otg_descriptor_t;
7299 +
7300 +/* OTG feature selectors */
7301 +#define UOTG_B_HNP_ENABLE      3
7302 +#define UOTG_A_HNP_SUPPORT     4
7303 +#define UOTG_A_ALT_HNP_SUPPORT 5
7304 +
7305 +typedef struct {
7306 +       uWord           wStatus;
7307 +/* Device status flags */
7308 +#define UDS_SELF_POWERED               0x0001
7309 +#define UDS_REMOTE_WAKEUP              0x0002
7310 +/* Endpoint status flags */
7311 +#define UES_HALT                       0x0001
7312 +} UPACKED usb_status_t;
7313 +
7314 +typedef struct {
7315 +       uWord           wHubStatus;
7316 +#define UHS_LOCAL_POWER                        0x0001
7317 +#define UHS_OVER_CURRENT               0x0002
7318 +       uWord           wHubChange;
7319 +} UPACKED usb_hub_status_t;
7320 +
7321 +typedef struct {
7322 +       uWord           wPortStatus;
7323 +#define UPS_CURRENT_CONNECT_STATUS     0x0001
7324 +#define UPS_PORT_ENABLED               0x0002
7325 +#define UPS_SUSPEND                    0x0004
7326 +#define UPS_OVERCURRENT_INDICATOR      0x0008
7327 +#define UPS_RESET                      0x0010
7328 +#define UPS_PORT_POWER                 0x0100
7329 +#define UPS_LOW_SPEED                  0x0200
7330 +#define UPS_HIGH_SPEED                 0x0400
7331 +#define UPS_PORT_TEST                  0x0800
7332 +#define UPS_PORT_INDICATOR             0x1000
7333 +       uWord           wPortChange;
7334 +#define UPS_C_CONNECT_STATUS           0x0001
7335 +#define UPS_C_PORT_ENABLED             0x0002
7336 +#define UPS_C_SUSPEND                  0x0004
7337 +#define UPS_C_OVERCURRENT_INDICATOR    0x0008
7338 +#define UPS_C_PORT_RESET               0x0010
7339 +} UPACKED usb_port_status_t;
7340 +
7341 +/* Device class codes */
7342 +#define UDCLASS_IN_INTERFACE   0x00
7343 +#define UDCLASS_COMM           0x02
7344 +#define UDCLASS_HUB            0x09
7345 +#define  UDSUBCLASS_HUB                0x00
7346 +#define  UDPROTO_FSHUB         0x00
7347 +#define  UDPROTO_HSHUBSTT      0x01
7348 +#define  UDPROTO_HSHUBMTT      0x02
7349 +#define UDCLASS_DIAGNOSTIC     0xdc
7350 +#define UDCLASS_WIRELESS       0xe0
7351 +#define  UDSUBCLASS_RF         0x01
7352 +#define   UDPROTO_BLUETOOTH    0x01
7353 +#define UDCLASS_VENDOR         0xff
7354 +
7355 +/* Interface class codes */
7356 +#define UICLASS_UNSPEC         0x00
7357 +
7358 +#define UICLASS_AUDIO          0x01
7359 +#define  UISUBCLASS_AUDIOCONTROL       1
7360 +#define  UISUBCLASS_AUDIOSTREAM                2
7361 +#define  UISUBCLASS_MIDISTREAM         3
7362 +
7363 +#define UICLASS_CDC            0x02 /* communication */
7364 +#define         UISUBCLASS_DIRECT_LINE_CONTROL_MODEL   1
7365 +#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL     2
7366 +#define         UISUBCLASS_TELEPHONE_CONTROL_MODEL     3
7367 +#define         UISUBCLASS_MULTICHANNEL_CONTROL_MODEL  4
7368 +#define         UISUBCLASS_CAPI_CONTROLMODEL           5
7369 +#define         UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
7370 +#define         UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
7371 +#define   UIPROTO_CDC_AT                       1
7372 +
7373 +#define UICLASS_HID            0x03
7374 +#define  UISUBCLASS_BOOT       1
7375 +#define  UIPROTO_BOOT_KEYBOARD 1
7376 +
7377 +#define UICLASS_PHYSICAL       0x05
7378 +
7379 +#define UICLASS_IMAGE          0x06
7380 +
7381 +#define UICLASS_PRINTER                0x07
7382 +#define  UISUBCLASS_PRINTER    1
7383 +#define  UIPROTO_PRINTER_UNI   1
7384 +#define  UIPROTO_PRINTER_BI    2
7385 +#define  UIPROTO_PRINTER_1284  3
7386 +
7387 +#define UICLASS_MASS           0x08
7388 +#define  UISUBCLASS_RBC                1
7389 +#define  UISUBCLASS_SFF8020I   2
7390 +#define  UISUBCLASS_QIC157     3
7391 +#define  UISUBCLASS_UFI                4
7392 +#define  UISUBCLASS_SFF8070I   5
7393 +#define  UISUBCLASS_SCSI       6
7394 +#define  UIPROTO_MASS_CBI_I    0
7395 +#define  UIPROTO_MASS_CBI      1
7396 +#define  UIPROTO_MASS_BBB_OLD  2       /* Not in the spec anymore */
7397 +#define  UIPROTO_MASS_BBB      80      /* 'P' for the Iomega Zip drive */
7398 +
7399 +#define UICLASS_HUB            0x09
7400 +#define  UISUBCLASS_HUB                0
7401 +#define  UIPROTO_FSHUB         0
7402 +#define  UIPROTO_HSHUBSTT      0 /* Yes, same as previous */
7403 +#define  UIPROTO_HSHUBMTT      1
7404 +
7405 +#define UICLASS_CDC_DATA       0x0a
7406 +#define  UISUBCLASS_DATA               0
7407 +#define   UIPROTO_DATA_ISDNBRI         0x30    /* Physical iface */
7408 +#define   UIPROTO_DATA_HDLC            0x31    /* HDLC */
7409 +#define   UIPROTO_DATA_TRANSPARENT     0x32    /* Transparent */
7410 +#define   UIPROTO_DATA_Q921M           0x50    /* Management for Q921 */
7411 +#define   UIPROTO_DATA_Q921            0x51    /* Data for Q921 */
7412 +#define   UIPROTO_DATA_Q921TM          0x52    /* TEI multiplexer for Q921 */
7413 +#define   UIPROTO_DATA_V42BIS          0x90    /* Data compression */
7414 +#define   UIPROTO_DATA_Q931            0x91    /* Euro-ISDN */
7415 +#define   UIPROTO_DATA_V120            0x92    /* V.24 rate adaption */
7416 +#define   UIPROTO_DATA_CAPI            0x93    /* CAPI 2.0 commands */
7417 +#define   UIPROTO_DATA_HOST_BASED      0xfd    /* Host based driver */
7418 +#define   UIPROTO_DATA_PUF             0xfe    /* see Prot. Unit Func. Desc.*/
7419 +#define   UIPROTO_DATA_VENDOR          0xff    /* Vendor specific */
7420 +
7421 +#define UICLASS_SMARTCARD      0x0b
7422 +
7423 +/*#define UICLASS_FIRM_UPD     0x0c*/
7424 +
7425 +#define UICLASS_SECURITY       0x0d
7426 +
7427 +#define UICLASS_DIAGNOSTIC     0xdc
7428 +
7429 +#define UICLASS_WIRELESS       0xe0
7430 +#define  UISUBCLASS_RF                 0x01
7431 +#define   UIPROTO_BLUETOOTH            0x01
7432 +
7433 +#define UICLASS_APPL_SPEC      0xfe
7434 +#define  UISUBCLASS_FIRMWARE_DOWNLOAD  1
7435 +#define  UISUBCLASS_IRDA               2
7436 +#define  UIPROTO_IRDA                  0
7437 +
7438 +#define UICLASS_VENDOR         0xff
7439 +
7440 +
7441 +#define USB_HUB_MAX_DEPTH 5
7442 +
7443 +/*
7444 + * Minimum time a device needs to be powered down to go through
7445 + * a power cycle.  XXX Are these time in the spec?
7446 + */
7447 +#define USB_POWER_DOWN_TIME    200 /* ms */
7448 +#define USB_PORT_POWER_DOWN_TIME       100 /* ms */
7449 +
7450 +#if 0
7451 +/* These are the values from the spec. */
7452 +#define USB_PORT_RESET_DELAY   10  /* ms */
7453 +#define USB_PORT_ROOT_RESET_DELAY 50  /* ms */
7454 +#define USB_PORT_RESET_RECOVERY        10  /* ms */
7455 +#define USB_PORT_POWERUP_DELAY 100 /* ms */
7456 +#define USB_SET_ADDRESS_SETTLE 2   /* ms */
7457 +#define USB_RESUME_DELAY       (20*5)  /* ms */
7458 +#define USB_RESUME_WAIT                10  /* ms */
7459 +#define USB_RESUME_RECOVERY    10  /* ms */
7460 +#define USB_EXTRA_POWER_UP_TIME        0   /* ms */
7461 +#else
7462 +/* Allow for marginal (i.e. non-conforming) devices. */
7463 +#define USB_PORT_RESET_DELAY   50  /* ms */
7464 +#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */
7465 +#define USB_PORT_RESET_RECOVERY        250  /* ms */
7466 +#define USB_PORT_POWERUP_DELAY 300 /* ms */
7467 +#define USB_SET_ADDRESS_SETTLE 10  /* ms */
7468 +#define USB_RESUME_DELAY       (50*5)  /* ms */
7469 +#define USB_RESUME_WAIT                50  /* ms */
7470 +#define USB_RESUME_RECOVERY    50  /* ms */
7471 +#define USB_EXTRA_POWER_UP_TIME        20  /* ms */
7472 +#endif
7473 +
7474 +#define USB_MIN_POWER          100 /* mA */
7475 +#define USB_MAX_POWER          500 /* mA */
7476 +
7477 +#define USB_BUS_RESET_DELAY    100 /* ms XXX?*/
7478 +
7479 +
7480 +#define USB_UNCONFIG_NO 0
7481 +#define USB_UNCONFIG_INDEX (-1)
7482 +
7483 +/*** ioctl() related stuff ***/
7484 +
7485 +struct usb_ctl_request {
7486 +       int     ucr_addr;
7487 +       usb_device_request_t ucr_request;
7488 +       void    *ucr_data;
7489 +       int     ucr_flags;
7490 +#define USBD_SHORT_XFER_OK     0x04    /* allow short reads */
7491 +       int     ucr_actlen;             /* actual length transferred */
7492 +};
7493 +
7494 +struct usb_alt_interface {
7495 +       int     uai_config_index;
7496 +       int     uai_interface_index;
7497 +       int     uai_alt_no;
7498 +};
7499 +
7500 +#define USB_CURRENT_CONFIG_INDEX (-1)
7501 +#define USB_CURRENT_ALT_INDEX (-1)
7502 +
7503 +struct usb_config_desc {
7504 +       int     ucd_config_index;
7505 +       usb_config_descriptor_t ucd_desc;
7506 +};
7507 +
7508 +struct usb_interface_desc {
7509 +       int     uid_config_index;
7510 +       int     uid_interface_index;
7511 +       int     uid_alt_index;
7512 +       usb_interface_descriptor_t uid_desc;
7513 +};
7514 +
7515 +struct usb_endpoint_desc {
7516 +       int     ued_config_index;
7517 +       int     ued_interface_index;
7518 +       int     ued_alt_index;
7519 +       int     ued_endpoint_index;
7520 +       usb_endpoint_descriptor_t ued_desc;
7521 +};
7522 +
7523 +struct usb_full_desc {
7524 +       int     ufd_config_index;
7525 +       u_int   ufd_size;
7526 +       u_char  *ufd_data;
7527 +};
7528 +
7529 +struct usb_string_desc {
7530 +       int     usd_string_index;
7531 +       int     usd_language_id;
7532 +       usb_string_descriptor_t usd_desc;
7533 +};
7534 +
7535 +struct usb_ctl_report_desc {
7536 +       int     ucrd_size;
7537 +       u_char  ucrd_data[1024];        /* filled data size will vary */
7538 +};
7539 +
7540 +typedef struct { u_int32_t cookie; } usb_event_cookie_t;
7541 +
7542 +#define USB_MAX_DEVNAMES 4
7543 +#define USB_MAX_DEVNAMELEN 16
7544 +struct usb_device_info {
7545 +       u_int8_t        udi_bus;
7546 +       u_int8_t        udi_addr;       /* device address */
7547 +       usb_event_cookie_t udi_cookie;
7548 +       char            udi_product[USB_MAX_STRING_LEN];
7549 +       char            udi_vendor[USB_MAX_STRING_LEN];
7550 +       char            udi_release[8];
7551 +       u_int16_t       udi_productNo;
7552 +       u_int16_t       udi_vendorNo;
7553 +       u_int16_t       udi_releaseNo;
7554 +       u_int8_t        udi_class;
7555 +       u_int8_t        udi_subclass;
7556 +       u_int8_t        udi_protocol;
7557 +       u_int8_t        udi_config;
7558 +       u_int8_t        udi_speed;
7559 +#define USB_SPEED_LOW  1
7560 +#define USB_SPEED_FULL 2
7561 +#define USB_SPEED_HIGH 3
7562 +       int             udi_power;      /* power consumption in mA, 0 if selfpowered */
7563 +       int             udi_nports;
7564 +       char            udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
7565 +       u_int8_t        udi_ports[16];/* hub only: addresses of devices on ports */
7566 +#define USB_PORT_ENABLED 0xff
7567 +#define USB_PORT_SUSPENDED 0xfe
7568 +#define USB_PORT_POWERED 0xfd
7569 +#define USB_PORT_DISABLED 0xfc
7570 +};
7571 +
7572 +struct usb_ctl_report {
7573 +       int     ucr_report;
7574 +       u_char  ucr_data[1024]; /* filled data size will vary */
7575 +};
7576 +
7577 +struct usb_device_stats {
7578 +       u_long  uds_requests[4];        /* indexed by transfer type UE_* */
7579 +};
7580 +
7581 +
7582 +
7583 +
7584 +#define WUSB_MIN_IE                    0x80
7585 +#define WUSB_WCTA_IE                   0x80
7586 +#define WUSB_WCONNECTACK_IE            0x81
7587 +#define WUSB_WHOSTINFO_IE              0x82
7588 +#define  WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
7589 +#define   WUHI_CA_RECONN                       0x00
7590 +#define   WUHI_CA_LIMITED              0x01
7591 +#define   WUHI_CA_ALL                  0x03
7592 +#define  WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
7593 +#define WUSB_WCHCHANGEANNOUNCE_IE      0x83
7594 +#define WUSB_WDEV_DISCONNECT_IE                0x84
7595 +#define WUSB_WHOST_DISCONNECT_IE       0x85
7596 +#define WUSB_WRELEASE_CHANNEL_IE       0x86
7597 +#define WUSB_WWORK_IE                  0x87
7598 +#define WUSB_WCHANNEL_STOP_IE          0x88
7599 +#define WUSB_WDEV_KEEPALIVE_IE         0x89
7600 +#define WUSB_WISOCH_DISCARD_IE         0x8A
7601 +#define WUSB_WRESETDEVICE_IE           0x8B
7602 +#define WUSB_WXMIT_PACKET_ADJUST_IE    0x8C
7603 +#define WUSB_MAX_IE                    0x8C
7604 +
7605 +/* Device Notification Types */
7606 +
7607 +#define WUSB_DN_MIN                    0x01
7608 +#define WUSB_DN_CONNECT                        0x01
7609 +# define WUSB_DA_OLDCONN       0x00
7610 +# define WUSB_DA_NEWCONN       0x01
7611 +# define WUSB_DA_SELF_BEACON   0x02
7612 +# define WUSB_DA_DIR_BEACON    0x04
7613 +# define WUSB_DA_NO_BEACON     0x06
7614 +#define WUSB_DN_DISCONNECT             0x02
7615 +#define WUSB_DN_EPRDY                  0x03
7616 +#define WUSB_DN_MASAVAILCHANGED                0x04
7617 +#define WUSB_DN_REMOTEWAKEUP           0x05
7618 +#define WUSB_DN_SLEEP                  0x06
7619 +#define WUSB_DN_ALIVE                  0x07
7620 +#define WUSB_DN_MAX                    0x07
7621 +
7622 +
7623 +/* WUSB Handshake Data.  Used during the SET/GET HANDSHAKE requests */
7624 +typedef struct wusb_hndshk_data {
7625 +       uint8_t bMessageNumber;
7626 +       uint8_t bStatus;
7627 +       uint8_t tTKID[3];
7628 +       uint8_t bReserved;
7629 +       uint8_t CDID[16];
7630 +       uint8_t Nonce[16];
7631 +       uint8_t MIC[8];
7632 +} UPACKED wusb_hndshk_data_t;
7633 +#define WUSB_HANDSHAKE_LEN_FOR_MIC     38
7634 +
7635 +/* WUSB Connection Context */
7636 +typedef struct wusb_conn_context {
7637 +       uint8_t CHID [16];
7638 +       uint8_t CDID [16];
7639 +       uint8_t CK [16];
7640 +} UPACKED wusb_conn_context_t;
7641 +
7642 +/* WUSB Security Descriptor */
7643 +typedef struct wusb_security_desc {
7644 +       uint8_t bLength;
7645 +       uint8_t bDescriptorType;
7646 +       uint16_t wTotalLength;
7647 +       uint8_t bNumEncryptionTypes;
7648 +} UPACKED wusb_security_desc_t;
7649 +
7650 +/* WUSB Encryption Type Descriptor */
7651 +typedef struct wusb_encrypt_type_desc {
7652 +       uint8_t bLength;
7653 +       uint8_t bDescriptorType;
7654 +
7655 +       uint8_t bEncryptionType;
7656 +#define WUETD_UNSECURE         0
7657 +#define WUETD_WIRED            1
7658 +#define WUETD_CCM_1            2
7659 +#define WUETD_RSA_1            3
7660 +
7661 +       uint8_t bEncryptionValue;
7662 +       uint8_t bAuthKeyIndex;
7663 +} UPACKED wusb_encrypt_type_desc_t;
7664 +
7665 +/* WUSB Key Descriptor */
7666 +typedef struct wusb_key_desc {
7667 +       uint8_t bLength;
7668 +       uint8_t bDescriptorType;
7669 +       uint8_t tTKID[3];
7670 +       uint8_t bReserved;
7671 +       uint8_t KeyData[1];     /* variable length */
7672 +} UPACKED wusb_key_desc_t;
7673 +
7674 +/* WUSB BOS Descriptor (Binary device Object Store) */
7675 +typedef struct wusb_bos_desc {
7676 +       uint8_t bLength;
7677 +       uint8_t bDescriptorType;
7678 +       uint16_t wTotalLength;
7679 +       uint8_t bNumDeviceCaps;
7680 +} UPACKED wusb_bos_desc_t;
7681 +
7682 +
7683 +/* Device Capability Type Codes */
7684 +#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
7685 +
7686 +/* Device Capability Descriptor */
7687 +typedef struct wusb_dev_cap_desc {
7688 +       uint8_t bLength;
7689 +       uint8_t bDescriptorType;
7690 +       uint8_t bDevCapabilityType;
7691 +       uint8_t caps[1];              /* Variable length */
7692 +} UPACKED wusb_dev_cap_desc_t;
7693 +
7694 +/* Device Capability Descriptor */
7695 +typedef struct wusb_dev_cap_uwb_desc {
7696 +       uint8_t bLength;
7697 +       uint8_t bDescriptorType;
7698 +       uint8_t bDevCapabilityType;
7699 +       uint8_t bmAttributes;
7700 +       uint16_t wPHYRates;      /* Bitmap */
7701 +       uint8_t bmTFITXPowerInfo;
7702 +       uint8_t bmFFITXPowerInfo;
7703 +       uint16_t bmBandGroup;
7704 +       uint8_t bReserved;
7705 +} UPACKED wusb_dev_cap_uwb_desc_t;
7706 +
7707 +/* Wireless USB Endpoint Companion Descriptor */
7708 +typedef struct wusb_endpoint_companion_desc {
7709 +       uint8_t bLength;
7710 +       uint8_t bDescriptorType;
7711 +       uint8_t bMaxBurst;
7712 +       uint8_t bMaxSequence;
7713 +       uint16_t wMaxStreamDelay;
7714 +       uint16_t wOverTheAirPacketSize;
7715 +       uint8_t bOverTheAirInterval;
7716 +       uint8_t bmCompAttributes;
7717 +} UPACKED wusb_endpoint_companion_desc_t;
7718 +
7719 +
7720 +/* Wireless USB Numeric Association M1 Data Structure */
7721 +typedef struct wusb_m1_data {
7722 +       uint8_t version;
7723 +       uint16_t langId;
7724 +       uint8_t deviceFriendlyNameLength;
7725 +       uint8_t sha_256_m3[32];
7726 +       uint8_t deviceFriendlyName[256];
7727 +} UPACKED wusb_m1_data_t;
7728 +
7729 +typedef struct wusb_m2_data {
7730 +       uint8_t version;
7731 +       uint16_t langId;
7732 +       uint8_t hostFriendlyNameLength;
7733 +       uint8_t pkh[384];
7734 +       uint8_t hostFriendlyName[256];
7735 +} UPACKED wusb_m2_data_t;
7736 +
7737 +typedef struct wusb_m3_data {
7738 +       uint8_t pkd[384];
7739 +       uint8_t nd;
7740 +} UPACKED wusb_m3_data_t;
7741 +
7742 +typedef struct wusb_m4_data {
7743 +       uint32_t _attributeTypeIdAndLength_1;
7744 +       uint16_t associationTypeId;
7745 +
7746 +       uint32_t _attributeTypeIdAndLength_2;
7747 +       uint16_t associationSubTypeId;
7748 +
7749 +       uint32_t _attributeTypeIdAndLength_3;
7750 +       uint32_t length;
7751 +
7752 +       uint32_t _attributeTypeIdAndLength_4;
7753 +       uint32_t associationStatus;
7754 +
7755 +       uint32_t _attributeTypeIdAndLength_5;
7756 +       uint8_t chid[16];
7757 +
7758 +       uint32_t _attributeTypeIdAndLength_6;
7759 +       uint8_t cdid[16];
7760 +
7761 +       uint32_t _attributeTypeIdAndLength_7;
7762 +       uint8_t bandGroups[2];
7763 +} UPACKED wusb_m4_data_t;
7764 +
7765 +
7766 +
7767 +
7768 +#endif /* _USB_H_ */
7769 --- /dev/null
7770 +++ b/drivers/usb/host/dwc_otg/Makefile
7771 @@ -0,0 +1,78 @@
7772 +#
7773 +# Makefile for DWC_otg Highspeed USB controller driver
7774 +#
7775 +
7776 +ifneq ($(KERNELRELEASE),)
7777 +
7778 +ifeq ($(BUS_INTERFACE),)
7779 +       # BUS_INTERFACE = -DLM_INTERFACE
7780 +       BUS_INTERFACE = -DPLATFORM_INTERFACE=1
7781 +endif
7782 +
7783 +CPPFLAGS       += -DDEBUG 
7784 +
7785 +# Use one of the following flags to compile the software in host-only or
7786 +# device-only mode.
7787 +#CPPFLAGS        += -DDWC_HOST_ONLY
7788 +#CPPFLAGS        += -DDWC_DEVICE_ONLY
7789 +
7790 +CPPFLAGS       += -Dlinux -DDWC_HS_ELECT_TST
7791 +#CGG: CPPFLAGS += -DDWC_EN_ISOC
7792 +CPPFLAGS       += -I$(obj)/../dwc_common_port
7793 +#CPPFLAGS      += -I$(PORTLIB)
7794 +CPPFLAGS       += -DDWC_LINUX
7795 +CPPFLAGS       += $(CFI)
7796 +CPPFLAGS       += $(BUS_INTERFACE)
7797 +
7798 +obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
7799 +
7800 +dwc_otg-objs   := dwc_otg_driver.o dwc_otg_attr.o 
7801 +dwc_otg-objs   += dwc_otg_cil.o dwc_otg_cil_intr.o 
7802 +dwc_otg-objs   += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o 
7803 +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
7804 +ifneq ($(CFI),)
7805 +dwc_otg-objs   += dwc_otg_cfi.o
7806 +endif
7807 +
7808 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
7809 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
7810 +
7811 +ifneq ($(kernrel3),2.6.20)
7812 +EXTRA_CFLAGS += $(CPPFLAGS)
7813 +endif
7814 +
7815 +else
7816 +
7817 +PWD            := $(shell pwd)
7818 +PORTLIB                := $(PWD)/../dwc_common_port
7819 +
7820 +# Command paths
7821 +CTAGS          := $(CTAGS)
7822 +DOXYGEN                := $(DOXYGEN)
7823 +
7824 +default: portlib
7825 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
7826 +
7827 +install: default
7828 +ifneq ($(INSTALL_MOD_PATH),)
7829 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install
7830 +       $(MAKE) -C$(KDIR) M=$(PWD) modules_install      
7831 +else
7832 +       @echo "No install path defined"
7833 +endif
7834 +
7835 +portlib:
7836 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
7837 +       cp $(PORTLIB)/Module.symvers $(PWD)/
7838 +
7839 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
7840 +       $(DOXYGEN) doc/doxygen.cfg
7841 +
7842 +tags:  $(wildcard *.[hc])
7843 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
7844 +
7845 +
7846 +clean:
7847 +       rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions
7848 +
7849 +endif
7850 --- /dev/null
7851 +++ b/drivers/usb/host/dwc_otg/dummy_audio.c
7852 @@ -0,0 +1,1575 @@
7853 +/*
7854 + * zero.c -- Gadget Zero, for USB development
7855 + *
7856 + * Copyright (C) 2003-2004 David Brownell
7857 + * All rights reserved.
7858 + *
7859 + * Redistribution and use in source and binary forms, with or without
7860 + * modification, are permitted provided that the following conditions
7861 + * are met:
7862 + * 1. Redistributions of source code must retain the above copyright
7863 + *    notice, this list of conditions, and the following disclaimer,
7864 + *    without modification.
7865 + * 2. Redistributions in binary form must reproduce the above copyright
7866 + *    notice, this list of conditions and the following disclaimer in the
7867 + *    documentation and/or other materials provided with the distribution.
7868 + * 3. The names of the above-listed copyright holders may not be used
7869 + *    to endorse or promote products derived from this software without
7870 + *    specific prior written permission.
7871 + *
7872 + * ALTERNATIVELY, this software may be distributed under the terms of the
7873 + * GNU General Public License ("GPL") as published by the Free Software
7874 + * Foundation, either version 2 of that License or (at your option) any
7875 + * later version.
7876 + *
7877 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
7878 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
7879 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
7880 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
7881 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
7882 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
7883 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
7884 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
7885 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
7886 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7887 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7888 + */
7889 +
7890 +
7891 +/*
7892 + * Gadget Zero only needs two bulk endpoints, and is an example of how you
7893 + * can write a hardware-agnostic gadget driver running inside a USB device.
7894 + *
7895 + * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
7896 + * affect most of the driver.
7897 + *
7898 + * Use it with the Linux host/master side "usbtest" driver to get a basic
7899 + * functional test of your device-side usb stack, or with "usb-skeleton".
7900 + *
7901 + * It supports two similar configurations.  One sinks whatever the usb host
7902 + * writes, and in return sources zeroes.  The other loops whatever the host
7903 + * writes back, so the host can read it.  Module options include:
7904 + *
7905 + *   buflen=N          default N=4096, buffer size used
7906 + *   qlen=N            default N=32, how many buffers in the loopback queue
7907 + *   loopdefault       default false, list loopback config first
7908 + *
7909 + * Many drivers will only have one configuration, letting them be much
7910 + * simpler if they also don't support high speed operation (like this
7911 + * driver does).
7912 + */
7913 +
7914 +#include <linux/config.h>
7915 +#include <linux/module.h>
7916 +#include <linux/kernel.h>
7917 +#include <linux/delay.h>
7918 +#include <linux/ioport.h>
7919 +#include <linux/sched.h>
7920 +#include <linux/slab.h>
7921 +#include <linux/smp_lock.h>
7922 +#include <linux/errno.h>
7923 +#include <linux/init.h>
7924 +#include <linux/timer.h>
7925 +#include <linux/list.h>
7926 +#include <linux/interrupt.h>
7927 +#include <linux/uts.h>
7928 +#include <linux/version.h>
7929 +#include <linux/device.h>
7930 +#include <linux/moduleparam.h>
7931 +#include <linux/proc_fs.h>
7932 +
7933 +#include <asm/byteorder.h>
7934 +#include <asm/io.h>
7935 +#include <asm/irq.h>
7936 +#include <asm/system.h>
7937 +#include <asm/unaligned.h>
7938 +
7939 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
7940 +# include <linux/usb/ch9.h>
7941 +#else
7942 +# include <linux/usb_ch9.h>
7943 +#endif
7944 +
7945 +#include <linux/usb_gadget.h>
7946 +
7947 +
7948 +/*-------------------------------------------------------------------------*/
7949 +/*-------------------------------------------------------------------------*/
7950 +
7951 +
7952 +static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
7953 +{
7954 +       int     count = 0;
7955 +       u8      c;
7956 +       u16     uchar;
7957 +
7958 +       /* this insists on correct encodings, though not minimal ones.
7959 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
7960 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
7961 +        */
7962 +       while (len != 0 && (c = (u8) *s++) != 0) {
7963 +               if (unlikely(c & 0x80)) {
7964 +                       // 2-byte sequence:
7965 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
7966 +                       if ((c & 0xe0) == 0xc0) {
7967 +                               uchar = (c & 0x1f) << 6;
7968 +
7969 +                               c = (u8) *s++;
7970 +                               if ((c & 0xc0) != 0xc0)
7971 +                                       goto fail;
7972 +                               c &= 0x3f;
7973 +                               uchar |= c;
7974 +
7975 +                       // 3-byte sequence (most CJKV characters):
7976 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
7977 +                       } else if ((c & 0xf0) == 0xe0) {
7978 +                               uchar = (c & 0x0f) << 12;
7979 +
7980 +                               c = (u8) *s++;
7981 +                               if ((c & 0xc0) != 0xc0)
7982 +                                       goto fail;
7983 +                               c &= 0x3f;
7984 +                               uchar |= c << 6;
7985 +
7986 +                               c = (u8) *s++;
7987 +                               if ((c & 0xc0) != 0xc0)
7988 +                                       goto fail;
7989 +                               c &= 0x3f;
7990 +                               uchar |= c;
7991 +
7992 +                               /* no bogus surrogates */
7993 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
7994 +                                       goto fail;
7995 +
7996 +                       // 4-byte sequence (surrogate pairs, currently rare):
7997 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
7998 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
7999 +                       // (uuuuu = wwww + 1)
8000 +                       // FIXME accept the surrogate code points (only)
8001 +
8002 +                       } else
8003 +                               goto fail;
8004 +               } else
8005 +                       uchar = c;
8006 +               put_unaligned (cpu_to_le16 (uchar), cp++);
8007 +               count++;
8008 +               len--;
8009 +       }
8010 +       return count;
8011 +fail:
8012 +       return -1;
8013 +}
8014 +
8015 +
8016 +/**
8017 + * usb_gadget_get_string - fill out a string descriptor 
8018 + * @table: of c strings encoded using UTF-8
8019 + * @id: string id, from low byte of wValue in get string descriptor
8020 + * @buf: at least 256 bytes
8021 + *
8022 + * Finds the UTF-8 string matching the ID, and converts it into a
8023 + * string descriptor in utf16-le.
8024 + * Returns length of descriptor (always even) or negative errno
8025 + *
8026 + * If your driver needs stings in multiple languages, you'll probably
8027 + * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
8028 + * using this routine after choosing which set of UTF-8 strings to use.
8029 + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
8030 + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
8031 + * characters (which are also widely used in C strings).
8032 + */
8033 +int
8034 +usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
8035 +{
8036 +       struct usb_string       *s;
8037 +       int                     len;
8038 +
8039 +       /* descriptor 0 has the language id */
8040 +       if (id == 0) {
8041 +               buf [0] = 4;
8042 +               buf [1] = USB_DT_STRING;
8043 +               buf [2] = (u8) table->language;
8044 +               buf [3] = (u8) (table->language >> 8);
8045 +               return 4;
8046 +       }
8047 +       for (s = table->strings; s && s->s; s++)
8048 +               if (s->id == id)
8049 +                       break;
8050 +
8051 +       /* unrecognized: stall. */
8052 +       if (!s || !s->s)
8053 +               return -EINVAL;
8054 +
8055 +       /* string descriptors have length, tag, then UTF16-LE text */
8056 +       len = min ((size_t) 126, strlen (s->s));
8057 +       memset (buf + 2, 0, 2 * len);   /* zero all the bytes */
8058 +       len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
8059 +       if (len < 0)
8060 +               return -EINVAL;
8061 +       buf [0] = (len + 1) * 2;
8062 +       buf [1] = USB_DT_STRING;
8063 +       return buf [0];
8064 +}
8065 +
8066 +
8067 +/*-------------------------------------------------------------------------*/
8068 +/*-------------------------------------------------------------------------*/
8069 +
8070 +
8071 +/**
8072 + * usb_descriptor_fillbuf - fill buffer with descriptors
8073 + * @buf: Buffer to be filled
8074 + * @buflen: Size of buf
8075 + * @src: Array of descriptor pointers, terminated by null pointer.
8076 + *
8077 + * Copies descriptors into the buffer, returning the length or a
8078 + * negative error code if they can't all be copied.  Useful when
8079 + * assembling descriptors for an associated set of interfaces used
8080 + * as part of configuring a composite device; or in other cases where
8081 + * sets of descriptors need to be marshaled.
8082 + */
8083 +int
8084 +usb_descriptor_fillbuf(void *buf, unsigned buflen,
8085 +               const struct usb_descriptor_header **src)
8086 +{
8087 +       u8      *dest = buf;
8088 +
8089 +       if (!src)
8090 +               return -EINVAL;
8091 +
8092 +       /* fill buffer from src[] until null descriptor ptr */
8093 +       for (; 0 != *src; src++) {
8094 +               unsigned                len = (*src)->bLength;
8095 +
8096 +               if (len > buflen)
8097 +                       return -EINVAL;
8098 +               memcpy(dest, *src, len);
8099 +               buflen -= len;
8100 +               dest += len;
8101 +       }
8102 +       return dest - (u8 *)buf;
8103 +}
8104 +
8105 +
8106 +/**
8107 + * usb_gadget_config_buf - builts a complete configuration descriptor
8108 + * @config: Header for the descriptor, including characteristics such
8109 + *     as power requirements and number of interfaces.
8110 + * @desc: Null-terminated vector of pointers to the descriptors (interface,
8111 + *     endpoint, etc) defining all functions in this device configuration.
8112 + * @buf: Buffer for the resulting configuration descriptor.
8113 + * @length: Length of buffer.  If this is not big enough to hold the
8114 + *     entire configuration descriptor, an error code will be returned.
8115 + *
8116 + * This copies descriptors into the response buffer, building a descriptor
8117 + * for that configuration.  It returns the buffer length or a negative
8118 + * status code.  The config.wTotalLength field is set to match the length
8119 + * of the result, but other descriptor fields (including power usage and
8120 + * interface count) must be set by the caller.
8121 + *
8122 + * Gadget drivers could use this when constructing a config descriptor
8123 + * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
8124 + * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
8125 + */
8126 +int usb_gadget_config_buf(
8127 +       const struct usb_config_descriptor      *config,
8128 +       void                                    *buf,
8129 +       unsigned                                length,
8130 +       const struct usb_descriptor_header      **desc
8131 +)
8132 +{
8133 +       struct usb_config_descriptor            *cp = buf;
8134 +       int                                     len;
8135 +
8136 +       /* config descriptor first */
8137 +       if (length < USB_DT_CONFIG_SIZE || !desc)
8138 +               return -EINVAL;
8139 +       *cp = *config; 
8140 +
8141 +       /* then interface/endpoint/class/vendor/... */
8142 +       len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
8143 +                       length - USB_DT_CONFIG_SIZE, desc);
8144 +       if (len < 0)
8145 +               return len;
8146 +       len += USB_DT_CONFIG_SIZE;
8147 +       if (len > 0xffff)
8148 +               return -EINVAL;
8149 +
8150 +       /* patch up the config descriptor */
8151 +       cp->bLength = USB_DT_CONFIG_SIZE;
8152 +       cp->bDescriptorType = USB_DT_CONFIG;
8153 +       cp->wTotalLength = cpu_to_le16(len);
8154 +       cp->bmAttributes |= USB_CONFIG_ATT_ONE;
8155 +       return len;
8156 +}
8157 +
8158 +/*-------------------------------------------------------------------------*/
8159 +/*-------------------------------------------------------------------------*/
8160 +
8161 +
8162 +#define RBUF_LEN (1024*1024)
8163 +static int rbuf_start;
8164 +static int rbuf_len;
8165 +static __u8 rbuf[RBUF_LEN];
8166 +
8167 +/*-------------------------------------------------------------------------*/
8168 +
8169 +#define DRIVER_VERSION         "St Patrick's Day 2004"
8170 +
8171 +static const char shortname [] = "zero";
8172 +static const char longname [] = "YAMAHA YST-MS35D USB Speaker  ";
8173 +
8174 +static const char source_sink [] = "source and sink data";
8175 +static const char loopback [] = "loop input to output";
8176 +
8177 +/*-------------------------------------------------------------------------*/
8178 +
8179 +/*
8180 + * driver assumes self-powered hardware, and
8181 + * has no way for users to trigger remote wakeup.
8182 + *
8183 + * this version autoconfigures as much as possible,
8184 + * which is reasonable for most "bulk-only" drivers.
8185 + */
8186 +static const char *EP_IN_NAME;         /* source */
8187 +static const char *EP_OUT_NAME;                /* sink */
8188 +
8189 +/*-------------------------------------------------------------------------*/
8190 +
8191 +/* big enough to hold our biggest descriptor */
8192 +#define USB_BUFSIZ     512
8193 +
8194 +struct zero_dev {
8195 +       spinlock_t              lock;
8196 +       struct usb_gadget       *gadget;
8197 +       struct usb_request      *req;           /* for control responses */
8198 +
8199 +       /* when configured, we have one of two configs:
8200 +        * - source data (in to host) and sink it (out from host)
8201 +        * - or loop it back (out from host back in to host)
8202 +        */
8203 +       u8                      config;
8204 +       struct usb_ep           *in_ep, *out_ep;
8205 +
8206 +       /* autoresume timer */
8207 +       struct timer_list       resume;
8208 +};
8209 +
8210 +#define xprintk(d,level,fmt,args...) \
8211 +       dev_printk(level , &(d)->gadget->dev , fmt , ## args)
8212 +
8213 +#ifdef DEBUG
8214 +#define DBG(dev,fmt,args...) \
8215 +       xprintk(dev , KERN_DEBUG , fmt , ## args)
8216 +#else
8217 +#define DBG(dev,fmt,args...) \
8218 +       do { } while (0)
8219 +#endif /* DEBUG */
8220 +
8221 +#ifdef VERBOSE
8222 +#define VDBG   DBG
8223 +#else
8224 +#define VDBG(dev,fmt,args...) \
8225 +       do { } while (0)
8226 +#endif /* VERBOSE */
8227 +
8228 +#define ERROR(dev,fmt,args...) \
8229 +       xprintk(dev , KERN_ERR , fmt , ## args)
8230 +#define WARN(dev,fmt,args...) \
8231 +       xprintk(dev , KERN_WARNING , fmt , ## args)
8232 +#define INFO(dev,fmt,args...) \
8233 +       xprintk(dev , KERN_INFO , fmt , ## args)
8234 +
8235 +/*-------------------------------------------------------------------------*/
8236 +
8237 +static unsigned buflen = 4096;
8238 +static unsigned qlen = 32;
8239 +static unsigned pattern = 0;
8240 +
8241 +module_param (buflen, uint, S_IRUGO|S_IWUSR);
8242 +module_param (qlen, uint, S_IRUGO|S_IWUSR);
8243 +module_param (pattern, uint, S_IRUGO|S_IWUSR);
8244 +
8245 +/*
8246 + * if it's nonzero, autoresume says how many seconds to wait
8247 + * before trying to wake up the host after suspend.
8248 + */
8249 +static unsigned autoresume = 0;
8250 +module_param (autoresume, uint, 0);
8251 +
8252 +/*
8253 + * Normally the "loopback" configuration is second (index 1) so
8254 + * it's not the default.  Here's where to change that order, to
8255 + * work better with hosts where config changes are problematic.
8256 + * Or controllers (like superh) that only support one config.
8257 + */
8258 +static int loopdefault = 0;
8259 +
8260 +module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
8261 +
8262 +/*-------------------------------------------------------------------------*/
8263 +
8264 +/* Thanks to NetChip Technologies for donating this product ID.
8265 + *
8266 + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
8267 + * Instead:  allocate your own, using normal USB-IF procedures.
8268 + */
8269 +#ifndef        CONFIG_USB_ZERO_HNPTEST
8270 +#define DRIVER_VENDOR_NUM      0x0525          /* NetChip */
8271 +#define DRIVER_PRODUCT_NUM     0xa4a0          /* Linux-USB "Gadget Zero" */
8272 +#else
8273 +#define DRIVER_VENDOR_NUM      0x1a0a          /* OTG test device IDs */
8274 +#define DRIVER_PRODUCT_NUM     0xbadd
8275 +#endif
8276 +
8277 +/*-------------------------------------------------------------------------*/
8278 +
8279 +/*
8280 + * DESCRIPTORS ... most are static, but strings and (full)
8281 + * configuration descriptors are built on demand.
8282 + */
8283 +
8284 +/*
8285 +#define STRING_MANUFACTURER            25
8286 +#define STRING_PRODUCT                 42
8287 +#define STRING_SERIAL                  101
8288 +*/
8289 +#define STRING_MANUFACTURER            1
8290 +#define STRING_PRODUCT                 2
8291 +#define STRING_SERIAL                  3
8292 +
8293 +#define STRING_SOURCE_SINK             250
8294 +#define STRING_LOOPBACK                        251
8295 +
8296 +/*
8297 + * This device advertises two configurations; these numbers work
8298 + * on a pxa250 as well as more flexible hardware.
8299 + */
8300 +#define        CONFIG_SOURCE_SINK      3
8301 +#define        CONFIG_LOOPBACK         2
8302 +
8303 +/*
8304 +static struct usb_device_descriptor
8305 +device_desc = {
8306 +       .bLength =              sizeof device_desc,
8307 +       .bDescriptorType =      USB_DT_DEVICE,
8308 +
8309 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
8310 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
8311 +
8312 +       .idVendor =             __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
8313 +       .idProduct =            __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
8314 +       .iManufacturer =        STRING_MANUFACTURER,
8315 +       .iProduct =             STRING_PRODUCT,
8316 +       .iSerialNumber =        STRING_SERIAL,
8317 +       .bNumConfigurations =   2,
8318 +};
8319 +*/
8320 +static struct usb_device_descriptor
8321 +device_desc = {
8322 +       .bLength =              sizeof device_desc,
8323 +       .bDescriptorType =      USB_DT_DEVICE,
8324 +       .bcdUSB =               __constant_cpu_to_le16 (0x0100),
8325 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
8326 +       .bDeviceSubClass =      0,
8327 +       .bDeviceProtocol =      0,
8328 +       .bMaxPacketSize0 =      64,
8329 +       .bcdDevice =            __constant_cpu_to_le16 (0x0100),
8330 +       .idVendor =             __constant_cpu_to_le16 (0x0499),
8331 +       .idProduct =            __constant_cpu_to_le16 (0x3002),
8332 +       .iManufacturer =        STRING_MANUFACTURER,
8333 +       .iProduct =             STRING_PRODUCT,
8334 +       .iSerialNumber =        STRING_SERIAL,
8335 +       .bNumConfigurations =   1,
8336 +};
8337 +
8338 +static struct usb_config_descriptor
8339 +z_config = {
8340 +       .bLength =              sizeof z_config,
8341 +       .bDescriptorType =      USB_DT_CONFIG,
8342 +
8343 +       /* compute wTotalLength on the fly */
8344 +       .bNumInterfaces =       2,
8345 +       .bConfigurationValue =  1,
8346 +       .iConfiguration =       0,
8347 +       .bmAttributes =         0x40,
8348 +       .bMaxPower =            0,      /* self-powered */
8349 +};
8350 +
8351 +
8352 +static struct usb_otg_descriptor
8353 +otg_descriptor = {
8354 +       .bLength =              sizeof otg_descriptor,
8355 +       .bDescriptorType =      USB_DT_OTG,
8356 +
8357 +       .bmAttributes =         USB_OTG_SRP,
8358 +};
8359 +
8360 +/* one interface in each configuration */
8361 +#ifdef CONFIG_USB_GADGET_DUALSPEED
8362 +
8363 +/*
8364 + * usb 2.0 devices need to expose both high speed and full speed
8365 + * descriptors, unless they only run at full speed.
8366 + *
8367 + * that means alternate endpoint descriptors (bigger packets)
8368 + * and a "device qualifier" ... plus more construction options
8369 + * for the config descriptor.
8370 + */
8371 +
8372 +static struct usb_qualifier_descriptor
8373 +dev_qualifier = {
8374 +       .bLength =              sizeof dev_qualifier,
8375 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
8376 +
8377 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
8378 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
8379 +
8380 +       .bNumConfigurations =   2,
8381 +};
8382 +
8383 +
8384 +struct usb_cs_as_general_descriptor {
8385 +       __u8  bLength;
8386 +       __u8  bDescriptorType;
8387 +
8388 +       __u8  bDescriptorSubType;
8389 +       __u8  bTerminalLink;
8390 +       __u8  bDelay;
8391 +       __u16  wFormatTag;
8392 +} __attribute__ ((packed));
8393 +
8394 +struct usb_cs_as_format_descriptor {
8395 +       __u8  bLength;
8396 +       __u8  bDescriptorType;
8397 +
8398 +       __u8  bDescriptorSubType;
8399 +       __u8  bFormatType;
8400 +       __u8  bNrChannels;
8401 +       __u8  bSubframeSize;
8402 +       __u8  bBitResolution;
8403 +       __u8  bSamfreqType;
8404 +       __u8  tLowerSamFreq[3];
8405 +       __u8  tUpperSamFreq[3];
8406 +} __attribute__ ((packed));
8407 +
8408 +static const struct usb_interface_descriptor
8409 +z_audio_control_if_desc = {
8410 +       .bLength =              sizeof z_audio_control_if_desc,
8411 +       .bDescriptorType =      USB_DT_INTERFACE,
8412 +       .bInterfaceNumber = 0,
8413 +       .bAlternateSetting = 0,
8414 +       .bNumEndpoints = 0,
8415 +       .bInterfaceClass = USB_CLASS_AUDIO,
8416 +       .bInterfaceSubClass = 0x1,
8417 +       .bInterfaceProtocol = 0,
8418 +       .iInterface = 0,
8419 +};
8420 +
8421 +static const struct usb_interface_descriptor
8422 +z_audio_if_desc = {
8423 +       .bLength =              sizeof z_audio_if_desc,
8424 +       .bDescriptorType =      USB_DT_INTERFACE,
8425 +       .bInterfaceNumber = 1,
8426 +       .bAlternateSetting = 0,
8427 +       .bNumEndpoints = 0,
8428 +       .bInterfaceClass = USB_CLASS_AUDIO,
8429 +       .bInterfaceSubClass = 0x2,
8430 +       .bInterfaceProtocol = 0,
8431 +       .iInterface = 0,
8432 +};
8433 +
8434 +static const struct usb_interface_descriptor
8435 +z_audio_if_desc2 = {
8436 +       .bLength =              sizeof z_audio_if_desc,
8437 +       .bDescriptorType =      USB_DT_INTERFACE,
8438 +       .bInterfaceNumber = 1,
8439 +       .bAlternateSetting = 1,
8440 +       .bNumEndpoints = 1,
8441 +       .bInterfaceClass = USB_CLASS_AUDIO,
8442 +       .bInterfaceSubClass = 0x2,
8443 +       .bInterfaceProtocol = 0,
8444 +       .iInterface = 0,
8445 +};
8446 +
8447 +static const struct usb_cs_as_general_descriptor
8448 +z_audio_cs_as_if_desc = {
8449 +       .bLength = 7,
8450 +       .bDescriptorType = 0x24,
8451 +       
8452 +       .bDescriptorSubType = 0x01,
8453 +       .bTerminalLink = 0x01,
8454 +       .bDelay = 0x0,
8455 +       .wFormatTag = __constant_cpu_to_le16 (0x0001)
8456 +};
8457 +
8458 +
8459 +static const struct usb_cs_as_format_descriptor 
8460 +z_audio_cs_as_format_desc = {
8461 +       .bLength = 0xe,
8462 +       .bDescriptorType = 0x24,
8463 +       
8464 +       .bDescriptorSubType = 2,
8465 +       .bFormatType = 1,
8466 +       .bNrChannels = 1,
8467 +       .bSubframeSize = 1,
8468 +       .bBitResolution = 8,
8469 +       .bSamfreqType = 0,
8470 +       .tLowerSamFreq = {0x7e, 0x13, 0x00},
8471 +       .tUpperSamFreq = {0xe2, 0xd6, 0x00},
8472 +};
8473 +
8474 +static const struct usb_endpoint_descriptor 
8475 +z_iso_ep = {
8476 +       .bLength = 0x09,
8477 +       .bDescriptorType = 0x05,
8478 +       .bEndpointAddress = 0x04,
8479 +       .bmAttributes = 0x09,
8480 +       .wMaxPacketSize = 0x0038,
8481 +       .bInterval = 0x01,
8482 +       .bRefresh = 0x00,
8483 +       .bSynchAddress = 0x00,  
8484 +};
8485 +
8486 +static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
8487 +
8488 +// 9 bytes
8489 +static char z_ac_interface_header_desc[] = 
8490 +{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };
8491 +
8492 +// 12 bytes
8493 +static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 
8494 +                    0x03, 0x00, 0x00, 0x00};
8495 +// 13 bytes
8496 +static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00, 
8497 +                    0x02, 0x00, 0x02, 0x00, 0x00};
8498 +// 9 bytes
8499 +static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02, 
8500 +                    0x00};
8501 +
8502 +static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 
8503 +                     0x00};
8504 +
8505 +static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
8506 +
8507 +static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00, 
8508 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
8509 +
8510 +static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
8511 +                     0x00};
8512 +
8513 +static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
8514 +
8515 +static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
8516 +                     0x00};
8517 +
8518 +static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
8519 +
8520 +static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,
8521 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
8522 +
8523 +static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
8524 +                     0x00};
8525 +
8526 +static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
8527 +
8528 +static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,
8529 +                      0x00};
8530 +
8531 +static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
8532 +
8533 +static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,
8534 +                      0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};
8535 +
8536 +static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,
8537 +                      0x00};
8538 +
8539 +static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
8540 +
8541 +static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00, 
8542 +                      0x00};
8543 +
8544 +static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
8545 +
8546 +static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00, 
8547 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
8548 +
8549 +static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,
8550 +                      0x00};
8551 +
8552 +static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
8553 +
8554 +static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,
8555 +                      0x00};
8556 +
8557 +static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
8558 +
8559 +static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00, 
8560 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
8561 +
8562 +static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,
8563 +                      0x00};
8564 +
8565 +static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
8566 +
8567 +
8568 +
8569 +static const struct usb_descriptor_header *z_function [] = {
8570 +       (struct usb_descriptor_header *) &z_audio_control_if_desc,
8571 +       (struct usb_descriptor_header *) &z_ac_interface_header_desc,
8572 +       (struct usb_descriptor_header *) &z_0,
8573 +       (struct usb_descriptor_header *) &z_1,
8574 +       (struct usb_descriptor_header *) &z_2,
8575 +       (struct usb_descriptor_header *) &z_audio_if_desc,
8576 +       (struct usb_descriptor_header *) &z_audio_if_desc2,
8577 +       (struct usb_descriptor_header *) &z_audio_cs_as_if_desc,
8578 +       (struct usb_descriptor_header *) &z_audio_cs_as_format_desc,
8579 +       (struct usb_descriptor_header *) &z_iso_ep,
8580 +       (struct usb_descriptor_header *) &z_iso_ep2,
8581 +       (struct usb_descriptor_header *) &za_0,
8582 +       (struct usb_descriptor_header *) &za_1,
8583 +       (struct usb_descriptor_header *) &za_2,
8584 +       (struct usb_descriptor_header *) &za_3,
8585 +       (struct usb_descriptor_header *) &za_4,
8586 +       (struct usb_descriptor_header *) &za_5,
8587 +       (struct usb_descriptor_header *) &za_6,
8588 +       (struct usb_descriptor_header *) &za_7,
8589 +       (struct usb_descriptor_header *) &za_8,
8590 +       (struct usb_descriptor_header *) &za_9,
8591 +       (struct usb_descriptor_header *) &za_10,
8592 +       (struct usb_descriptor_header *) &za_11,
8593 +       (struct usb_descriptor_header *) &za_12,
8594 +       (struct usb_descriptor_header *) &za_13,
8595 +       (struct usb_descriptor_header *) &za_14,
8596 +       (struct usb_descriptor_header *) &za_15,
8597 +       (struct usb_descriptor_header *) &za_16,
8598 +       (struct usb_descriptor_header *) &za_17,
8599 +       (struct usb_descriptor_header *) &za_18,
8600 +       (struct usb_descriptor_header *) &za_19,
8601 +       (struct usb_descriptor_header *) &za_20,
8602 +       (struct usb_descriptor_header *) &za_21,
8603 +       (struct usb_descriptor_header *) &za_22,
8604 +       (struct usb_descriptor_header *) &za_23,
8605 +       (struct usb_descriptor_header *) &za_24,
8606 +       NULL,
8607 +};
8608 +
8609 +/* maxpacket and other transfer characteristics vary by speed. */
8610 +#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
8611 +
8612 +#else
8613 +
8614 +/* if there's no high speed support, maxpacket doesn't change. */
8615 +#define ep_desc(g,hs,fs) fs
8616 +
8617 +#endif /* !CONFIG_USB_GADGET_DUALSPEED */
8618 +
8619 +static char                            manufacturer [40];
8620 +//static char                          serial [40];
8621 +static char                            serial [] = "Ser 00 em";
8622 +
8623 +/* static strings, in UTF-8 */
8624 +static struct usb_string               strings [] = {
8625 +       { STRING_MANUFACTURER, manufacturer, },
8626 +       { STRING_PRODUCT, longname, },
8627 +       { STRING_SERIAL, serial, },
8628 +       { STRING_LOOPBACK, loopback, },
8629 +       { STRING_SOURCE_SINK, source_sink, },
8630 +       {  }                    /* end of list */
8631 +};
8632 +
8633 +static struct usb_gadget_strings       stringtab = {
8634 +       .language       = 0x0409,       /* en-us */
8635 +       .strings        = strings,
8636 +};
8637 +
8638 +/*
8639 + * config descriptors are also handcrafted.  these must agree with code
8640 + * that sets configurations, and with code managing interfaces and their
8641 + * altsettings.  other complexity may come from:
8642 + *
8643 + *  - high speed support, including "other speed config" rules
8644 + *  - multiple configurations
8645 + *  - interfaces with alternate settings
8646 + *  - embedded class or vendor-specific descriptors
8647 + *
8648 + * this handles high speed, and has a second config that could as easily
8649 + * have been an alternate interface setting (on most hardware).
8650 + *
8651 + * NOTE:  to demonstrate (and test) more USB capabilities, this driver
8652 + * should include an altsetting to test interrupt transfers, including
8653 + * high bandwidth modes at high speed.  (Maybe work like Intel's test
8654 + * device?)
8655 + */
8656 +static int
8657 +config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)
8658 +{
8659 +       int len;
8660 +       const struct usb_descriptor_header **function;
8661 +       
8662 +       function = z_function;
8663 +       len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);
8664 +       if (len < 0)
8665 +               return len;
8666 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
8667 +       return len;
8668 +}
8669 +
8670 +/*-------------------------------------------------------------------------*/
8671 +
8672 +static struct usb_request *
8673 +alloc_ep_req (struct usb_ep *ep, unsigned length)
8674 +{
8675 +       struct usb_request      *req;
8676 +
8677 +       req = usb_ep_alloc_request (ep, GFP_ATOMIC);
8678 +       if (req) {
8679 +               req->length = length;
8680 +               req->buf = usb_ep_alloc_buffer (ep, length,
8681 +                               &req->dma, GFP_ATOMIC);
8682 +               if (!req->buf) {
8683 +                       usb_ep_free_request (ep, req);
8684 +                       req = NULL;
8685 +               }
8686 +       }
8687 +       return req;
8688 +}
8689 +
8690 +static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
8691 +{
8692 +       if (req->buf)
8693 +               usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
8694 +       usb_ep_free_request (ep, req);
8695 +}
8696 +
8697 +/*-------------------------------------------------------------------------*/
8698 +
8699 +/* optionally require specific source/sink data patterns  */
8700 +
8701 +static int
8702 +check_read_data (
8703 +       struct zero_dev         *dev,
8704 +       struct usb_ep           *ep,
8705 +       struct usb_request      *req
8706 +)
8707 +{
8708 +       unsigned        i;
8709 +       u8              *buf = req->buf;
8710 +
8711 +       for (i = 0; i < req->actual; i++, buf++) {
8712 +               switch (pattern) {
8713 +               /* all-zeroes has no synchronization issues */
8714 +               case 0:
8715 +                       if (*buf == 0)
8716 +                               continue;
8717 +                       break;
8718 +               /* mod63 stays in sync with short-terminated transfers,
8719 +                * or otherwise when host and gadget agree on how large
8720 +                * each usb transfer request should be.  resync is done
8721 +                * with set_interface or set_config.
8722 +                */
8723 +               case 1:
8724 +                       if (*buf == (u8)(i % 63))
8725 +                               continue;
8726 +                       break;
8727 +               }
8728 +               ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
8729 +               usb_ep_set_halt (ep);
8730 +               return -EINVAL;
8731 +       }
8732 +       return 0;
8733 +}
8734 +
8735 +/*-------------------------------------------------------------------------*/
8736 +
8737 +static void zero_reset_config (struct zero_dev *dev)
8738 +{
8739 +       if (dev->config == 0)
8740 +               return;
8741 +
8742 +       DBG (dev, "reset config\n");
8743 +
8744 +       /* just disable endpoints, forcing completion of pending i/o.
8745 +        * all our completion handlers free their requests in this case.
8746 +        */
8747 +       if (dev->in_ep) {
8748 +               usb_ep_disable (dev->in_ep);
8749 +               dev->in_ep = NULL;
8750 +       }
8751 +       if (dev->out_ep) {
8752 +               usb_ep_disable (dev->out_ep);
8753 +               dev->out_ep = NULL;
8754 +       }
8755 +       dev->config = 0;
8756 +       del_timer (&dev->resume);
8757 +}
8758 +
8759 +#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
8760 +
8761 +static void 
8762 +zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)
8763 +{
8764 +       struct zero_dev *dev = ep->driver_data;
8765 +       int             status = req->status;
8766 +       int i, j;
8767 +
8768 +       switch (status) {
8769 +
8770 +       case 0:                         /* normal completion? */
8771 +               //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);
8772 +               for (i=0, j=rbuf_start; i<req->actual; i++) {
8773 +                       //printk ("%02x ", ((__u8*)req->buf)[i]);
8774 +                       rbuf[j] = ((__u8*)req->buf)[i];
8775 +                       j++;
8776 +                       if (j >= RBUF_LEN) j=0;
8777 +               }
8778 +               rbuf_start = j;
8779 +               //printk ("\n\n");
8780 +
8781 +               if (rbuf_len < RBUF_LEN) {
8782 +                       rbuf_len += req->actual;
8783 +                       if (rbuf_len > RBUF_LEN) {
8784 +                               rbuf_len = RBUF_LEN;
8785 +                       }
8786 +               }
8787 +
8788 +               break;
8789 +
8790 +       /* this endpoint is normally active while we're configured */
8791 +       case -ECONNABORTED:             /* hardware forced ep reset */
8792 +       case -ECONNRESET:               /* request dequeued */
8793 +       case -ESHUTDOWN:                /* disconnect from host */
8794 +               VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
8795 +                               req->actual, req->length);
8796 +               if (ep == dev->out_ep)
8797 +                       check_read_data (dev, ep, req);
8798 +               free_ep_req (ep, req);
8799 +               return;
8800 +
8801 +       case -EOVERFLOW:                /* buffer overrun on read means that
8802 +                                        * we didn't provide a big enough
8803 +                                        * buffer.
8804 +                                        */
8805 +       default:
8806 +#if 1
8807 +               DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
8808 +                               status, req->actual, req->length);
8809 +#endif
8810 +       case -EREMOTEIO:                /* short read */
8811 +               break;
8812 +       }
8813 +
8814 +       status = usb_ep_queue (ep, req, GFP_ATOMIC);
8815 +       if (status) {
8816 +               ERROR (dev, "kill %s:  resubmit %d bytes --> %d\n",
8817 +                               ep->name, req->length, status);
8818 +               usb_ep_set_halt (ep);
8819 +               /* FIXME recover later ... somehow */
8820 +       }
8821 +}
8822 +
8823 +static struct usb_request *
8824 +zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)
8825 +{
8826 +       struct usb_request      *req;
8827 +       int                     status;
8828 +
8829 +       req = alloc_ep_req (ep, 512);
8830 +       if (!req)
8831 +               return NULL;
8832 +
8833 +       req->complete = zero_isoc_complete;
8834 +
8835 +       status = usb_ep_queue (ep, req, gfp_flags);
8836 +       if (status) {
8837 +               struct zero_dev *dev = ep->driver_data;
8838 +
8839 +               ERROR (dev, "start %s --> %d\n", ep->name, status);
8840 +               free_ep_req (ep, req);
8841 +               req = NULL;
8842 +       }
8843 +
8844 +       return req;
8845 +}
8846 +
8847 +/* change our operational config.  this code must agree with the code
8848 + * that returns config descriptors, and altsetting code.
8849 + *
8850 + * it's also responsible for power management interactions. some
8851 + * configurations might not work with our current power sources.
8852 + *
8853 + * note that some device controller hardware will constrain what this
8854 + * code can do, perhaps by disallowing more than one configuration or
8855 + * by limiting configuration choices (like the pxa2xx).
8856 + */
8857 +static int
8858 +zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
8859 +{
8860 +       int                     result = 0;
8861 +       struct usb_gadget       *gadget = dev->gadget;
8862 +       const struct usb_endpoint_descriptor    *d;
8863 +       struct usb_ep           *ep;
8864 +
8865 +       if (number == dev->config)
8866 +               return 0;
8867 +
8868 +       zero_reset_config (dev);
8869 +
8870 +       gadget_for_each_ep (ep, gadget) {
8871 +
8872 +               if (strcmp (ep->name, "ep4") == 0) {
8873 +
8874 +                       d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6
8875 +                       result = usb_ep_enable (ep, d);
8876 +
8877 +                       if (result == 0) {
8878 +                               ep->driver_data = dev;
8879 +                               dev->in_ep = ep;
8880 +
8881 +                               if (zero_start_isoc_ep (ep, gfp_flags) != 0) {
8882 +
8883 +                                       dev->in_ep = ep;
8884 +                                       continue;
8885 +                               }
8886 +
8887 +                               usb_ep_disable (ep);
8888 +                               result = -EIO;
8889 +                       }
8890 +               }
8891 +
8892 +       }
8893 +
8894 +       dev->config = number;
8895 +       return result;
8896 +}
8897 +
8898 +/*-------------------------------------------------------------------------*/
8899 +
8900 +static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
8901 +{
8902 +       if (req->status || req->actual != req->length)
8903 +               DBG ((struct zero_dev *) ep->driver_data,
8904 +                               "setup complete --> %d, %d/%d\n",
8905 +                               req->status, req->actual, req->length);
8906 +}
8907 +
8908 +/*
8909 + * The setup() callback implements all the ep0 functionality that's
8910 + * not handled lower down, in hardware or the hardware driver (like
8911 + * device and endpoint feature flags, and their status).  It's all
8912 + * housekeeping for the gadget function we're implementing.  Most of
8913 + * the work is in config-specific setup.
8914 + */
8915 +static int
8916 +zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
8917 +{
8918 +       struct zero_dev         *dev = get_gadget_data (gadget);
8919 +       struct usb_request      *req = dev->req;
8920 +       int                     value = -EOPNOTSUPP;
8921 +
8922 +       /* usually this stores reply data in the pre-allocated ep0 buffer,
8923 +        * but config change events will reconfigure hardware.
8924 +        */
8925 +       req->zero = 0;
8926 +       switch (ctrl->bRequest) {
8927 +
8928 +       case USB_REQ_GET_DESCRIPTOR:
8929 +
8930 +               switch (ctrl->wValue >> 8) {
8931 +
8932 +               case USB_DT_DEVICE:
8933 +                       value = min (ctrl->wLength, (u16) sizeof device_desc);
8934 +                       memcpy (req->buf, &device_desc, value);
8935 +                       break;
8936 +#ifdef CONFIG_USB_GADGET_DUALSPEED
8937 +               case USB_DT_DEVICE_QUALIFIER:
8938 +                       if (!gadget->is_dualspeed)
8939 +                               break;
8940 +                       value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
8941 +                       memcpy (req->buf, &dev_qualifier, value);
8942 +                       break;
8943 +
8944 +               case USB_DT_OTHER_SPEED_CONFIG:
8945 +                       if (!gadget->is_dualspeed)
8946 +                               break;
8947 +                       // FALLTHROUGH
8948 +#endif /* CONFIG_USB_GADGET_DUALSPEED */
8949 +               case USB_DT_CONFIG:
8950 +                       value = config_buf (gadget, req->buf,
8951 +                                       ctrl->wValue >> 8,
8952 +                                       ctrl->wValue & 0xff);
8953 +                       if (value >= 0)
8954 +                               value = min (ctrl->wLength, (u16) value);
8955 +                       break;
8956 +
8957 +               case USB_DT_STRING:
8958 +                       /* wIndex == language code.
8959 +                        * this driver only handles one language, you can
8960 +                        * add string tables for other languages, using
8961 +                        * any UTF-8 characters
8962 +                        */
8963 +                       value = usb_gadget_get_string (&stringtab,
8964 +                                       ctrl->wValue & 0xff, req->buf);
8965 +                       if (value >= 0) {
8966 +                               value = min (ctrl->wLength, (u16) value);
8967 +                       }
8968 +                       break;
8969 +               }
8970 +               break;
8971 +
8972 +       /* currently two configs, two speeds */
8973 +       case USB_REQ_SET_CONFIGURATION:
8974 +               if (ctrl->bRequestType != 0)
8975 +                       goto unknown;
8976 +
8977 +               spin_lock (&dev->lock);
8978 +               value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
8979 +               spin_unlock (&dev->lock);
8980 +               break;
8981 +       case USB_REQ_GET_CONFIGURATION:
8982 +               if (ctrl->bRequestType != USB_DIR_IN)
8983 +                       goto unknown;
8984 +               *(u8 *)req->buf = dev->config;
8985 +               value = min (ctrl->wLength, (u16) 1);
8986 +               break;
8987 +
8988 +       /* until we add altsetting support, or other interfaces,
8989 +        * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
8990 +        * and already killed pending endpoint I/O.
8991 +        */
8992 +       case USB_REQ_SET_INTERFACE:
8993 +
8994 +               if (ctrl->bRequestType != USB_RECIP_INTERFACE)
8995 +                       goto unknown;
8996 +               spin_lock (&dev->lock);
8997 +               if (dev->config) {
8998 +                       u8              config = dev->config;
8999 +
9000 +                       /* resets interface configuration, forgets about
9001 +                        * previous transaction state (queued bufs, etc)
9002 +                        * and re-inits endpoint state (toggle etc)
9003 +                        * no response queued, just zero status == success.
9004 +                        * if we had more than one interface we couldn't
9005 +                        * use this "reset the config" shortcut.
9006 +                        */
9007 +                       zero_reset_config (dev);
9008 +                       zero_set_config (dev, config, GFP_ATOMIC);
9009 +                       value = 0;
9010 +               }
9011 +               spin_unlock (&dev->lock);
9012 +               break;
9013 +       case USB_REQ_GET_INTERFACE:
9014 +               if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {
9015 +                       value = ctrl->wLength;
9016 +                       break;
9017 +               }
9018 +               else {
9019 +                       if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
9020 +                               goto unknown;
9021 +                       if (!dev->config)
9022 +                               break;
9023 +                       if (ctrl->wIndex != 0) {
9024 +                               value = -EDOM;
9025 +                               break;
9026 +                       }
9027 +                       *(u8 *)req->buf = 0;
9028 +                       value = min (ctrl->wLength, (u16) 1);
9029 +               }
9030 +               break;
9031 +
9032 +       /*
9033 +        * These are the same vendor-specific requests supported by
9034 +        * Intel's USB 2.0 compliance test devices.  We exceed that
9035 +        * device spec by allowing multiple-packet requests.
9036 +        */
9037 +       case 0x5b:      /* control WRITE test -- fill the buffer */
9038 +               if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
9039 +                       goto unknown;
9040 +               if (ctrl->wValue || ctrl->wIndex)
9041 +                       break;
9042 +               /* just read that many bytes into the buffer */
9043 +               if (ctrl->wLength > USB_BUFSIZ)
9044 +                       break;
9045 +               value = ctrl->wLength;
9046 +               break;
9047 +       case 0x5c:      /* control READ test -- return the buffer */
9048 +               if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
9049 +                       goto unknown;
9050 +               if (ctrl->wValue || ctrl->wIndex)
9051 +                       break;
9052 +               /* expect those bytes are still in the buffer; send back */
9053 +               if (ctrl->wLength > USB_BUFSIZ
9054 +                               || ctrl->wLength != req->length)
9055 +                       break;
9056 +               value = ctrl->wLength;
9057 +               break;
9058 +
9059 +       case 0x01: // SET_CUR
9060 +       case 0x02:
9061 +       case 0x03:
9062 +       case 0x04:
9063 +       case 0x05:
9064 +               value = ctrl->wLength;
9065 +               break;
9066 +       case 0x81:
9067 +               switch (ctrl->wValue) {
9068 +               case 0x0201:
9069 +               case 0x0202:
9070 +                       ((u8*)req->buf)[0] = 0x00;
9071 +                       ((u8*)req->buf)[1] = 0xe3;
9072 +                       break;
9073 +               case 0x0300:
9074 +               case 0x0500:
9075 +                       ((u8*)req->buf)[0] = 0x00;
9076 +                       break;
9077 +               }
9078 +               //((u8*)req->buf)[0] = 0x81;
9079 +               //((u8*)req->buf)[1] = 0x81;
9080 +               value = ctrl->wLength;
9081 +               break;
9082 +       case 0x82:
9083 +               switch (ctrl->wValue) {
9084 +               case 0x0201:
9085 +               case 0x0202:
9086 +                       ((u8*)req->buf)[0] = 0x00;
9087 +                       ((u8*)req->buf)[1] = 0xc3;
9088 +                       break;
9089 +               case 0x0300:
9090 +               case 0x0500:
9091 +                       ((u8*)req->buf)[0] = 0x00;
9092 +                       break;
9093 +               }
9094 +               //((u8*)req->buf)[0] = 0x82;
9095 +               //((u8*)req->buf)[1] = 0x82;
9096 +               value = ctrl->wLength;
9097 +               break;
9098 +       case 0x83:
9099 +               switch (ctrl->wValue) {
9100 +               case 0x0201:
9101 +               case 0x0202:
9102 +                       ((u8*)req->buf)[0] = 0x00;
9103 +                       ((u8*)req->buf)[1] = 0x00;
9104 +                       break;
9105 +               case 0x0300:
9106 +                       ((u8*)req->buf)[0] = 0x60;
9107 +                       break;
9108 +               case 0x0500:    
9109 +                       ((u8*)req->buf)[0] = 0x18;
9110 +                       break;
9111 +               }
9112 +               //((u8*)req->buf)[0] = 0x83;
9113 +               //((u8*)req->buf)[1] = 0x83;
9114 +               value = ctrl->wLength;
9115 +               break;
9116 +       case 0x84:
9117 +               switch (ctrl->wValue) {
9118 +               case 0x0201:
9119 +               case 0x0202:
9120 +                       ((u8*)req->buf)[0] = 0x00;
9121 +                       ((u8*)req->buf)[1] = 0x01;
9122 +                       break;
9123 +               case 0x0300:
9124 +               case 0x0500:
9125 +                       ((u8*)req->buf)[0] = 0x08;
9126 +                       break;
9127 +               }
9128 +               //((u8*)req->buf)[0] = 0x84;
9129 +               //((u8*)req->buf)[1] = 0x84;
9130 +               value = ctrl->wLength;
9131 +               break;
9132 +       case 0x85:
9133 +               ((u8*)req->buf)[0] = 0x85;
9134 +               ((u8*)req->buf)[1] = 0x85;
9135 +               value = ctrl->wLength;
9136 +               break;
9137 +
9138 +       
9139 +       default:
9140 +unknown:
9141 +               printk("unknown control req%02x.%02x v%04x i%04x l%d\n",
9142 +                       ctrl->bRequestType, ctrl->bRequest,
9143 +                       ctrl->wValue, ctrl->wIndex, ctrl->wLength);
9144 +       }
9145 +
9146 +       /* respond with data transfer before status phase? */
9147 +       if (value >= 0) {
9148 +               req->length = value;
9149 +               req->zero = value < ctrl->wLength
9150 +                               && (value % gadget->ep0->maxpacket) == 0;
9151 +               value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
9152 +               if (value < 0) {
9153 +                       DBG (dev, "ep_queue < 0 --> %d\n", value);
9154 +                       req->status = 0;
9155 +                       zero_setup_complete (gadget->ep0, req);
9156 +               }
9157 +       }
9158 +
9159 +       /* device either stalls (value < 0) or reports success */
9160 +       return value;
9161 +}
9162 +
9163 +static void
9164 +zero_disconnect (struct usb_gadget *gadget)
9165 +{
9166 +       struct zero_dev         *dev = get_gadget_data (gadget);
9167 +       unsigned long           flags;
9168 +
9169 +       spin_lock_irqsave (&dev->lock, flags);
9170 +       zero_reset_config (dev);
9171 +
9172 +       /* a more significant application might have some non-usb
9173 +        * activities to quiesce here, saving resources like power
9174 +        * or pushing the notification up a network stack.
9175 +        */
9176 +       spin_unlock_irqrestore (&dev->lock, flags);
9177 +
9178 +       /* next we may get setup() calls to enumerate new connections;
9179 +        * or an unbind() during shutdown (including removing module).
9180 +        */
9181 +}
9182 +
9183 +static void
9184 +zero_autoresume (unsigned long _dev)
9185 +{
9186 +       struct zero_dev *dev = (struct zero_dev *) _dev;
9187 +       int             status;
9188 +
9189 +       /* normally the host would be woken up for something
9190 +        * more significant than just a timer firing...
9191 +        */
9192 +       if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
9193 +               status = usb_gadget_wakeup (dev->gadget);
9194 +               DBG (dev, "wakeup --> %d\n", status);
9195 +       }
9196 +}
9197 +
9198 +/*-------------------------------------------------------------------------*/
9199 +
9200 +static void
9201 +zero_unbind (struct usb_gadget *gadget)
9202 +{
9203 +       struct zero_dev         *dev = get_gadget_data (gadget);
9204 +
9205 +       DBG (dev, "unbind\n");
9206 +
9207 +       /* we've already been disconnected ... no i/o is active */
9208 +       if (dev->req)
9209 +               free_ep_req (gadget->ep0, dev->req);
9210 +       del_timer_sync (&dev->resume);
9211 +       kfree (dev);
9212 +       set_gadget_data (gadget, NULL);
9213 +}
9214 +
9215 +static int
9216 +zero_bind (struct usb_gadget *gadget)
9217 +{
9218 +       struct zero_dev         *dev;
9219 +       //struct usb_ep         *ep;
9220 +
9221 +       printk("binding\n");
9222 +       /*
9223 +        * DRIVER POLICY CHOICE:  you may want to do this differently.
9224 +        * One thing to avoid is reusing a bcdDevice revision code
9225 +        * with different host-visible configurations or behavior
9226 +        * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
9227 +        */
9228 +       //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
9229 +
9230 +
9231 +       /* ok, we made sense of the hardware ... */
9232 +       dev = kmalloc (sizeof *dev, SLAB_KERNEL);
9233 +       if (!dev)
9234 +               return -ENOMEM;
9235 +       memset (dev, 0, sizeof *dev);
9236 +       spin_lock_init (&dev->lock);
9237 +       dev->gadget = gadget;
9238 +       set_gadget_data (gadget, dev);
9239 +
9240 +       /* preallocate control response and buffer */
9241 +       dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
9242 +       if (!dev->req)
9243 +               goto enomem;
9244 +       dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
9245 +                               &dev->req->dma, GFP_KERNEL);
9246 +       if (!dev->req->buf)
9247 +               goto enomem;
9248 +
9249 +       dev->req->complete = zero_setup_complete;
9250 +
9251 +       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
9252 +
9253 +#ifdef CONFIG_USB_GADGET_DUALSPEED
9254 +       /* assume ep0 uses the same value for both speeds ... */
9255 +       dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
9256 +
9257 +       /* and that all endpoints are dual-speed */
9258 +       //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
9259 +       //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
9260 +#endif
9261 +
9262 +       usb_gadget_set_selfpowered (gadget);
9263 +
9264 +       init_timer (&dev->resume);
9265 +       dev->resume.function = zero_autoresume;
9266 +       dev->resume.data = (unsigned long) dev;
9267 +
9268 +       gadget->ep0->driver_data = dev;
9269 +
9270 +       INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
9271 +       INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
9272 +               EP_OUT_NAME, EP_IN_NAME);
9273 +
9274 +       snprintf (manufacturer, sizeof manufacturer,
9275 +               UTS_SYSNAME " " UTS_RELEASE " with %s",
9276 +               gadget->name);
9277 +
9278 +       return 0;
9279 +
9280 +enomem:
9281 +       zero_unbind (gadget);
9282 +       return -ENOMEM;
9283 +}
9284 +
9285 +/*-------------------------------------------------------------------------*/
9286 +
9287 +static void
9288 +zero_suspend (struct usb_gadget *gadget)
9289 +{
9290 +       struct zero_dev         *dev = get_gadget_data (gadget);
9291 +
9292 +       if (gadget->speed == USB_SPEED_UNKNOWN)
9293 +               return;
9294 +
9295 +       if (autoresume) {
9296 +               mod_timer (&dev->resume, jiffies + (HZ * autoresume));
9297 +               DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
9298 +       } else
9299 +               DBG (dev, "suspend\n");
9300 +}
9301 +
9302 +static void
9303 +zero_resume (struct usb_gadget *gadget)
9304 +{
9305 +       struct zero_dev         *dev = get_gadget_data (gadget);
9306 +
9307 +       DBG (dev, "resume\n");
9308 +       del_timer (&dev->resume);
9309 +}
9310 +
9311 +
9312 +/*-------------------------------------------------------------------------*/
9313 +
9314 +static struct usb_gadget_driver zero_driver = {
9315 +#ifdef CONFIG_USB_GADGET_DUALSPEED
9316 +       .speed          = USB_SPEED_HIGH,
9317 +#else
9318 +       .speed          = USB_SPEED_FULL,
9319 +#endif
9320 +       .function       = (char *) longname,
9321 +       .bind           = zero_bind,
9322 +       .unbind         = zero_unbind,
9323 +
9324 +       .setup          = zero_setup,
9325 +       .disconnect     = zero_disconnect,
9326 +
9327 +       .suspend        = zero_suspend,
9328 +       .resume         = zero_resume,
9329 +
9330 +       .driver         = {
9331 +               .name           = (char *) shortname,
9332 +               // .shutdown = ...
9333 +               // .suspend = ...
9334 +               // .resume = ...
9335 +       },
9336 +};
9337 +
9338 +MODULE_AUTHOR ("David Brownell");
9339 +MODULE_LICENSE ("Dual BSD/GPL");
9340 +
9341 +static struct proc_dir_entry *pdir, *pfile;
9342 +
9343 +static int isoc_read_data (char *page, char **start,
9344 +                          off_t off, int count,
9345 +                          int *eof, void *data)
9346 +{
9347 +       int i;
9348 +       static int c = 0;
9349 +       static int done = 0;
9350 +       static int s = 0;
9351 +
9352 +/*
9353 +       printk ("\ncount: %d\n", count);
9354 +       printk ("rbuf_start: %d\n", rbuf_start);
9355 +       printk ("rbuf_len: %d\n", rbuf_len);
9356 +       printk ("off: %d\n", off);
9357 +       printk ("start: %p\n\n", *start);
9358 +*/
9359 +       if (done) {
9360 +               c = 0;
9361 +               done = 0;
9362 +               *eof = 1;
9363 +               return 0;
9364 +       }
9365 +
9366 +       if (c == 0) {
9367 +               if (rbuf_len == RBUF_LEN)
9368 +                       s = rbuf_start;
9369 +               else s = 0;
9370 +       }
9371 +
9372 +       for (i=0; i<count && c<rbuf_len; i++, c++) {
9373 +               page[i] = rbuf[(c+s) % RBUF_LEN];
9374 +       }
9375 +       *start = page;
9376 +       
9377 +       if (c >= rbuf_len) {
9378 +               *eof = 1;
9379 +               done = 1;
9380 +       }
9381 +
9382 +
9383 +       return i;
9384 +}
9385 +
9386 +static int __init init (void)
9387 +{
9388 +
9389 +       int retval = 0;
9390 +
9391 +       pdir = proc_mkdir("isoc_test", NULL);
9392 +       if(pdir == NULL) {
9393 +               retval = -ENOMEM;
9394 +               printk("Error creating dir\n");
9395 +               goto done;
9396 +       }
9397 +       pdir->owner = THIS_MODULE;
9398 +
9399 +       pfile = create_proc_read_entry("isoc_data",
9400 +                                      0444, pdir,
9401 +                                      isoc_read_data,
9402 +                                      NULL);
9403 +       if (pfile == NULL) {
9404 +               retval = -ENOMEM;
9405 +               printk("Error creating file\n");
9406 +               goto no_file;
9407 +       }
9408 +       pfile->owner = THIS_MODULE;
9409 +
9410 +       return usb_gadget_register_driver (&zero_driver);
9411 +
9412 + no_file:
9413 +       remove_proc_entry("isoc_data", NULL);
9414 + done:
9415 +       return retval;
9416 +}
9417 +module_init (init);
9418 +
9419 +static void __exit cleanup (void)
9420 +{
9421 +
9422 +       usb_gadget_unregister_driver (&zero_driver);
9423 +       
9424 +       remove_proc_entry("isoc_data", pdir);
9425 +       remove_proc_entry("isoc_test", NULL);
9426 +}
9427 +module_exit (cleanup);
9428 --- /dev/null
9429 +++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h
9430 @@ -0,0 +1,142 @@
9431 +/* ==========================================================================
9432 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
9433 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9434 + * otherwise expressly agreed to in writing between Synopsys and you.
9435 + * 
9436 + * The Software IS NOT an item of Licensed Software or Licensed Product under
9437 + * any End User Software License Agreement or Agreement for Licensed Product
9438 + * with Synopsys or any supplement thereto. You are permitted to use and
9439 + * redistribute this Software in source and binary forms, with or without
9440 + * modification, provided that redistributions of source code must retain this
9441 + * notice. You may not view, use, disclose, copy or distribute this file or
9442 + * any information contained herein except pursuant to this license grant from
9443 + * Synopsys. If you do not agree with this notice, including the disclaimer
9444 + * below, then you are not authorized to use the Software.
9445 + * 
9446 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
9447 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9448 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9449 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
9450 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
9451 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
9452 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
9453 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9454 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9455 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9456 + * DAMAGE.
9457 + * ========================================================================== */
9458 +
9459 +#if !defined(__DWC_CFI_COMMON_H__)
9460 +#define __DWC_CFI_COMMON_H__
9461 +
9462 +//#include <linux/types.h>
9463 +
9464 +/**
9465 + * @file 
9466 + *
9467 + * This file contains the CFI specific common constants, interfaces
9468 + * (functions and macros) and structures for Linux. No PCD specific
9469 + * data structure or definition is to be included in this file.
9470 + *
9471 + */
9472 +
9473 +/** This is a request for all Core Features */
9474 +#define VEN_CORE_GET_FEATURES          0xB1
9475 +
9476 +/** This is a request to get the value of a specific Core Feature */
9477 +#define VEN_CORE_GET_FEATURE           0xB2
9478 +
9479 +/** This command allows the host to set the value of a specific Core Feature */
9480 +#define VEN_CORE_SET_FEATURE           0xB3
9481 +
9482 +/** This command allows the host to set the default values of 
9483 + * either all or any specific Core Feature 
9484 + */
9485 +#define VEN_CORE_RESET_FEATURES                0xB4
9486 +
9487 +/** This command forces the PCD to write the deferred values of a Core Features */
9488 +#define VEN_CORE_ACTIVATE_FEATURES     0xB5
9489 +
9490 +/** This request reads a DWORD value from a register at the specified offset */
9491 +#define VEN_CORE_READ_REGISTER         0xB6
9492 +
9493 +/** This request writes a DWORD value into a register at the specified offset */
9494 +#define VEN_CORE_WRITE_REGISTER                0xB7
9495 +
9496 +/** This structure is the header of the Core Features dataset returned to 
9497 + *  the Host
9498 + */
9499 +struct cfi_all_features_header {
9500 +/** The features header structure length is */
9501 +#define CFI_ALL_FEATURES_HDR_LEN               8
9502 +       /**
9503 +        * The total length of the features dataset returned to the Host 
9504 +        */
9505 +       uint16_t wTotalLen;
9506 +
9507 +       /**
9508 +        * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H).
9509 +        * This field identifies the version of the CFI Specification with which 
9510 +        * the device is compliant.
9511 +        */
9512 +       uint16_t wVersion;
9513 +
9514 +       /** The ID of the Core */
9515 +       uint16_t wCoreID;
9516 +#define CFI_CORE_ID_UDC                1
9517 +#define CFI_CORE_ID_OTG                2
9518 +#define CFI_CORE_ID_WUDEV      3
9519 +
9520 +       /** Number of features returned by VEN_CORE_GET_FEATURES request */
9521 +       uint16_t wNumFeatures;
9522 +} UPACKED;
9523 +
9524 +typedef struct cfi_all_features_header cfi_all_features_header_t;
9525 +
9526 +/** This structure is a header of the Core Feature descriptor dataset returned to 
9527 + *  the Host after the VEN_CORE_GET_FEATURES request
9528 + */
9529 +struct cfi_feature_desc_header {
9530 +#define CFI_FEATURE_DESC_HDR_LEN       8
9531 +
9532 +       /** The feature ID */
9533 +       uint16_t wFeatureID;
9534 +
9535 +       /** Length of this feature descriptor in bytes - including the
9536 +        * length of the feature name string
9537 +        */
9538 +       uint16_t wLength;
9539 +
9540 +       /** The data length of this feature in bytes */
9541 +       uint16_t wDataLength;
9542 +
9543 +       /** 
9544 +        * Attributes of this features 
9545 +        * D0: Access rights
9546 +        * 0 - Read/Write
9547 +        * 1 - Read only
9548 +        */
9549 +       uint8_t bmAttributes;
9550 +#define CFI_FEATURE_ATTR_RO            1
9551 +#define CFI_FEATURE_ATTR_RW            0
9552 +
9553 +       /** Length of the feature name in bytes */
9554 +       uint8_t bNameLen;
9555 +
9556 +       /** The feature name buffer */
9557 +       //uint8_t *name;
9558 +} UPACKED;
9559 +
9560 +typedef struct cfi_feature_desc_header cfi_feature_desc_header_t;
9561 +
9562 +/**
9563 + * This structure describes a NULL terminated string referenced by its id field.
9564 + * It is very similar to usb_string structure but has the id field type set to 16-bit.
9565 + */
9566 +struct cfi_string {
9567 +       uint16_t id;
9568 +       const uint8_t *s;
9569 +};
9570 +typedef struct cfi_string cfi_string_t;
9571 +
9572 +#endif
9573 --- /dev/null
9574 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
9575 @@ -0,0 +1,1316 @@
9576 +/* ==========================================================================
9577 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
9578 + * $Revision: #35 $
9579 + * $Date: 2009/04/03 $
9580 + * $Change: 1225160 $
9581 + *
9582 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
9583 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9584 + * otherwise expressly agreed to in writing between Synopsys and you.
9585 + *
9586 + * The Software IS NOT an item of Licensed Software or Licensed Product under
9587 + * any End User Software License Agreement or Agreement for Licensed Product
9588 + * with Synopsys or any supplement thereto. You are permitted to use and
9589 + * redistribute this Software in source and binary forms, with or without
9590 + * modification, provided that redistributions of source code must retain this
9591 + * notice. You may not view, use, disclose, copy or distribute this file or
9592 + * any information contained herein except pursuant to this license grant from
9593 + * Synopsys. If you do not agree with this notice, including the disclaimer
9594 + * below, then you are not authorized to use the Software.
9595 + *
9596 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
9597 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9598 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9599 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
9600 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
9601 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
9602 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
9603 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9604 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9605 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9606 + * DAMAGE.
9607 + * ========================================================================== */
9608 +
9609 +/** @file
9610 + *
9611 + * The diagnostic interface will provide access to the controller for
9612 + * bringing up the hardware and testing.  The Linux driver attributes
9613 + * feature will be used to provide the Linux Diagnostic
9614 + * Interface. These attributes are accessed through sysfs.
9615 + */
9616 +
9617 +/** @page "Linux Module Attributes"
9618 + *
9619 + * The Linux module attributes feature is used to provide the Linux
9620 + * Diagnostic Interface.  These attributes are accessed through sysfs.
9621 + * The diagnostic interface will provide access to the controller for
9622 + * bringing up the hardware and testing.
9623 +
9624 + The following table shows the attributes.
9625 + <table>
9626 + <tr>
9627 + <td><b> Name</b></td>
9628 + <td><b> Description</b></td>
9629 + <td><b> Access</b></td>
9630 + </tr>
9631 +
9632 + <tr>
9633 + <td> mode </td>
9634 + <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
9635 + <td> Read</td>
9636 + </tr>
9637 +
9638 + <tr>
9639 + <td> hnpcapable </td>
9640 + <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
9641 + Read returns the current value.</td>
9642 + <td> Read/Write</td>
9643 + </tr>
9644 +
9645 + <tr>
9646 + <td> srpcapable </td>
9647 + <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
9648 + Read returns the current value.</td>
9649 + <td> Read/Write</td>
9650 + </tr>
9651 +
9652 + <tr>
9653 + <td> hsic_connect </td>
9654 + <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register.
9655 + Read returns the current value.</td>
9656 + <td> Read/Write</td>
9657 + </tr>
9658 +
9659 + <tr>
9660 + <td> inv_sel_hsic </td>
9661 + <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register.
9662 + Read returns the current value.</td>
9663 + <td> Read/Write</td>
9664 + </tr>
9665 +
9666 + <tr>
9667 + <td> hnp </td>
9668 + <td> Initiates the Host Negotiation Protocol.  Read returns the status.</td>
9669 + <td> Read/Write</td>
9670 + </tr>
9671 +
9672 + <tr>
9673 + <td> srp </td>
9674 + <td> Initiates the Session Request Protocol.  Read returns the status.</td>
9675 + <td> Read/Write</td>
9676 + </tr>
9677 +
9678 + <tr>
9679 + <td> buspower </td>
9680 + <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
9681 + <td> Read/Write</td>
9682 + </tr>
9683 +
9684 + <tr>
9685 + <td> bussuspend </td>
9686 + <td> Suspends the USB bus.</td>
9687 + <td> Read/Write</td>
9688 + </tr>
9689 +
9690 + <tr>
9691 + <td> busconnected </td>
9692 + <td> Gets the connection status of the bus</td>
9693 + <td> Read</td>
9694 + </tr>
9695 +
9696 + <tr>
9697 + <td> gotgctl </td>
9698 + <td> Gets or sets the Core Control Status Register.</td>
9699 + <td> Read/Write</td>
9700 + </tr>
9701 +
9702 + <tr>
9703 + <td> gusbcfg </td>
9704 + <td> Gets or sets the Core USB Configuration Register</td>
9705 + <td> Read/Write</td>
9706 + </tr>
9707 +
9708 + <tr>
9709 + <td> grxfsiz </td>
9710 + <td> Gets or sets the Receive FIFO Size Register</td>
9711 + <td> Read/Write</td>
9712 + </tr>
9713 +
9714 + <tr>
9715 + <td> gnptxfsiz </td>
9716 + <td> Gets or sets the non-periodic Transmit Size Register</td>
9717 + <td> Read/Write</td>
9718 + </tr>
9719 +
9720 + <tr>
9721 + <td> gpvndctl </td>
9722 + <td> Gets or sets the PHY Vendor Control Register</td>
9723 + <td> Read/Write</td>
9724 + </tr>
9725 +
9726 + <tr>
9727 + <td> ggpio </td>
9728 + <td> Gets the value in the lower 16-bits of the General Purpose IO Register
9729 + or sets the upper 16 bits.</td>
9730 + <td> Read/Write</td>
9731 + </tr>
9732 +
9733 + <tr>
9734 + <td> guid </td>
9735 + <td> Gets or sets the value of the User ID Register</td>
9736 + <td> Read/Write</td>
9737 + </tr>
9738 +
9739 + <tr>
9740 + <td> gsnpsid </td>
9741 + <td> Gets the value of the Synopsys ID Regester</td>
9742 + <td> Read</td>
9743 + </tr>
9744 +
9745 + <tr>
9746 + <td> devspeed </td>
9747 + <td> Gets or sets the device speed setting in the DCFG register</td>
9748 + <td> Read/Write</td>
9749 + </tr>
9750 +
9751 + <tr>
9752 + <td> enumspeed </td>
9753 + <td> Gets the device enumeration Speed.</td>
9754 + <td> Read</td>
9755 + </tr>
9756 +
9757 + <tr>
9758 + <td> hptxfsiz </td>
9759 + <td> Gets the value of the Host Periodic Transmit FIFO</td>
9760 + <td> Read</td>
9761 + </tr>
9762 +
9763 + <tr>
9764 + <td> hprt0 </td>
9765 + <td> Gets or sets the value in the Host Port Control and Status Register</td>
9766 + <td> Read/Write</td>
9767 + </tr>
9768 +
9769 + <tr>
9770 + <td> regoffset </td>
9771 + <td> Sets the register offset for the next Register Access</td>
9772 + <td> Read/Write</td>
9773 + </tr>
9774 +
9775 + <tr>
9776 + <td> regvalue </td>
9777 + <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
9778 + <td> Read/Write</td>
9779 + </tr>
9780 +
9781 + <tr>
9782 + <td> remote_wakeup </td>
9783 + <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
9784 + wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
9785 + Wakeup signalling bit in the Device Control Register is set for 1
9786 + milli-second.</td>
9787 + <td> Read/Write</td>
9788 + </tr>
9789 +
9790 + <tr>
9791 + <td> regdump </td>
9792 + <td> Dumps the contents of core registers.</td>
9793 + <td> Read</td>
9794 + </tr>
9795 +
9796 + <tr>
9797 + <td> spramdump </td>
9798 + <td> Dumps the contents of core registers.</td>
9799 + <td> Read</td>
9800 + </tr>
9801 +
9802 + <tr>
9803 + <td> hcddump </td>
9804 + <td> Dumps the current HCD state.</td>
9805 + <td> Read</td>
9806 + </tr>
9807 +
9808 + <tr>
9809 + <td> hcd_frrem </td>
9810 + <td> Shows the average value of the Frame Remaining
9811 + field in the Host Frame Number/Frame Remaining register when an SOF interrupt
9812 + occurs. This can be used to determine the average interrupt latency. Also
9813 + shows the average Frame Remaining value for start_transfer and the "a" and
9814 + "b" sample points. The "a" and "b" sample points may be used during debugging
9815 + bto determine how long it takes to execute a section of the HCD code.</td>
9816 + <td> Read</td>
9817 + </tr>
9818 +
9819 + <tr>
9820 + <td> rd_reg_test </td>
9821 + <td> Displays the time required to read the GNPTXFSIZ register many times
9822 + (the output shows the number of times the register is read).
9823 + <td> Read</td>
9824 + </tr>
9825 +
9826 + <tr>
9827 + <td> wr_reg_test </td>
9828 + <td> Displays the time required to write the GNPTXFSIZ register many times
9829 + (the output shows the number of times the register is written).
9830 + <td> Read</td>
9831 + </tr>
9832 +
9833 + <tr>
9834 + <td> lpm_response </td>
9835 + <td> Gets or sets lpm_response mode. Applicable only in device mode.
9836 + <td> Write</td>
9837 + </tr>
9838 +
9839 + <tr>
9840 + <td> sleep_local_dev </td>
9841 + <td> Generetates sleep signaling. Applicable only in host mode.
9842 + <td> Write</td>
9843 + </tr>
9844 +
9845 + <tr>
9846 + <td> sleep_status </td>
9847 + <td> Shows sleep status of device.
9848 + <td> Read</td>
9849 + </tr>
9850 +
9851 + </table>
9852 +
9853 + Example usage:
9854 + To get the current mode:
9855 + cat /sys/devices/lm0/mode
9856 +
9857 + To power down the USB:
9858 + echo 0 > /sys/devices/lm0/buspower
9859 + */
9860 +
9861 +#include <linux/kernel.h>
9862 +#include <linux/module.h>
9863 +#include <linux/moduleparam.h>
9864 +#include <linux/init.h>
9865 +#include <linux/device.h>
9866 +#include <linux/errno.h>
9867 +#include <linux/types.h>
9868 +#include <linux/stat.h>                /* permission constants */
9869 +#include <linux/version.h>
9870 +#include <linux/param.h>
9871 +#include <linux/delay.h>
9872 +#include <linux/jiffies.h>
9873 +
9874 +
9875 +#ifdef LM_INTERFACE
9876 +#include <asm/sizes.h>
9877 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
9878 +#include <asm/arch/lm.h>
9879 +#else
9880 +/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -
9881 +   here we use definitions stolen from arm-integrator headers
9882 +*/
9883 +#include <mach/lm.h>
9884 +#endif
9885 +#elif defined(PLATFORM_INTERFACE)
9886 +#include <linux/platform_device.h>
9887 +#endif
9888 +
9889 +#include <asm/io.h>
9890 +
9891 +#include "dwc_os.h"
9892 +#include "dwc_otg_driver.h"
9893 +#include "dwc_otg_attr.h"
9894 +#include "dwc_otg_core_if.h"
9895 +#include "dwc_otg_pcd_if.h"
9896 +#include "dwc_otg_hcd_if.h"
9897 +
9898 +/*
9899 + * MACROs for defining sysfs attribute
9900 + */
9901 +#ifdef LM_INTERFACE
9902 +
9903 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
9904 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
9905 +{ \
9906 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
9907 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);             \
9908 +       uint32_t val; \
9909 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
9910 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
9911 +}
9912 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
9913 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
9914 +                                       const char *buf, size_t count) \
9915 +{ \
9916 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
9917 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
9918 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
9919 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
9920 +       return count; \
9921 +}
9922 +
9923 +#elif defined(PCI_INTERFACE)
9924 +
9925 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
9926 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
9927 +{ \
9928 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);      \
9929 +       uint32_t val; \
9930 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
9931 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
9932 +}
9933 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
9934 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
9935 +                                       const char *buf, size_t count) \
9936 +{ \
9937 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
9938 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
9939 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
9940 +       return count; \
9941 +}
9942 +
9943 +#elif defined(PLATFORM_INTERFACE)
9944 +
9945 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
9946 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
9947 +{ \
9948 +        struct platform_device *platform_dev = \
9949 +                container_of(_dev, struct platform_device, dev); \
9950 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);  \
9951 +       uint32_t val; \
9952 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
9953 +                    __func__, _dev, platform_dev, otg_dev); \
9954 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
9955 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
9956 +}
9957 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
9958 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
9959 +                                       const char *buf, size_t count) \
9960 +{ \
9961 +        struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
9962 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
9963 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
9964 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
9965 +       return count; \
9966 +}
9967 +#endif
9968 +
9969 +/*
9970 + * MACROs for defining sysfs attribute for 32-bit registers
9971 + */
9972 +#ifdef LM_INTERFACE
9973 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
9974 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
9975 +{ \
9976 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
9977 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
9978 +       uint32_t val; \
9979 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
9980 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
9981 +}
9982 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
9983 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
9984 +                                       const char *buf, size_t count) \
9985 +{ \
9986 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
9987 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
9988 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
9989 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
9990 +       return count; \
9991 +}
9992 +#elif defined(PCI_INTERFACE)
9993 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
9994 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
9995 +{ \
9996 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
9997 +       uint32_t val; \
9998 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
9999 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
10000 +}
10001 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
10002 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
10003 +                                       const char *buf, size_t count) \
10004 +{ \
10005 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
10006 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
10007 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
10008 +       return count; \
10009 +}
10010 +
10011 +#elif defined(PLATFORM_INTERFACE)
10012 +#include "dwc_otg_dbg.h"
10013 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
10014 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
10015 +{ \
10016 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
10017 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
10018 +       uint32_t val; \
10019 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
10020 +                    __func__, _dev, platform_dev, otg_dev); \
10021 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
10022 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
10023 +}
10024 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
10025 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
10026 +                                       const char *buf, size_t count) \
10027 +{ \
10028 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
10029 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
10030 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
10031 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
10032 +       return count; \
10033 +}
10034 +
10035 +#endif
10036 +
10037 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \
10038 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
10039 +DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
10040 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
10041 +
10042 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \
10043 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
10044 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
10045 +
10046 +#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
10047 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
10048 +DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
10049 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
10050 +
10051 +#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
10052 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
10053 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
10054 +
10055 +/** @name Functions for Show/Store of Attributes */
10056 +/**@{*/
10057 +
10058 +/**
10059 + * Show the register offset of the Register Access.
10060 + */
10061 +static ssize_t regoffset_show(struct device *_dev,
10062 +                             struct device_attribute *attr, char *buf)
10063 +{
10064 +#ifdef LM_INTERFACE
10065 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10066 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10067 +#elif defined(PCI_INTERFACE)
10068 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10069 +#elif defined(PLATFORM_INTERFACE)
10070 +       struct platform_device *platform_dev = container_of(_dev,
10071 +                                                    struct platform_device, dev);
10072 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10073 +#endif
10074 +
10075 +       return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",
10076 +                       otg_dev->reg_offset);
10077 +}
10078 +
10079 +/**
10080 + * Set the register offset for the next Register Access        Read/Write
10081 + */
10082 +static ssize_t regoffset_store(struct device *_dev,
10083 +                              struct device_attribute *attr,
10084 +                              const char *buf, size_t count)
10085 +{
10086 +#ifdef LM_INTERFACE
10087 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10088 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10089 +#elif defined(PCI_INTERFACE)
10090 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10091 +#elif defined(PLATFORM_INTERFACE)
10092 +       struct platform_device *platform_dev = container_of(_dev,
10093 +                                                    struct platform_device, dev);
10094 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10095 +#endif
10096 +
10097 +       uint32_t offset = simple_strtoul(buf, NULL, 16);
10098 +        if (offset < SZ_256K) {
10099 +               otg_dev->reg_offset = offset;
10100 +       } else {
10101 +               dev_err(_dev, "invalid offset\n");
10102 +       }
10103 +
10104 +       return count;
10105 +}
10106 +
10107 +DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store);
10108 +
10109 +/**
10110 + * Show the value of the register at the offset in the reg_offset
10111 + * attribute.
10112 + */
10113 +static ssize_t regvalue_show(struct device *_dev,
10114 +                            struct device_attribute *attr, char *buf)
10115 +{
10116 +#ifdef LM_INTERFACE
10117 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10118 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10119 +#elif defined(PCI_INTERFACE)
10120 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10121 +#elif defined(PLATFORM_INTERFACE)
10122 +       struct platform_device *platform_dev =
10123 +           container_of(_dev, struct platform_device, dev);
10124 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10125 +#endif
10126 +
10127 +       uint32_t val;
10128 +       volatile uint32_t *addr;
10129 +
10130 +       if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) {
10131 +               /* Calculate the address */
10132 +               addr = (uint32_t *) (otg_dev->reg_offset +
10133 +                                    (uint8_t *) otg_dev->base);
10134 +               val = dwc_read_reg32(addr);
10135 +               return snprintf(buf,
10136 +                               sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1,
10137 +                               "Reg@0x%06x = 0x%08x\n", otg_dev->reg_offset,
10138 +                               val);
10139 +       } else {
10140 +               dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->reg_offset);
10141 +               return sprintf(buf, "invalid offset\n");
10142 +       }
10143 +}
10144 +
10145 +/**
10146 + * Store the value in the register at the offset in the reg_offset
10147 + * attribute.
10148 + *
10149 + */
10150 +static ssize_t regvalue_store(struct device *_dev,
10151 +                             struct device_attribute *attr,
10152 +                             const char *buf, size_t count)
10153 +{
10154 +#ifdef LM_INTERFACE
10155 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10156 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10157 +#elif defined(PCI_INTERFACE)
10158 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10159 +#elif defined(PLATFORM_INTERFACE)
10160 +       struct platform_device *platform_dev =
10161 +           container_of(_dev, struct platform_device, dev);
10162 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10163 +#endif
10164 +
10165 +       volatile uint32_t *addr;
10166 +       uint32_t val = simple_strtoul(buf, NULL, 16);
10167 +       //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
10168 +       if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) {
10169 +               /* Calculate the address */
10170 +               addr = (uint32_t *) (otg_dev->reg_offset +
10171 +                                    (uint8_t *) otg_dev->base);
10172 +               dwc_write_reg32(addr, val);
10173 +       } else {
10174 +               dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
10175 +                       otg_dev->reg_offset);
10176 +       }
10177 +       return count;
10178 +}
10179 +
10180 +DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store);
10181 +
10182 +/*
10183 + * Attributes
10184 + */
10185 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode");
10186 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable");
10187 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "Mode");
10188 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect");
10189 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC");
10190 +
10191 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
10192 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
10193 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected");
10194 +
10195 +DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL");
10196 +DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,
10197 +                            &(otg_dev->core_if->core_global_regs->gusbcfg),
10198 +                            "GUSBCFG");
10199 +DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,
10200 +                            &(otg_dev->core_if->core_global_regs->grxfsiz),
10201 +                            "GRXFSIZ");
10202 +DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,
10203 +                            &(otg_dev->core_if->core_global_regs->gnptxfsiz),
10204 +                            "GNPTXFSIZ");
10205 +DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,
10206 +                            &(otg_dev->core_if->core_global_regs->gpvndctl),
10207 +                            "GPVNDCTL");
10208 +DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,
10209 +                            &(otg_dev->core_if->core_global_regs->ggpio),
10210 +                            "GGPIO");
10211 +DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid),
10212 +                            "GUID");
10213 +DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,
10214 +                            &(otg_dev->core_if->core_global_regs->gsnpsid),
10215 +                            "GSNPSID");
10216 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed");
10217 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed");
10218 +
10219 +DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,
10220 +                            &(otg_dev->core_if->core_global_regs->hptxfsiz),
10221 +                            "HPTXFSIZ");
10222 +DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0");
10223 +
10224 +/**
10225 + * @todo Add code to initiate the HNP.
10226 + */
10227 +/**
10228 + * Show the HNP status bit
10229 + */
10230 +static ssize_t hnp_show(struct device *_dev,
10231 +                       struct device_attribute *attr, char *buf)
10232 +{
10233 +#ifdef LM_INTERFACE
10234 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10235 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10236 +#elif defined(PCI_INTERFACE)
10237 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10238 +#elif defined(PLATFORM_INTERFACE)
10239 +       struct platform_device *platform_dev =
10240 +           container_of(_dev, struct platform_device, dev);
10241 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10242 +#endif
10243 +       return sprintf(buf, "HstNegScs = 0x%x\n",
10244 +                      dwc_otg_get_hnpstatus(otg_dev->core_if));
10245 +}
10246 +
10247 +/**
10248 + * Set the HNP Request bit
10249 + */
10250 +static ssize_t hnp_store(struct device *_dev,
10251 +                        struct device_attribute *attr,
10252 +                        const char *buf, size_t count)
10253 +{
10254 +#ifdef LM_INTERFACE
10255 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10256 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10257 +#elif defined(PCI_INTERFACE)
10258 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10259 +#elif defined(PLATFORM_INTERFACE)
10260 +       struct platform_device *platform_dev =
10261 +           container_of(_dev, struct platform_device, dev);
10262 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10263 +#endif
10264 +       uint32_t in = simple_strtoul(buf, NULL, 16);
10265 +       dwc_otg_set_hnpreq(otg_dev->core_if, in);
10266 +       return count;
10267 +}
10268 +
10269 +DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
10270 +
10271 +/**
10272 + * @todo Add code to initiate the SRP.
10273 + */
10274 +/**
10275 + * Show the SRP status bit
10276 + */
10277 +static ssize_t srp_show(struct device *_dev,
10278 +                       struct device_attribute *attr, char *buf)
10279 +{
10280 +#ifndef DWC_HOST_ONLY
10281 +#ifdef LM_INTERFACE
10282 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10283 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10284 +#elif defined(PCI_INTERFACE)
10285 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10286 +#elif defined(PLATFORM_INTERFACE)
10287 +       struct platform_device *platform_dev =
10288 +           container_of(_dev, struct platform_device, dev);
10289 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10290 +#endif
10291 +       return sprintf(buf, "SesReqScs = 0x%x\n",
10292 +                      dwc_otg_get_srpstatus(otg_dev->core_if));
10293 +#else
10294 +       return sprintf(buf, "Host Only Mode!\n");
10295 +#endif
10296 +}
10297 +
10298 +/**
10299 + * Set the SRP Request bit
10300 + */
10301 +static ssize_t srp_store(struct device *_dev,
10302 +                        struct device_attribute *attr,
10303 +                        const char *buf, size_t count)
10304 +{
10305 +#ifndef DWC_HOST_ONLY
10306 +#ifdef LM_INTERFACE
10307 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10308 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10309 +#elif defined(PCI_INTERFACE)
10310 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10311 +#elif defined(PLATFORM_INTERFACE)
10312 +       struct platform_device *platform_dev =
10313 +           container_of(_dev, struct platform_device, dev);
10314 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10315 +#endif
10316 +       dwc_otg_pcd_initiate_srp(otg_dev->pcd);
10317 +#endif
10318 +       return count;
10319 +}
10320 +
10321 +DEVICE_ATTR(srp, 0644, srp_show, srp_store);
10322 +
10323 +/**
10324 + * @todo Need to do more for power on/off?
10325 + */
10326 +/**
10327 + * Show the Bus Power status
10328 + */
10329 +static ssize_t buspower_show(struct device *_dev,
10330 +                            struct device_attribute *attr, char *buf)
10331 +{
10332 +#ifdef LM_INTERFACE
10333 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10334 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10335 +#elif defined(PCI_INTERFACE)
10336 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10337 +#elif defined(PLATFORM_INTERFACE)
10338 +       struct platform_device *platform_dev =
10339 +           container_of(_dev, struct platform_device, dev);
10340 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10341 +#endif
10342 +       return sprintf(buf, "Bus Power = 0x%x\n",
10343 +                      dwc_otg_get_prtpower(otg_dev->core_if));
10344 +}
10345 +
10346 +/**
10347 + * Set the Bus Power status
10348 + */
10349 +static ssize_t buspower_store(struct device *_dev,
10350 +                             struct device_attribute *attr,
10351 +                             const char *buf, size_t count)
10352 +{
10353 +#ifdef LM_INTERFACE
10354 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10355 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10356 +#elif defined(PCI_INTERFACE)
10357 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10358 +#elif defined(PLATFORM_INTERFACE)
10359 +       struct platform_device *platform_dev =
10360 +           container_of(_dev, struct platform_device, dev);
10361 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10362 +#endif
10363 +       uint32_t on = simple_strtoul(buf, NULL, 16);
10364 +       dwc_otg_set_prtpower(otg_dev->core_if, on);
10365 +       return count;
10366 +}
10367 +
10368 +DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
10369 +
10370 +/**
10371 + * @todo Need to do more for suspend?
10372 + */
10373 +/**
10374 + * Show the Bus Suspend status
10375 + */
10376 +static ssize_t bussuspend_show(struct device *_dev,
10377 +                              struct device_attribute *attr, char *buf)
10378 +{
10379 +#ifdef LM_INTERFACE
10380 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10381 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10382 +#elif defined(PCI_INTERFACE)
10383 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10384 +#elif defined(PLATFORM_INTERFACE)
10385 +       struct platform_device *platform_dev =
10386 +           container_of(_dev, struct platform_device, dev);
10387 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10388 +#endif
10389 +
10390 +       return sprintf(buf, "Bus Suspend = 0x%x\n",
10391 +                      dwc_otg_get_prtsuspend(otg_dev->core_if));
10392 +}
10393 +
10394 +/**
10395 + * Set the Bus Suspend status
10396 + */
10397 +static ssize_t bussuspend_store(struct device *_dev,
10398 +                               struct device_attribute *attr,
10399 +                               const char *buf, size_t count)
10400 +{
10401 +#ifdef LM_INTERFACE
10402 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10403 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10404 +#elif defined(PCI_INTERFACE)
10405 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10406 +#elif defined(PLATFORM_INTERFACE)
10407 +       struct platform_device *platform_dev =
10408 +           container_of(_dev, struct platform_device, dev);
10409 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10410 +#endif
10411 +
10412 +       uint32_t in = simple_strtoul(buf, NULL, 16);
10413 +       dwc_otg_set_prtsuspend(otg_dev->core_if, in);
10414 +       return count;
10415 +}
10416 +
10417 +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
10418 +
10419 +/**
10420 + * Show the status of Remote Wakeup.
10421 + */
10422 +static ssize_t remote_wakeup_show(struct device *_dev,
10423 +                                 struct device_attribute *attr, char *buf)
10424 +{
10425 +#ifndef DWC_HOST_ONLY
10426 +#ifdef LM_INTERFACE
10427 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10428 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10429 +#elif defined(PCI_INTERFACE)
10430 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10431 +#elif defined(PLATFORM_INTERFACE)
10432 +       struct platform_device *platform_dev =
10433 +           container_of(_dev, struct platform_device, dev);
10434 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10435 +#endif
10436 +
10437 +       return sprintf(buf,
10438 +                      "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n",
10439 +                      dwc_otg_get_remotewakesig(otg_dev->core_if),
10440 +                      dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd),
10441 +                      dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if));
10442 +#else
10443 +       return sprintf(buf, "Host Only Mode!\n");
10444 +#endif /* DWC_HOST_ONLY */
10445 +}
10446 +
10447 +/**
10448 + * Initiate a remote wakeup of the host.  The Device control register
10449 + * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
10450 + * flag is set.
10451 + *
10452 + */
10453 +static ssize_t remote_wakeup_store(struct device *_dev,
10454 +                                  struct device_attribute *attr,
10455 +                                  const char *buf, size_t count)
10456 +{
10457 +#ifndef DWC_HOST_ONLY
10458 +#ifdef LM_INTERFACE
10459 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10460 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10461 +#elif defined(PCI_INTERFACE)
10462 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10463 +#elif defined(PLATFORM_INTERFACE)
10464 +       struct platform_device *platform_dev =
10465 +           container_of(_dev, struct platform_device, dev);
10466 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10467 +#endif
10468 +
10469 +       uint32_t val = simple_strtoul(buf, NULL, 16);
10470 +
10471 +       if (val & 1) {
10472 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
10473 +       } else {
10474 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
10475 +       }
10476 +#endif /* DWC_HOST_ONLY */
10477 +       return count;
10478 +}
10479 +
10480 +DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show,
10481 +           remote_wakeup_store);
10482 +
10483 +/**
10484 + * Dump global registers and either host or device registers (depending on the
10485 + * current mode of the core).
10486 + */
10487 +static ssize_t regdump_show(struct device *_dev,
10488 +                           struct device_attribute *attr, char *buf)
10489 +{
10490 +#ifdef LM_INTERFACE
10491 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10492 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10493 +#elif defined(PCI_INTERFACE)
10494 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10495 +#elif defined(PLATFORM_INTERFACE)
10496 +       struct platform_device *platform_dev =
10497 +           container_of(_dev, struct platform_device, dev);
10498 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10499 +#endif
10500 +
10501 +       dwc_otg_dump_global_registers(otg_dev->core_if);
10502 +       if (dwc_otg_is_host_mode(otg_dev->core_if)) {
10503 +               dwc_otg_dump_host_registers(otg_dev->core_if);
10504 +       } else {
10505 +               dwc_otg_dump_dev_registers(otg_dev->core_if);
10506 +
10507 +       }
10508 +       return sprintf(buf, "Register Dump\n");
10509 +}
10510 +
10511 +DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
10512 +
10513 +/**
10514 + * Dump global registers and either host or device registers (depending on the
10515 + * current mode of the core).
10516 + */
10517 +static ssize_t spramdump_show(struct device *_dev,
10518 +                             struct device_attribute *attr, char *buf)
10519 +{
10520 +#ifdef LM_INTERFACE
10521 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10522 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10523 +#elif defined(PCI_INTERFACE)
10524 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10525 +#elif defined(PLATFORM_INTERFACE)
10526 +       struct platform_device *platform_dev =
10527 +           container_of(_dev, struct platform_device, dev);
10528 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10529 +#endif
10530 +
10531 +       dwc_otg_dump_spram(otg_dev->core_if);
10532 +
10533 +       return sprintf(buf, "SPRAM Dump\n");
10534 +}
10535 +
10536 +DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
10537 +
10538 +/**
10539 + * Dump the current hcd state.
10540 + */
10541 +static ssize_t hcddump_show(struct device *_dev,
10542 +                           struct device_attribute *attr, char *buf)
10543 +{
10544 +#ifndef DWC_DEVICE_ONLY
10545 +#ifdef LM_INTERFACE
10546 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10547 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10548 +#elif defined(PCI_INTERFACE)
10549 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10550 +#elif defined(PLATFORM_INTERFACE)
10551 +       struct platform_device *platform_dev =
10552 +           container_of(_dev, struct platform_device, dev);
10553 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10554 +#endif
10555 +
10556 +       dwc_otg_hcd_dump_state(otg_dev->hcd);
10557 +#endif /* DWC_DEVICE_ONLY */
10558 +       return sprintf(buf, "HCD Dump\n");
10559 +}
10560 +
10561 +DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
10562 +
10563 +/**
10564 + * Dump the average frame remaining at SOF. This can be used to
10565 + * determine average interrupt latency. Frame remaining is also shown for
10566 + * start transfer and two additional sample points.
10567 + */
10568 +static ssize_t hcd_frrem_show(struct device *_dev,
10569 +                             struct device_attribute *attr, char *buf)
10570 +{
10571 +#ifndef DWC_DEVICE_ONLY
10572 +#ifdef LM_INTERFACE
10573 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10574 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10575 +#elif defined(PCI_INTERFACE)
10576 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10577 +#elif defined(PLATFORM_INTERFACE)
10578 +       struct platform_device *platform_dev =
10579 +           container_of(_dev, struct platform_device, dev);
10580 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10581 +#endif
10582 +
10583 +       dwc_otg_hcd_dump_frrem(otg_dev->hcd);
10584 +#endif /* DWC_DEVICE_ONLY */
10585 +       return sprintf(buf, "HCD Dump Frame Remaining\n");
10586 +}
10587 +
10588 +DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
10589 +
10590 +/**
10591 + * Displays the time required to read the GNPTXFSIZ register many times (the
10592 + * output shows the number of times the register is read).
10593 + */
10594 +#define RW_REG_COUNT 10000000
10595 +#define MSEC_PER_JIFFIE 1000/HZ
10596 +static ssize_t rd_reg_test_show(struct device *_dev,
10597 +                               struct device_attribute *attr, char *buf)
10598 +{
10599 +#ifdef LM_INTERFACE
10600 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10601 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10602 +#elif defined(PCI_INTERFACE)
10603 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10604 +#elif defined(PLATFORM_INTERFACE)
10605 +       struct platform_device *platform_dev =
10606 +           container_of(_dev, struct platform_device, dev);
10607 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10608 +#endif
10609 +
10610 +       int i;
10611 +       int time;
10612 +       int start_jiffies;
10613 +
10614 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
10615 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
10616 +       start_jiffies = jiffies;
10617 +       for (i = 0; i < RW_REG_COUNT; i++) {
10618 +               dwc_otg_get_gnptxfsiz(otg_dev->core_if);
10619 +       }
10620 +       time = jiffies - start_jiffies;
10621 +       return sprintf(buf,
10622 +                      "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
10623 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
10624 +}
10625 +
10626 +DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
10627 +
10628 +/**
10629 + * Displays the time required to write the GNPTXFSIZ register many times (the
10630 + * output shows the number of times the register is written).
10631 + */
10632 +static ssize_t wr_reg_test_show(struct device *_dev,
10633 +                               struct device_attribute *attr, char *buf)
10634 +{
10635 +#ifdef LM_INTERFACE
10636 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10637 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10638 +#elif defined(PCI_INTERFACE)
10639 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10640 +#elif defined(PLATFORM_INTERFACE)
10641 +       struct platform_device *platform_dev =
10642 +           container_of(_dev, struct platform_device, dev);
10643 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10644 +#endif
10645 +
10646 +       uint32_t reg_val;
10647 +       int i;
10648 +       int time;
10649 +       int start_jiffies;
10650 +
10651 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
10652 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
10653 +       reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if);
10654 +       start_jiffies = jiffies;
10655 +       for (i = 0; i < RW_REG_COUNT; i++) {
10656 +               dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val);
10657 +       }
10658 +       time = jiffies - start_jiffies;
10659 +       return sprintf(buf,
10660 +                      "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
10661 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
10662 +}
10663 +
10664 +DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
10665 +
10666 +#ifdef CONFIG_USB_DWC_OTG_LPM
10667 +
10668 +/**
10669 +* Show the lpm_response attribute.
10670 +*/
10671 +static ssize_t lpmresp_show(struct device *_dev,
10672 +                           struct device_attribute *attr, char *buf)
10673 +{
10674 +#ifdef LM_INTERFACE
10675 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10676 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10677 +#elif defined(PCI_INTERFACE)
10678 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10679 +#elif defined(PLATFORM_INTERFACE)
10680 +       struct platform_device *platform_dev =
10681 +           container_of(_dev, struct platform_device, dev);
10682 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10683 +#endif
10684 +
10685 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if))
10686 +               return sprintf(buf, "** LPM is DISABLED **\n");
10687 +
10688 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
10689 +               return sprintf(buf, "** Current mode is not device mode\n");
10690 +       }
10691 +       return sprintf(buf, "lpm_response = %d\n",
10692 +                      dwc_otg_get_lpmresponse(otg_dev->core_if));
10693 +}
10694 +
10695 +/**
10696 +* Store the lpm_response attribute.
10697 +*/
10698 +static ssize_t lpmresp_store(struct device *_dev,
10699 +                            struct device_attribute *attr,
10700 +                            const char *buf, size_t count)
10701 +{
10702 +#ifdef LM_INTERFACE
10703 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10704 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10705 +#elif defined(PCI_INTERFACE)
10706 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10707 +#elif defined(PLATFORM_INTERFACE)
10708 +       struct platform_device *platform_dev =
10709 +           container_of(_dev, struct platform_device, dev);
10710 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10711 +#endif
10712 +
10713 +       uint32_t val = simple_strtoul(buf, NULL, 16);
10714 +
10715 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) {
10716 +               return 0;
10717 +       }
10718 +
10719 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
10720 +               return 0;
10721 +       }
10722 +
10723 +       dwc_otg_set_lpmresponse(otg_dev->core_if, val);
10724 +       return count;
10725 +}
10726 +
10727 +DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store);
10728 +
10729 +/**
10730 +* Show the sleep_status attribute.
10731 +*/
10732 +static ssize_t sleepstatus_show(struct device *_dev,
10733 +                               struct device_attribute *attr, char *buf)
10734 +{
10735 +#ifdef LM_INTERFACE
10736 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10737 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10738 +#elif defined(PCI_INTERFACE)
10739 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10740 +#elif defined(PLATFORM_INTERFACE)
10741 +       struct platform_device *platform_dev =
10742 +           container_of(_dev, struct platform_device, dev);
10743 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10744 +#endif
10745 +
10746 +
10747 +       return sprintf(buf, "Sleep Status = %d\n",
10748 +                      dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if));
10749 +}
10750 +
10751 +/**
10752 + * Store the sleep_status attribure.
10753 + */
10754 +static ssize_t sleepstatus_store(struct device *_dev,
10755 +                                struct device_attribute *attr,
10756 +                                const char *buf, size_t count)
10757 +{
10758 +#ifdef LM_INTERFACE
10759 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev);
10760 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);
10761 +#elif defined(PCI_INTERFACE)
10762 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
10763 +#elif defined(PLATFORM_INTERFACE)
10764 +       struct platform_device *platform_dev =
10765 +           container_of(_dev, struct platform_device, dev);
10766 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);
10767 +#endif
10768 +
10769 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
10770 +
10771 +       if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) {
10772 +               if (dwc_otg_is_host_mode(core_if)) {
10773 +
10774 +                       DWC_PRINTF("Host initiated resume\n");
10775 +                       dwc_otg_set_prtresume(otg_dev->core_if, 1);
10776 +               }
10777 +       }
10778 +
10779 +       return count;
10780 +}
10781 +
10782 +DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show,
10783 +           sleepstatus_store);
10784 +
10785 +#endif                         /* CONFIG_USB_DWC_OTG_LPM_ENABLE */
10786 +
10787 +/**@}*/
10788 +
10789 +/**
10790 + * Create the device files
10791 + */
10792 +void dwc_otg_attr_create (
10793 +#ifdef LM_INTERFACE
10794 +       struct lm_device *dev
10795 +#elif  defined(PCI_INTERFACE)
10796 +       struct pci_dev *dev
10797 +#elif  defined(PLATFORM_INTERFACE)
10798 +       struct platform_device *dev
10799 +#endif
10800 +       )
10801 +
10802 +{
10803 +       int error;
10804 +
10805 +       error = device_create_file(&dev->dev, &dev_attr_regoffset);
10806 +       error = device_create_file(&dev->dev, &dev_attr_regvalue);
10807 +       error = device_create_file(&dev->dev, &dev_attr_mode);
10808 +       error = device_create_file(&dev->dev, &dev_attr_hnpcapable);
10809 +       error = device_create_file(&dev->dev, &dev_attr_srpcapable);
10810 +       error = device_create_file(&dev->dev, &dev_attr_hsic_connect);
10811 +       error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic);
10812 +       error = device_create_file(&dev->dev, &dev_attr_hnp);
10813 +       error = device_create_file(&dev->dev, &dev_attr_srp);
10814 +       error = device_create_file(&dev->dev, &dev_attr_buspower);
10815 +       error = device_create_file(&dev->dev, &dev_attr_bussuspend);
10816 +       error = device_create_file(&dev->dev, &dev_attr_busconnected);
10817 +       error = device_create_file(&dev->dev, &dev_attr_gotgctl);
10818 +       error = device_create_file(&dev->dev, &dev_attr_gusbcfg);
10819 +       error = device_create_file(&dev->dev, &dev_attr_grxfsiz);
10820 +       error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz);
10821 +       error = device_create_file(&dev->dev, &dev_attr_gpvndctl);
10822 +       error = device_create_file(&dev->dev, &dev_attr_ggpio);
10823 +       error = device_create_file(&dev->dev, &dev_attr_guid);
10824 +       error = device_create_file(&dev->dev, &dev_attr_gsnpsid);
10825 +       error = device_create_file(&dev->dev, &dev_attr_devspeed);
10826 +       error = device_create_file(&dev->dev, &dev_attr_enumspeed);
10827 +       error = device_create_file(&dev->dev, &dev_attr_hptxfsiz);
10828 +       error = device_create_file(&dev->dev, &dev_attr_hprt0);
10829 +       error = device_create_file(&dev->dev, &dev_attr_remote_wakeup);
10830 +       error = device_create_file(&dev->dev, &dev_attr_regdump);
10831 +       error = device_create_file(&dev->dev, &dev_attr_spramdump);
10832 +       error = device_create_file(&dev->dev, &dev_attr_hcddump);
10833 +       error = device_create_file(&dev->dev, &dev_attr_hcd_frrem);
10834 +       error = device_create_file(&dev->dev, &dev_attr_rd_reg_test);
10835 +       error = device_create_file(&dev->dev, &dev_attr_wr_reg_test);
10836 +#ifdef CONFIG_USB_DWC_OTG_LPM
10837 +       error = device_create_file(&dev->dev, &dev_attr_lpm_response);
10838 +       error = device_create_file(&dev->dev, &dev_attr_sleep_status);
10839 +#endif
10840 +}
10841 +
10842 +/**
10843 + * Remove the device files
10844 + */
10845 +void dwc_otg_attr_remove (
10846 +#ifdef LM_INTERFACE
10847 +       struct lm_device *dev
10848 +#elif  defined(PCI_INTERFACE)
10849 +       struct pci_dev *dev
10850 +#elif  defined(PLATFORM_INTERFACE)
10851 +       struct platform_device *dev
10852 +#endif
10853 +       )
10854 +
10855 +{
10856 +       device_remove_file(&dev->dev, &dev_attr_regoffset);
10857 +       device_remove_file(&dev->dev, &dev_attr_regvalue);
10858 +       device_remove_file(&dev->dev, &dev_attr_mode);
10859 +       device_remove_file(&dev->dev, &dev_attr_hnpcapable);
10860 +       device_remove_file(&dev->dev, &dev_attr_srpcapable);
10861 +       device_remove_file(&dev->dev, &dev_attr_hsic_connect);
10862 +       device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic);
10863 +       device_remove_file(&dev->dev, &dev_attr_hnp);
10864 +       device_remove_file(&dev->dev, &dev_attr_srp);
10865 +       device_remove_file(&dev->dev, &dev_attr_buspower);
10866 +       device_remove_file(&dev->dev, &dev_attr_bussuspend);
10867 +       device_remove_file(&dev->dev, &dev_attr_busconnected);
10868 +       device_remove_file(&dev->dev, &dev_attr_gotgctl);
10869 +       device_remove_file(&dev->dev, &dev_attr_gusbcfg);
10870 +       device_remove_file(&dev->dev, &dev_attr_grxfsiz);
10871 +       device_remove_file(&dev->dev, &dev_attr_gnptxfsiz);
10872 +       device_remove_file(&dev->dev, &dev_attr_gpvndctl);
10873 +       device_remove_file(&dev->dev, &dev_attr_ggpio);
10874 +       device_remove_file(&dev->dev, &dev_attr_guid);
10875 +       device_remove_file(&dev->dev, &dev_attr_gsnpsid);
10876 +       device_remove_file(&dev->dev, &dev_attr_devspeed);
10877 +       device_remove_file(&dev->dev, &dev_attr_enumspeed);
10878 +       device_remove_file(&dev->dev, &dev_attr_hptxfsiz);
10879 +       device_remove_file(&dev->dev, &dev_attr_hprt0);
10880 +       device_remove_file(&dev->dev, &dev_attr_remote_wakeup);
10881 +       device_remove_file(&dev->dev, &dev_attr_regdump);
10882 +       device_remove_file(&dev->dev, &dev_attr_spramdump);
10883 +       device_remove_file(&dev->dev, &dev_attr_hcddump);
10884 +       device_remove_file(&dev->dev, &dev_attr_hcd_frrem);
10885 +       device_remove_file(&dev->dev, &dev_attr_rd_reg_test);
10886 +       device_remove_file(&dev->dev, &dev_attr_wr_reg_test);
10887 +#ifdef CONFIG_USB_DWC_OTG_LPM
10888 +       device_remove_file(&dev->dev, &dev_attr_lpm_response);
10889 +       device_remove_file(&dev->dev, &dev_attr_sleep_status);
10890 +#endif
10891 +}
10892 --- /dev/null
10893 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h
10894 @@ -0,0 +1,88 @@
10895 +/* ==========================================================================
10896 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
10897 + * $Revision: #11 $
10898 + * $Date: 2009/04/03 $
10899 + * $Change: 1225160 $
10900 + *
10901 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
10902 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
10903 + * otherwise expressly agreed to in writing between Synopsys and you.
10904 + * 
10905 + * The Software IS NOT an item of Licensed Software or Licensed Product under
10906 + * any End User Software License Agreement or Agreement for Licensed Product
10907 + * with Synopsys or any supplement thereto. You are permitted to use and
10908 + * redistribute this Software in source and binary forms, with or without
10909 + * modification, provided that redistributions of source code must retain this
10910 + * notice. You may not view, use, disclose, copy or distribute this file or
10911 + * any information contained herein except pursuant to this license grant from
10912 + * Synopsys. If you do not agree with this notice, including the disclaimer
10913 + * below, then you are not authorized to use the Software.
10914 + * 
10915 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
10916 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10917 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10918 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
10919 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
10920 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
10921 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
10922 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10923 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10924 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
10925 + * DAMAGE.
10926 + * ========================================================================== */
10927 +
10928 +#if !defined(__DWC_OTG_ATTR_H__)
10929 +#define __DWC_OTG_ATTR_H__
10930 +
10931 +/** @file
10932 + * This file contains the interface to the Linux device attributes.
10933 + */
10934 +extern struct device_attribute dev_attr_regoffset;
10935 +extern struct device_attribute dev_attr_regvalue;
10936 +
10937 +extern struct device_attribute dev_attr_mode;
10938 +extern struct device_attribute dev_attr_hnpcapable;
10939 +extern struct device_attribute dev_attr_srpcapable;
10940 +extern struct device_attribute dev_attr_hnp;
10941 +extern struct device_attribute dev_attr_srp;
10942 +extern struct device_attribute dev_attr_buspower;
10943 +extern struct device_attribute dev_attr_bussuspend;
10944 +extern struct device_attribute dev_attr_busconnected;
10945 +extern struct device_attribute dev_attr_gotgctl;
10946 +extern struct device_attribute dev_attr_gusbcfg;
10947 +extern struct device_attribute dev_attr_grxfsiz;
10948 +extern struct device_attribute dev_attr_gnptxfsiz;
10949 +extern struct device_attribute dev_attr_gpvndctl;
10950 +extern struct device_attribute dev_attr_ggpio;
10951 +extern struct device_attribute dev_attr_guid;
10952 +extern struct device_attribute dev_attr_gsnpsid;
10953 +extern struct device_attribute dev_attr_devspeed;
10954 +extern struct device_attribute dev_attr_enumspeed;
10955 +extern struct device_attribute dev_attr_hptxfsiz;
10956 +extern struct device_attribute dev_attr_hprt0;
10957 +#ifdef CONFIG_USB_DWC_OTG_LPM
10958 +extern struct device_attribute dev_attr_lpm_response;
10959 +extern struct device_attribute dev_attr_sleep_local_dev;
10960 +extern struct device_attribute devi_attr_sleep_status;
10961 +#endif
10962 +
10963 +void dwc_otg_attr_create (
10964 +#ifdef LM_INTERFACE
10965 +       struct lm_device *dev
10966 +#elif  defined(PCI_INTERFACE)
10967 +       struct pci_dev *dev
10968 +#elif  defined(PLATFORM_INTERFACE)
10969 +       struct platform_device *dev
10970 +#endif
10971 +       );
10972 +
10973 +void dwc_otg_attr_remove (
10974 +#ifdef LM_INTERFACE
10975 +       struct lm_device *dev
10976 +#elif  defined(PCI_INTERFACE)
10977 +       struct pci_dev *dev
10978 +#elif  defined(PLATFORM_INTERFACE)
10979 +       struct platform_device *dev
10980 +#endif
10981 +       );
10982 +#endif
10983 --- /dev/null
10984 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
10985 @@ -0,0 +1,1876 @@
10986 +/* ==========================================================================
10987 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
10988 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
10989 + * otherwise expressly agreed to in writing between Synopsys and you.
10990 + * 
10991 + * The Software IS NOT an item of Licensed Software or Licensed Product under
10992 + * any End User Software License Agreement or Agreement for Licensed Product
10993 + * with Synopsys or any supplement thereto. You are permitted to use and
10994 + * redistribute this Software in source and binary forms, with or without
10995 + * modification, provided that redistributions of source code must retain this
10996 + * notice. You may not view, use, disclose, copy or distribute this file or
10997 + * any information contained herein except pursuant to this license grant from
10998 + * Synopsys. If you do not agree with this notice, including the disclaimer
10999 + * below, then you are not authorized to use the Software.
11000 + * 
11001 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
11002 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
11003 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
11004 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
11005 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11006 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
11007 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
11008 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
11009 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
11010 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
11011 + * DAMAGE.
11012 + * ========================================================================== */
11013 +
11014 +/** @file 
11015 + *
11016 + * This file contains the most of the CFI implementation for the OTG.
11017 + */
11018 +
11019 +#ifdef DWC_UTE_CFI
11020 +
11021 +#include "dwc_otg_pcd.h"
11022 +#include "dwc_otg_cfi.h"
11023 +
11024 +/** This definition should actually migrate to the Portability Library */
11025 +#define DWC_CONSTANT_CPU_TO_LE16(x) (x)
11026 +
11027 +extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
11028 +
11029 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
11030 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
11031 +                                struct dwc_otg_pcd *pcd,
11032 +                                struct cfi_usb_ctrlrequest *ctrl_req);
11033 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
11034 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
11035 +                            struct cfi_usb_ctrlrequest *req);
11036 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
11037 +                                struct cfi_usb_ctrlrequest *req);
11038 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
11039 +                               struct cfi_usb_ctrlrequest *req);
11040 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
11041 +                            struct cfi_usb_ctrlrequest *req);
11042 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
11043 +
11044 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
11045 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
11046 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
11047 +
11048 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
11049 +
11050 +/** This is the header of the all features descriptor */
11051 +static cfi_all_features_header_t all_props_desc_header = {
11052 +       .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
11053 +       .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
11054 +       .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
11055 +};
11056 +
11057 +/** This is an array of statically allocated feature descriptors */
11058 +static cfi_feature_desc_header_t prop_descs[] = {
11059 +
11060 +       /* FT_ID_DMA_MODE */
11061 +       {
11062 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
11063 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
11064 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
11065 +        },
11066 +
11067 +       /* FT_ID_DMA_BUFFER_SETUP */
11068 +       {
11069 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
11070 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
11071 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
11072 +        },
11073 +
11074 +       /* FT_ID_DMA_BUFF_ALIGN */
11075 +       {
11076 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
11077 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
11078 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
11079 +        },
11080 +
11081 +       /* FT_ID_DMA_CONCAT_SETUP */
11082 +       {
11083 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
11084 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
11085 +        //.wDataLength  = DWC_CONSTANT_CPU_TO_LE16(6),
11086 +        },
11087 +
11088 +       /* FT_ID_DMA_CIRCULAR */
11089 +       {
11090 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
11091 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
11092 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
11093 +        },
11094 +
11095 +       /* FT_ID_THRESHOLD_SETUP */
11096 +       {
11097 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
11098 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
11099 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
11100 +        },
11101 +
11102 +       /* FT_ID_DFIFO_DEPTH */
11103 +       {
11104 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
11105 +        .bmAttributes = CFI_FEATURE_ATTR_RO,
11106 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
11107 +        },
11108 +
11109 +       /* FT_ID_TX_FIFO_DEPTH */
11110 +       {
11111 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
11112 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
11113 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
11114 +        },
11115 +
11116 +       /* FT_ID_RX_FIFO_DEPTH */
11117 +       {
11118 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
11119 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
11120 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
11121 +        }
11122 +};
11123 +
11124 +/** The table of feature names */
11125 +cfi_string_t prop_name_table[] = {
11126 +       {FT_ID_DMA_MODE, "dma_mode"},
11127 +       {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
11128 +       {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
11129 +       {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
11130 +       {FT_ID_DMA_CIRCULAR, "buffer_circular"},
11131 +       {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
11132 +       {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
11133 +       {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
11134 +       {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
11135 +       {}
11136 +};
11137 +
11138 +/************************************************************************/
11139 +
11140 +/** 
11141 + * Returns the name of the feature by its ID 
11142 + * or NULL if no featute ID matches.
11143 + * 
11144 + */
11145 +const uint8_t *get_prop_name(uint16_t prop_id, int *len)
11146 +{
11147 +       cfi_string_t *pstr;
11148 +       *len = 0;
11149 +
11150 +       for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
11151 +               if (pstr->id == prop_id) {
11152 +                       *len = DWC_STRLEN(pstr->s);
11153 +                       return pstr->s;
11154 +               }
11155 +       }
11156 +       return NULL;
11157 +}
11158 +
11159 +/**
11160 + * This function handles all CFI specific control requests.
11161 + * 
11162 + * Return a negative value to stall the DCE.
11163 + */
11164 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
11165 +{
11166 +       int retval = 0;
11167 +       dwc_otg_pcd_ep_t *ep = NULL;
11168 +       cfiobject_t *cfi = pcd->cfi;
11169 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
11170 +       uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
11171 +       uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
11172 +       uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
11173 +       uint32_t regaddr = 0;
11174 +       uint32_t regval = 0;
11175 +
11176 +       /* Save this Control Request in the CFI object. 
11177 +        * The data field will be assigned in the data stage completion CB function.
11178 +        */
11179 +       cfi->ctrl_req = *ctrl;
11180 +       cfi->ctrl_req.data = NULL;
11181 +
11182 +       cfi->need_gadget_att = 0;
11183 +       cfi->need_status_in_complete = 0;
11184 +
11185 +       switch (ctrl->bRequest) {
11186 +       case VEN_CORE_GET_FEATURES:
11187 +               retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
11188 +               if (retval >= 0) {
11189 +                       //dump_msg(cfi->buf_in.buf, retval);
11190 +                       ep = &pcd->ep0;
11191 +
11192 +                       retval = min((uint16_t) retval, wLen);
11193 +                       /* Transfer this buffer to the host through the EP0-IN EP */
11194 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
11195 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
11196 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
11197 +                       ep->dwc_ep.xfer_len = retval;
11198 +                       ep->dwc_ep.xfer_count = 0;
11199 +                       ep->dwc_ep.sent_zlp = 0;
11200 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
11201 +
11202 +                       pcd->ep0_pending = 1;
11203 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
11204 +               }
11205 +               retval = 0;
11206 +               break;
11207 +
11208 +       case VEN_CORE_GET_FEATURE:
11209 +               CFI_INFO("VEN_CORE_GET_FEATURE\n");
11210 +               retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
11211 +                                              pcd, ctrl);
11212 +               if (retval >= 0) {
11213 +                       ep = &pcd->ep0;
11214 +
11215 +                       retval = min((uint16_t) retval, wLen);
11216 +                       /* Transfer this buffer to the host through the EP0-IN EP */
11217 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
11218 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
11219 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
11220 +                       ep->dwc_ep.xfer_len = retval;
11221 +                       ep->dwc_ep.xfer_count = 0;
11222 +                       ep->dwc_ep.sent_zlp = 0;
11223 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
11224 +
11225 +                       pcd->ep0_pending = 1;
11226 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
11227 +               }
11228 +               CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
11229 +               dump_msg(cfi->buf_in.buf, retval);
11230 +               break;
11231 +
11232 +       case VEN_CORE_SET_FEATURE:
11233 +               CFI_INFO("VEN_CORE_SET_FEATURE\n");
11234 +               /* Set up an XFER to get the data stage of the control request,
11235 +                * which is the new value of the feature to be modified.
11236 +                */
11237 +               ep = &pcd->ep0;
11238 +               ep->dwc_ep.is_in = 0;
11239 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
11240 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
11241 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
11242 +               ep->dwc_ep.xfer_len = wLen;
11243 +               ep->dwc_ep.xfer_count = 0;
11244 +               ep->dwc_ep.sent_zlp = 0;
11245 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
11246 +
11247 +               pcd->ep0_pending = 1;
11248 +               /* Read the control write's data stage */
11249 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
11250 +               retval = 0;
11251 +               break;
11252 +
11253 +       case VEN_CORE_RESET_FEATURES:
11254 +               CFI_INFO("VEN_CORE_RESET_FEATURES\n");
11255 +               cfi->need_gadget_att = 1;
11256 +               cfi->need_status_in_complete = 1;
11257 +               retval = cfi_preproc_reset(pcd, ctrl);
11258 +               CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
11259 +               break;
11260 +
11261 +       case VEN_CORE_ACTIVATE_FEATURES:
11262 +               CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
11263 +               break;
11264 +
11265 +       case VEN_CORE_READ_REGISTER:
11266 +               CFI_INFO("VEN_CORE_READ_REGISTER\n");
11267 +               /* wValue optionally contains the HI WORD of the register offset and
11268 +                * wIndex contains the LOW WORD of the register offset 
11269 +                */
11270 +               if (wValue == 0) {
11271 +                       /* @TODO - MAS - fix the access to the base field */
11272 +                       regaddr = 0;
11273 +                       //regaddr = (uint32_t) pcd->otg_dev->base;
11274 +                       //GET_CORE_IF(pcd)->co
11275 +                       regaddr |= wIndex;
11276 +               } else {
11277 +                       regaddr = (wValue << 16) | wIndex;
11278 +               }
11279 +
11280 +               /* Read a 32-bit value of the memory at the regaddr */
11281 +               regval = dwc_read_reg32((uint32_t *) regaddr);
11282 +
11283 +               ep = &pcd->ep0;
11284 +               dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
11285 +               ep->dwc_ep.is_in = 1;
11286 +               ep->dwc_ep.dma_addr = cfi->buf_in.addr;
11287 +               ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
11288 +               ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
11289 +               ep->dwc_ep.xfer_len = wLen;
11290 +               ep->dwc_ep.xfer_count = 0;
11291 +               ep->dwc_ep.sent_zlp = 0;
11292 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
11293 +
11294 +               pcd->ep0_pending = 1;
11295 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
11296 +               cfi->need_gadget_att = 0;
11297 +               retval = 0;
11298 +               break;
11299 +
11300 +       case VEN_CORE_WRITE_REGISTER:
11301 +               CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
11302 +               /* Set up an XFER to get the data stage of the control request,
11303 +                * which is the new value of the register to be modified.
11304 +                */
11305 +               ep = &pcd->ep0;
11306 +               ep->dwc_ep.is_in = 0;
11307 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
11308 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
11309 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
11310 +               ep->dwc_ep.xfer_len = wLen;
11311 +               ep->dwc_ep.xfer_count = 0;
11312 +               ep->dwc_ep.sent_zlp = 0;
11313 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
11314 +
11315 +               pcd->ep0_pending = 1;
11316 +               /* Read the control write's data stage */
11317 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
11318 +               retval = 0;
11319 +               break;
11320 +
11321 +       default:
11322 +               retval = -DWC_E_NOT_SUPPORTED;
11323 +               break;
11324 +       }
11325 +
11326 +       return retval;
11327 +}
11328 +
11329 +/**
11330 + * This function prepares the core features descriptors and copies its
11331 + * raw representation into the buffer <buf>.
11332 + * 
11333 + * The buffer structure is as follows:
11334 + *     all_features_header (8 bytes)
11335 + *     features_#1 (8 bytes + feature name string length)
11336 + *     features_#2 (8 bytes + feature name string length)
11337 + *     .....
11338 + *     features_#n - where n=the total count of feature descriptors
11339 + */
11340 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
11341 +{
11342 +       cfi_feature_desc_header_t *prop_hdr = prop_descs;
11343 +       cfi_feature_desc_header_t *prop;
11344 +       cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
11345 +       cfi_all_features_header_t *tmp;
11346 +       uint8_t *tmpbuf = buf;
11347 +       const uint8_t *pname = NULL;
11348 +       int i, j, namelen = 0, totlen;
11349 +
11350 +       /* Prepare and copy the core features into the buffer */
11351 +       CFI_INFO("%s:\n", __func__);
11352 +
11353 +       tmp = (cfi_all_features_header_t *) tmpbuf;
11354 +       *tmp = *all_props_hdr;
11355 +       tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
11356 +
11357 +       j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
11358 +       for (i = 0; i < j; i++, prop_hdr++) {
11359 +               pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
11360 +               prop = (cfi_feature_desc_header_t *) tmpbuf;
11361 +               *prop = *prop_hdr;
11362 +
11363 +               prop->bNameLen = namelen;
11364 +               prop->wLength =
11365 +                   DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
11366 +                                            namelen);
11367 +
11368 +               tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
11369 +               dwc_memcpy(tmpbuf, pname, namelen);
11370 +               tmpbuf += namelen;
11371 +       }
11372 +
11373 +       totlen = tmpbuf - buf;
11374 +
11375 +       if (totlen > 0) {
11376 +               tmp = (cfi_all_features_header_t *) buf;
11377 +               tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
11378 +       }
11379 +
11380 +       return totlen;
11381 +}
11382 +
11383 +/**
11384 + * This function releases all the dynamic memory in the CFI object.
11385 + */
11386 +static void cfi_release(cfiobject_t * cfiobj)
11387 +{
11388 +       cfi_ep_t *cfiep;
11389 +       dwc_list_link_t *tmp;
11390 +
11391 +       CFI_INFO("%s\n", __func__);
11392 +
11393 +       if (cfiobj->buf_in.buf) {
11394 +               dwc_dma_free(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
11395 +                            cfiobj->buf_in.addr);
11396 +               cfiobj->buf_in.buf = NULL;
11397 +       }
11398 +
11399 +       if (cfiobj->buf_out.buf) {
11400 +               dwc_dma_free(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
11401 +                            cfiobj->buf_out.addr);
11402 +               cfiobj->buf_out.buf = NULL;
11403 +       }
11404 +
11405 +       /* Free the Buffer Setup values for each EP */
11406 +       //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
11407 +       DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
11408 +               cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
11409 +               cfi_free_ep_bs_dyn_data(cfiep);
11410 +       }
11411 +}
11412 +
11413 +/**
11414 + * This function frees the dynamically allocated EP buffer setup data.
11415 + */
11416 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
11417 +{
11418 +       if (cfiep->bm_sg) {
11419 +               dwc_free(cfiep->bm_sg);
11420 +               cfiep->bm_sg = NULL;
11421 +       }
11422 +
11423 +       if (cfiep->bm_align) {
11424 +               dwc_free(cfiep->bm_align);
11425 +               cfiep->bm_align = NULL;
11426 +       }
11427 +
11428 +       if (cfiep->bm_concat) {
11429 +               if (NULL != cfiep->bm_concat->wTxBytes) {
11430 +                       dwc_free(cfiep->bm_concat->wTxBytes);
11431 +                       cfiep->bm_concat->wTxBytes = NULL;
11432 +               }
11433 +               dwc_free(cfiep->bm_concat);
11434 +               cfiep->bm_concat = NULL;
11435 +       }
11436 +}
11437 +
11438 +/**
11439 + * This function initializes the default values of the features
11440 + * for a specific endpoint and should be called only once when
11441 + * the EP is enabled first time.
11442 + */
11443 +static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
11444 +{
11445 +       int retval = 0;
11446 +
11447 +       cfiep->bm_sg = dwc_alloc(sizeof(ddma_sg_buffer_setup_t));
11448 +       if (NULL == cfiep->bm_sg) {
11449 +               CFI_INFO("Failed to allocate memory for SG feature value\n");
11450 +               return -DWC_E_NO_MEMORY;
11451 +       }
11452 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
11453 +
11454 +       /* For the Concatenation feature's default value we do not allocate
11455 +        * memory for the wTxBytes field - it will be done in the set_feature_value
11456 +        * request handler.
11457 +        */
11458 +       cfiep->bm_concat = dwc_alloc(sizeof(ddma_concat_buffer_setup_t));
11459 +       if (NULL == cfiep->bm_concat) {
11460 +               CFI_INFO
11461 +                   ("Failed to allocate memory for CONCATENATION feature value\n");
11462 +               dwc_free(cfiep->bm_sg);
11463 +               return -DWC_E_NO_MEMORY;
11464 +       }
11465 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
11466 +
11467 +       cfiep->bm_align = dwc_alloc(sizeof(ddma_align_buffer_setup_t));
11468 +       if (NULL == cfiep->bm_align) {
11469 +               CFI_INFO
11470 +                   ("Failed to allocate memory for Alignment feature value\n");
11471 +               dwc_free(cfiep->bm_sg);
11472 +               dwc_free(cfiep->bm_concat);
11473 +               return -DWC_E_NO_MEMORY;
11474 +       }
11475 +       dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
11476 +
11477 +       return retval;
11478 +}
11479 +
11480 +/**
11481 + * The callback function that notifies the CFI on the activation of
11482 + * an endpoint in the PCD. The following steps are done in this function:
11483 + *
11484 + *     Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's 
11485 + *             active endpoint)
11486 + *     Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP
11487 + *     Set the Buffer Mode to standard
11488 + *     Initialize the default values for all EP modes (SG, Circular, Concat, Align)
11489 + *     Add the cfi_ep_t object to the list of active endpoints in the CFI object
11490 + */
11491 +static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
11492 +                        struct dwc_otg_pcd_ep *ep)
11493 +{
11494 +       cfi_ep_t *cfiep;
11495 +       int retval = -DWC_E_NOT_SUPPORTED;
11496 +
11497 +       CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
11498 +                "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
11499 +       /* MAS - Check whether this endpoint already is in the list */
11500 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
11501 +
11502 +       if (NULL == cfiep) {
11503 +               /* Allocate a cfi_ep_t object */
11504 +               cfiep = dwc_alloc(sizeof(cfi_ep_t));
11505 +               if (NULL == cfiep) {
11506 +                       CFI_INFO
11507 +                           ("Unable to allocate memory for <cfiep> in function %s\n",
11508 +                            __func__);
11509 +                       return -DWC_E_NO_MEMORY;
11510 +               }
11511 +               dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
11512 +
11513 +               /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
11514 +               cfiep->ep = ep;
11515 +
11516 +               /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
11517 +               ep->dwc_ep.descs =
11518 +                   dwc_dma_alloc(MAX_DMA_DESCS_PER_EP *
11519 +                                 sizeof(dwc_otg_dma_desc_t),
11520 +                                 &ep->dwc_ep.descs_dma_addr);
11521 +
11522 +               if (NULL == ep->dwc_ep.descs) {
11523 +                       dwc_free(cfiep);
11524 +                       return -DWC_E_NO_MEMORY;
11525 +               }
11526 +
11527 +               DWC_LIST_INIT(&cfiep->lh);
11528 +
11529 +               /* Set the buffer mode to BM_STANDARD. It will be modified 
11530 +                * when building descriptors for a specific buffer mode */
11531 +               ep->dwc_ep.buff_mode = BM_STANDARD;
11532 +
11533 +               /* Create and initialize the default values for this EP's Buffer modes */
11534 +               if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
11535 +                       return retval;
11536 +
11537 +               /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
11538 +               DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
11539 +               retval = 0;
11540 +       } else {                /* The sought EP already is in the list */
11541 +               CFI_INFO("%s: The sought EP already is in the list\n",
11542 +                        __func__);
11543 +       }
11544 +
11545 +       return retval;
11546 +}
11547 +
11548 +/**
11549 + * This function is called when the data stage of a 3-stage Control Write request
11550 + * is complete.
11551 + * 
11552 + */
11553 +static int cfi_ctrl_write_complete(struct cfiobject *cfi,
11554 +                                  struct dwc_otg_pcd *pcd)
11555 +{
11556 +       uint32_t addr, reg_value;
11557 +       uint16_t wIndex, wValue;
11558 +       uint8_t bRequest;
11559 +       uint8_t *buf = cfi->buf_out.buf;
11560 +       //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
11561 +       struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
11562 +       int retval = -DWC_E_NOT_SUPPORTED;
11563 +
11564 +       CFI_INFO("%s\n", __func__);
11565 +
11566 +       bRequest = ctrl_req->bRequest;
11567 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
11568 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
11569 +
11570 +       /* 
11571 +        * Save the pointer to the data stage in the ctrl_req's <data> field.
11572 +        * The request should be already saved in the command stage by now.
11573 +        */
11574 +       ctrl_req->data = cfi->buf_out.buf;
11575 +       cfi->need_status_in_complete = 0;
11576 +       cfi->need_gadget_att = 0;
11577 +
11578 +       switch (bRequest) {
11579 +       case VEN_CORE_WRITE_REGISTER:
11580 +               /* The buffer contains raw data of the new value for the register */
11581 +               reg_value = *((uint32_t *) buf);
11582 +               if (wValue == 0) {
11583 +                       addr = 0;
11584 +                       //addr = (uint32_t) pcd->otg_dev->base;
11585 +                       addr += wIndex;
11586 +               } else {
11587 +                       addr = (wValue << 16) | wIndex;
11588 +               }
11589 +
11590 +               //writel(reg_value, addr);
11591 +
11592 +               retval = 0;
11593 +               cfi->need_status_in_complete = 1;
11594 +               break;
11595 +
11596 +       case VEN_CORE_SET_FEATURE:
11597 +               /* The buffer contains raw data of the new value of the feature */
11598 +               retval = cfi_set_feature_value(pcd);
11599 +               if (retval < 0)
11600 +                       return retval;
11601 +
11602 +               cfi->need_status_in_complete = 1;
11603 +               break;
11604 +
11605 +       default:
11606 +               break;
11607 +       }
11608 +
11609 +       return retval;
11610 +}
11611 +
11612 +/**
11613 + * This function builds the DMA descriptors for the SG buffer mode.
11614 + */
11615 +static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
11616 +                              dwc_otg_pcd_request_t * req)
11617 +{
11618 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
11619 +       ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
11620 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
11621 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
11622 +       dma_addr_t buff_addr = req->dma;
11623 +       int i;
11624 +       uint32_t txsize, off;
11625 +
11626 +       txsize = sgval->wSize;
11627 +       off = sgval->bOffset;
11628 +
11629 +//      CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", 
11630 +//              __func__, cfiep->ep->ep.name, txsize, off);
11631 +
11632 +       for (i = 0; i < sgval->bCount; i++) {
11633 +               desc->status.b.bs = BS_HOST_BUSY;
11634 +               desc->buf = buff_addr;
11635 +               desc->status.b.l = 0;
11636 +               desc->status.b.ioc = 0;
11637 +               desc->status.b.sp = 0;
11638 +               desc->status.b.bytes = txsize;
11639 +               desc->status.b.bs = BS_HOST_READY;
11640 +
11641 +               /* Set the next address of the buffer */
11642 +               buff_addr += txsize + off;
11643 +               desc_last = desc;
11644 +               desc++;
11645 +       }
11646 +
11647 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
11648 +       desc_last->status.b.l = 1;
11649 +       desc_last->status.b.ioc = 1;
11650 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
11651 +       /* Save the last DMA descriptor pointer */
11652 +       cfiep->dma_desc_last = desc_last;
11653 +       cfiep->desc_count = sgval->bCount;
11654 +}
11655 +
11656 +/**
11657 + * This function builds the DMA descriptors for the Concatenation buffer mode.
11658 + */
11659 +static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
11660 +                                  dwc_otg_pcd_request_t * req)
11661 +{
11662 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
11663 +       ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
11664 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
11665 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
11666 +       dma_addr_t buff_addr = req->dma;
11667 +       int i;
11668 +       uint16_t *txsize;
11669 +
11670 +       txsize = concatval->wTxBytes;
11671 +
11672 +       for (i = 0; i < concatval->hdr.bDescCount; i++) {
11673 +               desc->buf = buff_addr;
11674 +               desc->status.b.bs = BS_HOST_BUSY;
11675 +               desc->status.b.l = 0;
11676 +               desc->status.b.ioc = 0;
11677 +               desc->status.b.sp = 0;
11678 +               desc->status.b.bytes = *txsize;
11679 +               desc->status.b.bs = BS_HOST_READY;
11680 +
11681 +               txsize++;
11682 +               /* Set the next address of the buffer */
11683 +               buff_addr += UGETW(ep->desc->wMaxPacketSize);
11684 +               desc_last = desc;
11685 +               desc++;
11686 +       }
11687 +
11688 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
11689 +       desc_last->status.b.l = 1;
11690 +       desc_last->status.b.ioc = 1;
11691 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
11692 +       cfiep->dma_desc_last = desc_last;
11693 +       cfiep->desc_count = concatval->hdr.bDescCount;
11694 +}
11695 +
11696 +/**
11697 + * This function builds the DMA descriptors for the Circular buffer mode
11698 + */
11699 +static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
11700 +                                dwc_otg_pcd_request_t * req)
11701 +{
11702 +       /* @todo: MAS - add implementation when this feature needs to be tested */
11703 +}
11704 +
11705 +/**
11706 + * This function builds the DMA descriptors for the Alignment buffer mode
11707 + */
11708 +static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
11709 +                                 dwc_otg_pcd_request_t * req)
11710 +{
11711 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
11712 +       ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
11713 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
11714 +       dma_addr_t buff_addr = req->dma;
11715 +
11716 +       desc->status.b.bs = BS_HOST_BUSY;
11717 +       desc->status.b.l = 1;
11718 +       desc->status.b.ioc = 1;
11719 +       desc->status.b.sp = ep->dwc_ep.sent_zlp;
11720 +       desc->status.b.bytes = req->length;
11721 +       /* Adjust the buffer alignment */
11722 +       desc->buf = (buff_addr + alignval->bAlign);
11723 +       desc->status.b.bs = BS_HOST_READY;
11724 +       cfiep->dma_desc_last = desc;
11725 +       cfiep->desc_count = 1;
11726 +}
11727 +
11728 +/**
11729 + * This function builds the DMA descriptors chain for different modes of the
11730 + * buffer setup of an endpoint.
11731 + */
11732 +static void cfi_build_descriptors(struct cfiobject *cfi,
11733 +                                 struct dwc_otg_pcd *pcd,
11734 +                                 struct dwc_otg_pcd_ep *ep,
11735 +                                 dwc_otg_pcd_request_t * req)
11736 +{
11737 +       cfi_ep_t *cfiep;
11738 +
11739 +       /* Get the cfiep by the dwc_otg_pcd_ep */
11740 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
11741 +       if (NULL == cfiep) {
11742 +               CFI_INFO("%s: Unable to find a matching active endpoint\n",
11743 +                        __func__);
11744 +               return;
11745 +       }
11746 +
11747 +       cfiep->xfer_len = req->length;
11748 +
11749 +       /* Iterate through all the DMA descriptors */
11750 +       switch (cfiep->ep->dwc_ep.buff_mode) {
11751 +       case BM_SG:
11752 +               cfi_build_sg_descs(cfi, cfiep, req);
11753 +               break;
11754 +
11755 +       case BM_CONCAT:
11756 +               cfi_build_concat_descs(cfi, cfiep, req);
11757 +               break;
11758 +
11759 +       case BM_CIRCULAR:
11760 +               cfi_build_circ_descs(cfi, cfiep, req);
11761 +               break;
11762 +
11763 +       case BM_ALIGN:
11764 +               cfi_build_align_descs(cfi, cfiep, req);
11765 +               break;
11766 +
11767 +       default:
11768 +               break;
11769 +       }
11770 +}
11771 +
11772 +/**
11773 + * Allocate DMA buffer for different Buffer modes.
11774 + */
11775 +static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
11776 +                             struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
11777 +                             unsigned size, gfp_t flags)
11778 +{
11779 +       return dwc_dma_alloc(size, dma);
11780 +}
11781 +
11782 +/**
11783 + * This function initializes the CFI object.
11784 + */
11785 +int init_cfi(cfiobject_t * cfiobj)
11786 +{
11787 +       CFI_INFO("%s\n", __func__);
11788 +
11789 +       /* Allocate a buffer for IN XFERs */
11790 +       cfiobj->buf_in.buf =
11791 +           dwc_dma_alloc(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
11792 +       if (NULL == cfiobj->buf_in.buf) {
11793 +               CFI_INFO("Unable to allocate buffer for INs\n");
11794 +               return -DWC_E_NO_MEMORY;
11795 +       }
11796 +
11797 +       /* Allocate a buffer for OUT XFERs */
11798 +       cfiobj->buf_out.buf =
11799 +           dwc_dma_alloc(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
11800 +       if (NULL == cfiobj->buf_out.buf) {
11801 +               CFI_INFO("Unable to allocate buffer for OUT\n");
11802 +               return -DWC_E_NO_MEMORY;
11803 +       }
11804 +
11805 +       /* Initialize the callback function pointers */
11806 +       cfiobj->ops.release = cfi_release;
11807 +       cfiobj->ops.ep_enable = cfi_ep_enable;
11808 +       cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
11809 +       cfiobj->ops.build_descriptors = cfi_build_descriptors;
11810 +       cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
11811 +
11812 +       /* Initialize the list of active endpoints in the CFI object */
11813 +       DWC_LIST_INIT(&cfiobj->active_eps);
11814 +
11815 +       return 0;
11816 +}
11817 +
11818 +/**
11819 + * This function reads the required feature's current value into the buffer
11820 + *
11821 + * @retval: Returns negative as error, or the data length of the feature  
11822 + */
11823 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
11824 +                                struct dwc_otg_pcd *pcd,
11825 +                                struct cfi_usb_ctrlrequest *ctrl_req)
11826 +{
11827 +       int retval = -DWC_E_NOT_SUPPORTED;
11828 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
11829 +       uint16_t dfifo, rxfifo, txfifo;
11830 +
11831 +       switch (ctrl_req->wIndex) {
11832 +               /* Whether the DDMA is enabled or not */
11833 +       case FT_ID_DMA_MODE:
11834 +               *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
11835 +               retval = 1;
11836 +               break;
11837 +
11838 +       case FT_ID_DMA_BUFFER_SETUP:
11839 +               retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
11840 +               break;
11841 +
11842 +       case FT_ID_DMA_BUFF_ALIGN:
11843 +               retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
11844 +               break;
11845 +
11846 +       case FT_ID_DMA_CONCAT_SETUP:
11847 +               retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
11848 +               break;
11849 +
11850 +       case FT_ID_DMA_CIRCULAR:
11851 +               CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
11852 +               break;
11853 +
11854 +       case FT_ID_THRESHOLD_SETUP:
11855 +               CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
11856 +               break;
11857 +
11858 +       case FT_ID_DFIFO_DEPTH:
11859 +               dfifo = get_dfifo_size(coreif);
11860 +               *((uint16_t *) buf) = dfifo;
11861 +               retval = sizeof(uint16_t);
11862 +               break;
11863 +
11864 +       case FT_ID_TX_FIFO_DEPTH:
11865 +               retval = get_txfifo_size(pcd, ctrl_req->wValue);
11866 +               if (retval >= 0) {
11867 +                       txfifo = retval;
11868 +                       *((uint16_t *) buf) = txfifo;
11869 +                       retval = sizeof(uint16_t);
11870 +               }
11871 +               break;
11872 +
11873 +       case FT_ID_RX_FIFO_DEPTH:
11874 +               retval = get_rxfifo_size(coreif, ctrl_req->wValue);
11875 +               if (retval >= 0) {
11876 +                       rxfifo = retval;
11877 +                       *((uint16_t *) buf) = rxfifo;
11878 +                       retval = sizeof(uint16_t);
11879 +               }
11880 +               break;
11881 +       }
11882 +
11883 +       return retval;
11884 +}
11885 +
11886 +/**
11887 + * This function resets the SG for the specified EP to its default value
11888 + */
11889 +static int cfi_reset_sg_val(cfi_ep_t * cfiep)
11890 +{
11891 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
11892 +       return 0;
11893 +}
11894 +
11895 +/**
11896 + * This function resets the Alignment for the specified EP to its default value
11897 + */
11898 +static int cfi_reset_align_val(cfi_ep_t * cfiep)
11899 +{
11900 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
11901 +       return 0;
11902 +}
11903 +
11904 +/**
11905 + * This function resets the Concatenation for the specified EP to its default value
11906 + * This function will also set the value of the wTxBytes field to NULL after 
11907 + * freeing the memory previously allocated for this field.
11908 + */
11909 +static int cfi_reset_concat_val(cfi_ep_t * cfiep)
11910 +{
11911 +       /* First we need to free the wTxBytes field */
11912 +       if (cfiep->bm_concat->wTxBytes) {
11913 +               dwc_free(cfiep->bm_concat->wTxBytes);
11914 +               cfiep->bm_concat->wTxBytes = NULL;
11915 +       }
11916 +
11917 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
11918 +       return 0;
11919 +}
11920 +
11921 +/**
11922 + * This function resets all the buffer setups of the specified endpoint
11923 + */
11924 +static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
11925 +{
11926 +       cfi_reset_sg_val(cfiep);
11927 +       cfi_reset_align_val(cfiep);
11928 +       cfi_reset_concat_val(cfiep);
11929 +       return 0;
11930 +}
11931 +
11932 +static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
11933 +                                    uint8_t rx_rst, uint8_t tx_rst)
11934 +{
11935 +       int retval = -DWC_E_INVALID;
11936 +       uint16_t tx_siz[15];
11937 +       uint16_t rx_siz = 0;
11938 +       dwc_otg_pcd_ep_t *ep = NULL;
11939 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
11940 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
11941 +
11942 +       if (rx_rst) {
11943 +               rx_siz = params->dev_rx_fifo_size;
11944 +               params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
11945 +       }
11946 +
11947 +       if (tx_rst) {
11948 +               if (ep_addr == 0) {
11949 +                       int i;
11950 +
11951 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
11952 +                               tx_siz[i] =
11953 +                                   core_if->core_params->dev_tx_fifo_size[i];
11954 +                               core_if->core_params->dev_tx_fifo_size[i] =
11955 +                                   core_if->init_txfsiz[i];
11956 +                       }
11957 +               } else {
11958 +
11959 +                       ep = get_ep_by_addr(pcd, ep_addr);
11960 +
11961 +                       if (NULL == ep) {
11962 +                               CFI_INFO
11963 +                                   ("%s: Unable to get the endpoint addr=0x%02x\n",
11964 +                                    __func__, ep_addr);
11965 +                               return -DWC_E_INVALID;
11966 +                       }
11967 +
11968 +                       tx_siz[0] =
11969 +                           params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
11970 +                                                    1];
11971 +                       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
11972 +                           GET_CORE_IF(pcd)->init_txfsiz[ep->dwc_ep.
11973 +                                                         tx_fifo_num - 1];
11974 +               }
11975 +       }
11976 +
11977 +       if (resize_fifos(GET_CORE_IF(pcd))) {
11978 +               retval = 0;
11979 +       } else {
11980 +               CFI_INFO
11981 +                   ("%s: Error resetting the feature Reset All(FIFO size)\n",
11982 +                    __func__);
11983 +               if (rx_rst) {
11984 +                       params->dev_rx_fifo_size = rx_siz;
11985 +               }
11986 +
11987 +               if (tx_rst) {
11988 +                       if (ep_addr == 0) {
11989 +                               int i;
11990 +                               for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
11991 +                                    i++) {
11992 +                                       core_if->core_params->
11993 +                                           dev_tx_fifo_size[i] = tx_siz[i];
11994 +                               }
11995 +                       } else {
11996 +                               params->dev_tx_fifo_size[ep->dwc_ep.
11997 +                                                        tx_fifo_num - 1] =
11998 +                                   tx_siz[0];
11999 +                       }
12000 +               }
12001 +               retval = -DWC_E_INVALID;
12002 +       }
12003 +       return retval;
12004 +}
12005 +
12006 +static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
12007 +{
12008 +       int retval = 0;
12009 +       cfi_ep_t *cfiep;
12010 +       cfiobject_t *cfi = pcd->cfi;
12011 +       dwc_list_link_t *tmp;
12012 +
12013 +       retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
12014 +       if (retval < 0) {
12015 +               return retval;
12016 +       }
12017 +
12018 +       /* If the EP address is known then reset the features for only that EP */
12019 +       if (addr) {
12020 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
12021 +               if (NULL == cfiep) {
12022 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
12023 +                                __func__, addr);
12024 +                       return -DWC_E_INVALID;
12025 +               }
12026 +               retval = cfi_ep_reset_all_setup_vals(cfiep);
12027 +               cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
12028 +       }
12029 +       /* Otherwise (wValue == 0), reset all features of all EP's */
12030 +       else {
12031 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
12032 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
12033 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
12034 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
12035 +                       retval = cfi_ep_reset_all_setup_vals(cfiep);
12036 +                       cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
12037 +                       if (retval < 0) {
12038 +                               CFI_INFO
12039 +                                   ("%s: Error resetting the feature Reset All\n",
12040 +                                    __func__);
12041 +                               return retval;
12042 +                       }
12043 +               }
12044 +       }
12045 +       return retval;
12046 +}
12047 +
12048 +static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
12049 +                                          uint8_t addr)
12050 +{
12051 +       int retval = 0;
12052 +       cfi_ep_t *cfiep;
12053 +       cfiobject_t *cfi = pcd->cfi;
12054 +       dwc_list_link_t *tmp;
12055 +
12056 +       /* If the EP address is known then reset the features for only that EP */
12057 +       if (addr) {
12058 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
12059 +               if (NULL == cfiep) {
12060 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
12061 +                                __func__, addr);
12062 +                       return -DWC_E_INVALID;
12063 +               }
12064 +               retval = cfi_reset_sg_val(cfiep);
12065 +       }
12066 +       /* Otherwise (wValue == 0), reset all features of all EP's */
12067 +       else {
12068 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
12069 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
12070 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
12071 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
12072 +                       retval = cfi_reset_sg_val(cfiep);
12073 +                       if (retval < 0) {
12074 +                               CFI_INFO
12075 +                                   ("%s: Error resetting the feature Buffer Setup\n",
12076 +                                    __func__);
12077 +                               return retval;
12078 +                       }
12079 +               }
12080 +       }
12081 +       return retval;
12082 +}
12083 +
12084 +static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
12085 +{
12086 +       int retval = 0;
12087 +       cfi_ep_t *cfiep;
12088 +       cfiobject_t *cfi = pcd->cfi;
12089 +       dwc_list_link_t *tmp;
12090 +
12091 +       /* If the EP address is known then reset the features for only that EP */
12092 +       if (addr) {
12093 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
12094 +               if (NULL == cfiep) {
12095 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
12096 +                                __func__, addr);
12097 +                       return -DWC_E_INVALID;
12098 +               }
12099 +               retval = cfi_reset_concat_val(cfiep);
12100 +       }
12101 +       /* Otherwise (wValue == 0), reset all features of all EP's */
12102 +       else {
12103 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
12104 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
12105 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
12106 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
12107 +                       retval = cfi_reset_concat_val(cfiep);
12108 +                       if (retval < 0) {
12109 +                               CFI_INFO
12110 +                                   ("%s: Error resetting the feature Concatenation Value\n",
12111 +                                    __func__);
12112 +                               return retval;
12113 +                       }
12114 +               }
12115 +       }
12116 +       return retval;
12117 +}
12118 +
12119 +static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
12120 +{
12121 +       int retval = 0;
12122 +       cfi_ep_t *cfiep;
12123 +       cfiobject_t *cfi = pcd->cfi;
12124 +       dwc_list_link_t *tmp;
12125 +
12126 +       /* If the EP address is known then reset the features for only that EP */
12127 +       if (addr) {
12128 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
12129 +               if (NULL == cfiep) {
12130 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
12131 +                                __func__, addr);
12132 +                       return -DWC_E_INVALID;
12133 +               }
12134 +               retval = cfi_reset_align_val(cfiep);
12135 +       }
12136 +       /* Otherwise (wValue == 0), reset all features of all EP's */
12137 +       else {
12138 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
12139 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
12140 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
12141 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
12142 +                       retval = cfi_reset_align_val(cfiep);
12143 +                       if (retval < 0) {
12144 +                               CFI_INFO
12145 +                                   ("%s: Error resetting the feature Aliignment Value\n",
12146 +                                    __func__);
12147 +                               return retval;
12148 +                       }
12149 +               }
12150 +       }
12151 +       return retval;
12152 +
12153 +}
12154 +
12155 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
12156 +                            struct cfi_usb_ctrlrequest *req)
12157 +{
12158 +       int retval = 0;
12159 +
12160 +       switch (req->wIndex) {
12161 +       case 0:
12162 +               /* Reset all features */
12163 +               retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
12164 +               break;
12165 +
12166 +       case FT_ID_DMA_BUFFER_SETUP:
12167 +               /* Reset the SG buffer setup */
12168 +               retval =
12169 +                   cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
12170 +               break;
12171 +
12172 +       case FT_ID_DMA_CONCAT_SETUP:
12173 +               /* Reset the Concatenation buffer setup */
12174 +               retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
12175 +               break;
12176 +
12177 +       case FT_ID_DMA_BUFF_ALIGN:
12178 +               /* Reset the Alignment buffer setup */
12179 +               retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
12180 +               break;
12181 +
12182 +       case FT_ID_TX_FIFO_DEPTH:
12183 +               retval =
12184 +                   cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
12185 +               pcd->cfi->need_gadget_att = 0;
12186 +               break;
12187 +
12188 +       case FT_ID_RX_FIFO_DEPTH:
12189 +               retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
12190 +               pcd->cfi->need_gadget_att = 0;
12191 +               break;
12192 +       default:
12193 +               break;
12194 +       }
12195 +       return retval;
12196 +}
12197 +
12198 +/**
12199 + * This function sets a new value for the SG buffer setup.
12200 + */
12201 +static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
12202 +{
12203 +       uint8_t inaddr, outaddr;
12204 +       cfi_ep_t *epin, *epout;
12205 +       ddma_sg_buffer_setup_t *psgval;
12206 +       uint32_t desccount, size;
12207 +
12208 +       CFI_INFO("%s\n", __func__);
12209 +
12210 +       psgval = (ddma_sg_buffer_setup_t *) buf;
12211 +       desccount = (uint32_t) psgval->bCount;
12212 +       size = (uint32_t) psgval->wSize;
12213 +
12214 +       /* Check the DMA descriptor count */
12215 +       if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
12216 +               CFI_INFO
12217 +                   ("%s: The count of DMA Descriptors should be between 1 and %d\n",
12218 +                    __func__, MAX_DMA_DESCS_PER_EP);
12219 +               return -DWC_E_INVALID;
12220 +       }
12221 +
12222 +       /* Check the DMA descriptor count */
12223 +
12224 +       if (size == 0) {
12225 +
12226 +               CFI_INFO("%s: The transfer size should be at least 1 byte\n",
12227 +                        __func__);
12228 +
12229 +               return -DWC_E_INVALID;
12230 +
12231 +       }
12232 +
12233 +       inaddr = psgval->bInEndpointAddress;
12234 +       outaddr = psgval->bOutEndpointAddress;
12235 +
12236 +       epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
12237 +       epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
12238 +
12239 +       if (NULL == epin || NULL == epout) {
12240 +               CFI_INFO
12241 +                   ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
12242 +                    __func__, inaddr, outaddr);
12243 +               return -DWC_E_INVALID;
12244 +       }
12245 +
12246 +       epin->ep->dwc_ep.buff_mode = BM_SG;
12247 +       dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
12248 +
12249 +       epout->ep->dwc_ep.buff_mode = BM_SG;
12250 +       dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
12251 +
12252 +       return 0;
12253 +}
12254 +
12255 +/**
12256 + * This function sets a new value for the buffer Alignment setup.
12257 + */
12258 +static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
12259 +{
12260 +       cfi_ep_t *ep;
12261 +       uint8_t addr;
12262 +       ddma_align_buffer_setup_t *palignval;
12263 +
12264 +       palignval = (ddma_align_buffer_setup_t *) buf;
12265 +       addr = palignval->bEndpointAddress;
12266 +
12267 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
12268 +
12269 +       if (NULL == ep) {
12270 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
12271 +                        __func__, addr);
12272 +               return -DWC_E_INVALID;
12273 +       }
12274 +
12275 +       ep->ep->dwc_ep.buff_mode = BM_ALIGN;
12276 +       dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
12277 +
12278 +       return 0;
12279 +}
12280 +
12281 +/**
12282 + * This function sets a new value for the Concatenation buffer setup.
12283 + */
12284 +static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
12285 +{
12286 +       uint8_t addr;
12287 +       cfi_ep_t *ep;
12288 +       struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
12289 +       uint16_t *pVals;
12290 +       uint32_t desccount;
12291 +       int i;
12292 +       uint16_t mps;
12293 +
12294 +       pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
12295 +       desccount = (uint32_t) pConcatValHdr->bDescCount;
12296 +       pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
12297 +
12298 +       /* Check the DMA descriptor count */
12299 +       if (desccount > MAX_DMA_DESCS_PER_EP) {
12300 +               CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
12301 +                        __func__, MAX_DMA_DESCS_PER_EP);
12302 +               return -DWC_E_INVALID;
12303 +       }
12304 +
12305 +       addr = pConcatValHdr->bEndpointAddress;
12306 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
12307 +       if (NULL == ep) {
12308 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
12309 +                        __func__, addr);
12310 +               return -DWC_E_INVALID;
12311 +       }
12312 +
12313 +       mps = UGETW(ep->ep->desc->wMaxPacketSize);
12314 +
12315 +#if 0
12316 +       for (i = 0; i < desccount; i++) {
12317 +               CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
12318 +       }
12319 +       CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
12320 +#endif
12321 +
12322 +       /* Check the wTxSizes to be less than or equal to the mps */
12323 +       for (i = 0; i < desccount; i++) {
12324 +               if (pVals[i] > mps) {
12325 +                       CFI_INFO
12326 +                           ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
12327 +                            __func__, i, pVals[i]);
12328 +                       return -DWC_E_INVALID;
12329 +               }
12330 +       }
12331 +
12332 +       ep->ep->dwc_ep.buff_mode = BM_CONCAT;
12333 +       dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
12334 +
12335 +       /* Free the previously allocated storage for the wTxBytes */
12336 +       if (ep->bm_concat->wTxBytes) {
12337 +               dwc_free(ep->bm_concat->wTxBytes);
12338 +       }
12339 +
12340 +       /* Allocate a new storage for the wTxBytes field */
12341 +       ep->bm_concat->wTxBytes =
12342 +           dwc_alloc(sizeof(uint16_t) * pConcatValHdr->bDescCount);
12343 +       if (NULL == ep->bm_concat->wTxBytes) {
12344 +               CFI_INFO("%s: Unable to allocate memory\n", __func__);
12345 +               return -DWC_E_NO_MEMORY;
12346 +       }
12347 +
12348 +       /* Copy the new values into the wTxBytes filed */
12349 +       dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
12350 +                  sizeof(uint16_t) * pConcatValHdr->bDescCount);
12351 +
12352 +       return 0;
12353 +}
12354 +
12355 +/**
12356 + * This function calculates the total of all FIFO sizes
12357 + * 
12358 + * @param core_if Programming view of DWC_otg controller
12359 + *
12360 + * @return The total of data FIFO sizes.
12361 + *
12362 + */
12363 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
12364 +{
12365 +       dwc_otg_core_params_t *params = core_if->core_params;
12366 +       uint16_t dfifo_total = 0;
12367 +       int i;
12368 +
12369 +       /* The shared RxFIFO size */
12370 +       dfifo_total =
12371 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
12372 +
12373 +       /* Add up each TxFIFO size to the total */
12374 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
12375 +               dfifo_total += params->dev_tx_fifo_size[i];
12376 +       }
12377 +
12378 +       return dfifo_total;
12379 +}
12380 +
12381 +/**
12382 + * This function returns Rx FIFO size
12383 + * 
12384 + * @param core_if Programming view of DWC_otg controller
12385 + *
12386 + * @return The total of data FIFO sizes.
12387 + *
12388 + */
12389 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
12390 +{
12391 +       switch (wValue >> 8) {
12392 +       case 0:
12393 +               return (core_if->pwron_rxfsiz <
12394 +                       32768) ? core_if->pwron_rxfsiz : 32768;
12395 +               break;
12396 +       case 1:
12397 +               return core_if->core_params->dev_rx_fifo_size;
12398 +               break;
12399 +       default:
12400 +               return -DWC_E_INVALID;
12401 +               break;
12402 +       }
12403 +}
12404 +
12405 +/**
12406 + * This function returns Tx FIFO size for IN EP
12407 + * 
12408 + * @param core_if Programming view of DWC_otg controller
12409 + *
12410 + * @return The total of data FIFO sizes.
12411 + *
12412 + */
12413 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
12414 +{
12415 +       dwc_otg_pcd_ep_t *ep;
12416 +
12417 +       ep = get_ep_by_addr(pcd, wValue & 0xff);
12418 +
12419 +       if (NULL == ep) {
12420 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
12421 +                        __func__, wValue & 0xff);
12422 +               return -DWC_E_INVALID;
12423 +       }
12424 +
12425 +       if (!ep->dwc_ep.is_in) {
12426 +               CFI_INFO
12427 +                   ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
12428 +                    __func__, wValue & 0xff);
12429 +               return -DWC_E_INVALID;
12430 +       }
12431 +
12432 +       switch (wValue >> 8) {
12433 +       case 0:
12434 +               return (GET_CORE_IF(pcd)->
12435 +                       pwron_txfsiz[ep->dwc_ep.tx_fifo_num - 1] <
12436 +                       768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->dwc_ep.
12437 +                                                             tx_fifo_num -
12438 +                                                             1] : 32768;
12439 +               break;
12440 +       case 1:
12441 +               return GET_CORE_IF(pcd)->core_params->dev_tx_fifo_size[ep->
12442 +                                                                      dwc_ep.
12443 +                                                                      num - 1];
12444 +               break;
12445 +       default:
12446 +               return -DWC_E_INVALID;
12447 +               break;
12448 +       }
12449 +}
12450 +
12451 +/**
12452 + * This function checks if the submitted combination of 
12453 + * device mode FIFO sizes is possible or not.
12454 + * 
12455 + * @param core_if Programming view of DWC_otg controller
12456 + *
12457 + * @return 1 if possible, 0 otherwise.
12458 + *
12459 + */
12460 +static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
12461 +{
12462 +       uint16_t dfifo_actual = 0;
12463 +       dwc_otg_core_params_t *params = core_if->core_params;
12464 +       uint16_t start_addr = 0;
12465 +       int i;
12466 +
12467 +       dfifo_actual =
12468 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
12469 +
12470 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
12471 +               dfifo_actual += params->dev_tx_fifo_size[i];
12472 +       }
12473 +
12474 +       if (dfifo_actual > core_if->total_fifo_size) {
12475 +               return 0;
12476 +       }
12477 +
12478 +       if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
12479 +               return 0;
12480 +
12481 +       if (params->dev_nperio_tx_fifo_size > 32768
12482 +           || params->dev_nperio_tx_fifo_size < 16)
12483 +               return 0;
12484 +
12485 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
12486 +
12487 +               if (params->dev_tx_fifo_size[i] > 768
12488 +                   || params->dev_tx_fifo_size[i] < 4)
12489 +                       return 0;
12490 +       }
12491 +
12492 +       if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
12493 +               return 0;
12494 +       start_addr = params->dev_rx_fifo_size;
12495 +
12496 +       if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
12497 +               return 0;
12498 +       start_addr += params->dev_nperio_tx_fifo_size;
12499 +
12500 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
12501 +
12502 +               if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
12503 +                       return 0;
12504 +               start_addr += params->dev_tx_fifo_size[i];
12505 +       }
12506 +
12507 +       return 1;
12508 +}
12509 +
12510 +/**
12511 + * This function resizes Device mode FIFOs
12512 + * 
12513 + * @param core_if Programming view of DWC_otg controller
12514 + *
12515 + * @return 1 if successful, 0 otherwise
12516 + *
12517 + */
12518 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
12519 +{
12520 +       int i = 0;
12521 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
12522 +       dwc_otg_core_params_t *params = core_if->core_params;
12523 +       uint32_t rx_fifo_size;
12524 +       fifosize_data_t nptxfifosize;
12525 +       fifosize_data_t txfifosize[15];
12526 +
12527 +       uint32_t rx_fsz_bak;
12528 +       uint32_t nptxfsz_bak;
12529 +       uint32_t txfsz_bak[15];
12530 +
12531 +       uint16_t start_address;
12532 +       uint8_t retval = 1;
12533 +
12534 +       if (!check_fifo_sizes(core_if)) {
12535 +               return 0;
12536 +       }
12537 +
12538 +       /* Configure data FIFO sizes */
12539 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
12540 +               rx_fsz_bak = dwc_read_reg32(&global_regs->grxfsiz);
12541 +               rx_fifo_size = params->dev_rx_fifo_size;
12542 +               dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size);
12543 +
12544 +               /*
12545 +                * Tx FIFOs These FIFOs are numbered from 1 to 15.
12546 +                * Indexes of the FIFO size module parameters in the
12547 +                * dev_tx_fifo_size array and the FIFO size registers in
12548 +                * the dptxfsiz_dieptxf array run from 0 to 14.
12549 +                */
12550 +
12551 +               /* Non-periodic Tx FIFO */
12552 +               nptxfsz_bak = dwc_read_reg32(&global_regs->gnptxfsiz);
12553 +               nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
12554 +               start_address = params->dev_rx_fifo_size;
12555 +               nptxfifosize.b.startaddr = start_address;
12556 +
12557 +               dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);
12558 +
12559 +               start_address += nptxfifosize.b.depth;
12560 +
12561 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
12562 +                       txfsz_bak[i] =
12563 +                           dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]);
12564 +
12565 +                       txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
12566 +                       txfifosize[i].b.startaddr = start_address;
12567 +                       dwc_write_reg32(&global_regs->dptxfsiz_dieptxf[i],
12568 +                                       txfifosize[i].d32);
12569 +
12570 +                       start_address += txfifosize[i].b.depth;
12571 +               }
12572 +
12573 +               /** Check if register values are set correctly */
12574 +               if (rx_fifo_size != dwc_read_reg32(&global_regs->grxfsiz)) {
12575 +                       retval = 0;
12576 +               }
12577 +
12578 +               if (nptxfifosize.d32 != dwc_read_reg32(&global_regs->gnptxfsiz)) {
12579 +                       retval = 0;
12580 +               }
12581 +
12582 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
12583 +                       if (txfifosize[i].d32 !=
12584 +                           dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i])) {
12585 +                               retval = 0;
12586 +                       }
12587 +               }
12588 +
12589 +               /** If register values are not set correctly, reset old values */
12590 +               if (retval == 0) {
12591 +                       dwc_write_reg32(&global_regs->grxfsiz, rx_fsz_bak);
12592 +
12593 +                       /* Non-periodic Tx FIFO */
12594 +                       dwc_write_reg32(&global_regs->gnptxfsiz, nptxfsz_bak);
12595 +
12596 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
12597 +                               dwc_write_reg32(&global_regs->
12598 +                                               dptxfsiz_dieptxf[i],
12599 +                                               txfsz_bak[i]);
12600 +                       }
12601 +               }
12602 +       } else {
12603 +               return 0;
12604 +       }
12605 +
12606 +       /* Flush the FIFOs */
12607 +       dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
12608 +       dwc_otg_flush_rx_fifo(core_if);
12609 +
12610 +       return retval;
12611 +}
12612 +
12613 +/**
12614 + * This function sets a new value for the buffer Alignment setup.
12615 + */
12616 +static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
12617 +{
12618 +       int retval;
12619 +       uint32_t fsiz;
12620 +       uint16_t size;
12621 +       uint16_t ep_addr;
12622 +       dwc_otg_pcd_ep_t *ep;
12623 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
12624 +       tx_fifo_size_setup_t *ptxfifoval;
12625 +
12626 +       ptxfifoval = (tx_fifo_size_setup_t *) buf;
12627 +       ep_addr = ptxfifoval->bEndpointAddress;
12628 +       size = ptxfifoval->wDepth;
12629 +
12630 +       ep = get_ep_by_addr(pcd, ep_addr);
12631 +
12632 +       CFI_INFO
12633 +           ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
12634 +            __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
12635 +
12636 +       if (NULL == ep) {
12637 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
12638 +                        __func__, ep_addr);
12639 +               return -DWC_E_INVALID;
12640 +       }
12641 +
12642 +       fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
12643 +       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
12644 +
12645 +       if (resize_fifos(GET_CORE_IF(pcd))) {
12646 +               retval = 0;
12647 +       } else {
12648 +               CFI_INFO
12649 +                   ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
12650 +                    __func__, ep_addr);
12651 +               params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
12652 +               retval = -DWC_E_INVALID;
12653 +       }
12654 +
12655 +       return retval;
12656 +}
12657 +
12658 +/**
12659 + * This function sets a new value for the buffer Alignment setup.
12660 + */
12661 +static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
12662 +{
12663 +       int retval;
12664 +       uint32_t fsiz;
12665 +       uint16_t size;
12666 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
12667 +       rx_fifo_size_setup_t *prxfifoval;
12668 +
12669 +       prxfifoval = (rx_fifo_size_setup_t *) buf;
12670 +       size = prxfifoval->wDepth;
12671 +
12672 +       fsiz = params->dev_rx_fifo_size;
12673 +       params->dev_rx_fifo_size = size;
12674 +
12675 +       if (resize_fifos(GET_CORE_IF(pcd))) {
12676 +               retval = 0;
12677 +       } else {
12678 +               CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
12679 +                        __func__);
12680 +               params->dev_rx_fifo_size = fsiz;
12681 +               retval = -DWC_E_INVALID;
12682 +       }
12683 +
12684 +       return retval;
12685 +}
12686 +
12687 +/**
12688 + * This function reads the SG of an EP's buffer setup into the buffer buf
12689 + */
12690 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
12691 +                            struct cfi_usb_ctrlrequest *req)
12692 +{
12693 +       int retval = -DWC_E_INVALID;
12694 +       uint8_t addr;
12695 +       cfi_ep_t *ep;
12696 +
12697 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
12698 +       addr = req->wValue & 0xFF;
12699 +       if (addr == 0)          /* The address should be non-zero */
12700 +               return retval;
12701 +
12702 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
12703 +       if (NULL == ep) {
12704 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
12705 +                        __func__, addr);
12706 +               return retval;
12707 +       }
12708 +
12709 +       dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
12710 +       retval = BS_SG_VAL_DESC_LEN;
12711 +       return retval;
12712 +}
12713 +
12714 +/**
12715 + * This function reads the Concatenation value of an EP's buffer mode into 
12716 + * the buffer buf
12717 + */
12718 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
12719 +                                struct cfi_usb_ctrlrequest *req)
12720 +{
12721 +       int retval = -DWC_E_INVALID;
12722 +       uint8_t addr;
12723 +       cfi_ep_t *ep;
12724 +       uint8_t desc_count;
12725 +
12726 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
12727 +       addr = req->wValue & 0xFF;
12728 +       if (addr == 0)          /* The address should be non-zero */
12729 +               return retval;
12730 +
12731 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
12732 +       if (NULL == ep) {
12733 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
12734 +                        __func__, addr);
12735 +               return retval;
12736 +       }
12737 +
12738 +       /* Copy the header to the buffer */
12739 +       dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
12740 +       /* Advance the buffer pointer by the header size */
12741 +       buf += BS_CONCAT_VAL_HDR_LEN;
12742 +
12743 +       desc_count = ep->bm_concat->hdr.bDescCount;
12744 +       /* Copy alll the wTxBytes to the buffer */
12745 +       dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
12746 +
12747 +       retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
12748 +       return retval;
12749 +}
12750 +
12751 +/**
12752 + * This function reads the buffer Alignment value of an EP's buffer mode into 
12753 + * the buffer buf
12754 + *
12755 + * @return The total number of bytes copied to the buffer or negative error code.
12756 + */
12757 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
12758 +                               struct cfi_usb_ctrlrequest *req)
12759 +{
12760 +       int retval = -DWC_E_INVALID;
12761 +       uint8_t addr;
12762 +       cfi_ep_t *ep;
12763 +
12764 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
12765 +       addr = req->wValue & 0xFF;
12766 +       if (addr == 0)          /* The address should be non-zero */
12767 +               return retval;
12768 +
12769 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
12770 +       if (NULL == ep) {
12771 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
12772 +                        __func__, addr);
12773 +               return retval;
12774 +       }
12775 +
12776 +       dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
12777 +       retval = BS_ALIGN_VAL_HDR_LEN;
12778 +
12779 +       return retval;
12780 +}
12781 +
12782 +/**
12783 + * This function sets a new value for the specified feature
12784 + * 
12785 + * @param      pcd     A pointer to the PCD object
12786 + * 
12787 + * @return 0 if successful, negative error code otherwise to stall the DCE.
12788 + */
12789 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
12790 +{
12791 +       int retval = -DWC_E_NOT_SUPPORTED;
12792 +       uint16_t wIndex, wValue;
12793 +       uint8_t bRequest;
12794 +       struct dwc_otg_core_if *coreif;
12795 +       cfiobject_t *cfi = pcd->cfi;
12796 +       struct cfi_usb_ctrlrequest *ctrl_req;
12797 +       uint8_t *buf;
12798 +       ctrl_req = &cfi->ctrl_req;
12799 +
12800 +       buf = pcd->cfi->ctrl_req.data;
12801 +
12802 +       coreif = GET_CORE_IF(pcd);
12803 +       bRequest = ctrl_req->bRequest;
12804 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
12805 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
12806 +
12807 +       /* See which feature is to be modified */
12808 +       switch (wIndex) {
12809 +       case FT_ID_DMA_BUFFER_SETUP:
12810 +               /* Modify the feature */
12811 +               if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
12812 +                       return retval;
12813 +
12814 +               /* And send this request to the gadget */
12815 +               cfi->need_gadget_att = 1;
12816 +               break;
12817 +
12818 +       case FT_ID_DMA_BUFF_ALIGN:
12819 +               if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
12820 +                       return retval;
12821 +               cfi->need_gadget_att = 1;
12822 +               break;
12823 +
12824 +       case FT_ID_DMA_CONCAT_SETUP:
12825 +               /* Modify the feature */
12826 +               if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
12827 +                       return retval;
12828 +               cfi->need_gadget_att = 1;
12829 +               break;
12830 +
12831 +       case FT_ID_DMA_CIRCULAR:
12832 +               CFI_INFO("FT_ID_DMA_CIRCULAR\n");
12833 +               break;
12834 +
12835 +       case FT_ID_THRESHOLD_SETUP:
12836 +               CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
12837 +               break;
12838 +
12839 +       case FT_ID_DFIFO_DEPTH:
12840 +               CFI_INFO("FT_ID_DFIFO_DEPTH\n");
12841 +               break;
12842 +
12843 +       case FT_ID_TX_FIFO_DEPTH:
12844 +               CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
12845 +               if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
12846 +                       return retval;
12847 +               cfi->need_gadget_att = 0;
12848 +               break;
12849 +
12850 +       case FT_ID_RX_FIFO_DEPTH:
12851 +               CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
12852 +               if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
12853 +                       return retval;
12854 +               cfi->need_gadget_att = 0;
12855 +               break;
12856 +       }
12857 +
12858 +       return retval;
12859 +}
12860 +
12861 +#endif                         //DWC_UTE_CFI
12862 --- /dev/null
12863 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
12864 @@ -0,0 +1,319 @@
12865 +/* ==========================================================================
12866 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
12867 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
12868 + * otherwise expressly agreed to in writing between Synopsys and you.
12869 + * 
12870 + * The Software IS NOT an item of Licensed Software or Licensed Product under
12871 + * any End User Software License Agreement or Agreement for Licensed Product
12872 + * with Synopsys or any supplement thereto. You are permitted to use and
12873 + * redistribute this Software in source and binary forms, with or without
12874 + * modification, provided that redistributions of source code must retain this
12875 + * notice. You may not view, use, disclose, copy or distribute this file or
12876 + * any information contained herein except pursuant to this license grant from
12877 + * Synopsys. If you do not agree with this notice, including the disclaimer
12878 + * below, then you are not authorized to use the Software.
12879 + * 
12880 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
12881 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12882 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12883 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
12884 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
12885 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12886 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
12887 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12888 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12889 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
12890 + * DAMAGE.
12891 + * ========================================================================== */
12892 +
12893 +#if !defined(__DWC_OTG_CFI_H__)
12894 +#define __DWC_OTG_CFI_H__
12895 +
12896 +#include "dwc_otg_pcd.h"
12897 +#include "dwc_cfi_common.h"
12898 +
12899 +/**
12900 + * @file 
12901 + *
12902 + * This file contains the CFI related OTG PCD specific common constants, interfaces
12903 + * (functions and macros) and data structures.
12904 + *
12905 + */
12906 +
12907 +struct dwc_otg_pcd;
12908 +struct dwc_otg_pcd_ep;
12909 +
12910 +/** OTG CFI Features (properties) ID constants */
12911 +/** This is a request for all Core Features */
12912 +#define FT_ID_DMA_MODE                                 0x0001
12913 +#define FT_ID_DMA_BUFFER_SETUP                 0x0002
12914 +#define FT_ID_DMA_BUFF_ALIGN                   0x0003
12915 +#define FT_ID_DMA_CONCAT_SETUP                 0x0004
12916 +#define FT_ID_DMA_CIRCULAR                             0x0005
12917 +#define FT_ID_THRESHOLD_SETUP                  0x0006
12918 +#define FT_ID_DFIFO_DEPTH                              0x0007
12919 +#define FT_ID_TX_FIFO_DEPTH                            0x0008
12920 +#define FT_ID_RX_FIFO_DEPTH                            0x0009
12921 +
12922 +/**********************************************************/
12923 +#define CFI_INFO_DEF
12924 +
12925 +#ifdef CFI_INFO_DEF
12926 +#define CFI_INFO(fmt...)       DWC_PRINTF("CFI: " fmt);
12927 +#else
12928 +#define CFI_INFO(fmt...)
12929 +#endif
12930 +
12931 +#define min(x,y) ({ \
12932 +       x < y ? x : y; })
12933 +
12934 +#define max(x,y) ({ \
12935 +       x > y ? x : y; })
12936 +
12937 +/** 
12938 + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is
12939 + * also used for setting up a buffer for Circular DDMA.
12940 + */
12941 +struct _ddma_sg_buffer_setup {
12942 +#define BS_SG_VAL_DESC_LEN     6
12943 +       /* The OUT EP address */
12944 +       uint8_t bOutEndpointAddress;
12945 +       /* The IN EP address */
12946 +       uint8_t bInEndpointAddress;
12947 +       /* Number of bytes to put between transfer segments (must be DWORD boundaries) */
12948 +       uint8_t bOffset;
12949 +       /* The number of transfer segments (a DMA descriptors per each segment) */
12950 +       uint8_t bCount;
12951 +       /* Size (in byte) of each transfer segment */
12952 +       uint16_t wSize;
12953 +} __attribute__ ((packed));
12954 +typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t;
12955 +
12956 +/** Descriptor DMA Concatenation Buffer setup structure */
12957 +struct _ddma_concat_buffer_setup_hdr {
12958 +#define BS_CONCAT_VAL_HDR_LEN  4
12959 +       /* The endpoint for which the buffer is to be set up */
12960 +       uint8_t bEndpointAddress;
12961 +       /* The count of descriptors to be used */
12962 +       uint8_t bDescCount;
12963 +       /* The total size of the transfer */
12964 +       uint16_t wSize;
12965 +} __attribute__ ((packed));
12966 +typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t;
12967 +
12968 +/** Descriptor DMA Concatenation Buffer setup structure */
12969 +struct _ddma_concat_buffer_setup {
12970 +       /* The SG header */
12971 +       ddma_concat_buffer_setup_hdr_t hdr;
12972 +
12973 +       /* The XFER sizes pointer (allocated dynamically) */
12974 +       uint16_t *wTxBytes;
12975 +} __attribute__ ((packed));
12976 +typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t;
12977 +
12978 +/** Descriptor DMA Alignment Buffer setup structure */
12979 +struct _ddma_align_buffer_setup {
12980 +#define BS_ALIGN_VAL_HDR_LEN   2
12981 +       uint8_t bEndpointAddress;
12982 +       uint8_t bAlign;
12983 +} __attribute__ ((packed));
12984 +typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t;
12985 +
12986 +/** Transmit FIFO Size setup structure */
12987 +struct _tx_fifo_size_setup {
12988 +       uint8_t bEndpointAddress;
12989 +       uint16_t wDepth;
12990 +} __attribute__ ((packed));
12991 +typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t;
12992 +
12993 +/** Transmit FIFO Size setup structure */
12994 +struct _rx_fifo_size_setup {
12995 +       uint16_t wDepth;
12996 +} __attribute__ ((packed));
12997 +typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t;
12998 +
12999 +/**
13000 + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest
13001 + * This structure encapsulates the standard usb_ctrlrequest and adds a pointer 
13002 + * to the data returned in the data stage of a 3-stage Control Write requests.
13003 + */
13004 +struct cfi_usb_ctrlrequest {
13005 +       uint8_t bRequestType;
13006 +       uint8_t bRequest;
13007 +       uint16_t wValue;
13008 +       uint16_t wIndex;
13009 +       uint16_t wLength;
13010 +       uint8_t *data;
13011 +} UPACKED;
13012 +
13013 +/*---------------------------------------------------------------------------*/
13014 +
13015 +/**
13016 + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures.
13017 + * This structure is used to store the buffer setup data for any 
13018 + * enabled endpoint in the PCD.
13019 + */
13020 +struct cfi_ep {
13021 +       /* Entry for the list container */
13022 +       dwc_list_link_t lh;
13023 +       /* Pointer to the active PCD endpoint structure */
13024 +       struct dwc_otg_pcd_ep *ep;
13025 +       /* The last descriptor in the chain of DMA descriptors of the endpoint */
13026 +       struct dwc_otg_dma_desc *dma_desc_last;
13027 +       /* The SG feature value */
13028 +       ddma_sg_buffer_setup_t *bm_sg;
13029 +       /* The Circular feature value */
13030 +       ddma_sg_buffer_setup_t *bm_circ;
13031 +       /* The Concatenation feature value */
13032 +       ddma_concat_buffer_setup_t *bm_concat;
13033 +       /* The Alignment feature value */
13034 +       ddma_align_buffer_setup_t *bm_align;
13035 +       /* XFER length */
13036 +       uint32_t xfer_len;
13037 +       /* 
13038 +        * Count of DMA descriptors currently used.
13039 +        * The total should not exceed the MAX_DMA_DESCS_PER_EP value
13040 +        * defined in the dwc_otg_cil.h
13041 +        */
13042 +       uint32_t desc_count;
13043 +};
13044 +typedef struct cfi_ep cfi_ep_t;
13045 +
13046 +typedef struct cfi_dma_buff {
13047 +#define CFI_IN_BUF_LEN 1024
13048 +#define CFI_OUT_BUF_LEN        1024
13049 +       dma_addr_t addr;
13050 +       uint8_t *buf;
13051 +} cfi_dma_buff_t;
13052 +
13053 +struct cfiobject;
13054 +
13055 +/**
13056 + * This is the interface for the CFI operations.
13057 + * 
13058 + * @param      ep_enable                       Called when any endpoint is enabled and activated.
13059 + * @param      release                         Called when the CFI object is released and it needs to correctly
13060 + *                                                             deallocate the dynamic memory
13061 + * @param      ctrl_write_complete     Called when the data stage of the request is complete
13062 + */
13063 +typedef struct cfi_ops {
13064 +       int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
13065 +                         struct dwc_otg_pcd_ep * ep);
13066 +       void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
13067 +                              struct dwc_otg_pcd_ep * ep, dma_addr_t * dma,
13068 +                              unsigned size, gfp_t flags);
13069 +       void (*release) (struct cfiobject * cfi);
13070 +       int (*ctrl_write_complete) (struct cfiobject * cfi,
13071 +                                   struct dwc_otg_pcd * pcd);
13072 +       void (*build_descriptors) (struct cfiobject * cfi,
13073 +                                  struct dwc_otg_pcd * pcd,
13074 +                                  struct dwc_otg_pcd_ep * ep,
13075 +                                  dwc_otg_pcd_request_t * req);
13076 +} cfi_ops_t;
13077 +
13078 +struct cfiobject {
13079 +       cfi_ops_t ops;
13080 +       struct dwc_otg_pcd *pcd;
13081 +       struct usb_gadget *gadget;
13082 +
13083 +       /* Buffers used to send/receive CFI-related request data */
13084 +       cfi_dma_buff_t buf_in;
13085 +       cfi_dma_buff_t buf_out;
13086 +
13087 +       /* CFI specific Control request wrapper */
13088 +       struct cfi_usb_ctrlrequest ctrl_req;
13089 +
13090 +       /* The list of active EP's in the PCD of type cfi_ep_t */
13091 +       dwc_list_link_t active_eps;
13092 +
13093 +       /* This flag shall control the propagation of a specific request
13094 +        * to the gadget's processing routines.
13095 +        * 0 - no gadget handling
13096 +        * 1 - the gadget needs to know about this request (w/o completing a status 
13097 +        * phase - just return a 0 to the _setup callback)
13098 +        */
13099 +       uint8_t need_gadget_att;
13100 +
13101 +       /* Flag indicating whether the status IN phase needs to be 
13102 +        * completed by the PCD
13103 +        */
13104 +       uint8_t need_status_in_complete;
13105 +};
13106 +typedef struct cfiobject cfiobject_t;
13107 +
13108 +#define DUMP_MSG
13109 +
13110 +#if defined(DUMP_MSG)
13111 +static inline void dump_msg(const u8 * buf, unsigned int length)
13112 +{
13113 +       unsigned int start, num, i;
13114 +       char line[52], *p;
13115 +
13116 +       if (length >= 512)
13117 +               return;
13118 +
13119 +       start = 0;
13120 +       while (length > 0) {
13121 +               num = min(length, 16u);
13122 +               p = line;
13123 +               for (i = 0; i < num; ++i) {
13124 +                       if (i == 8)
13125 +                               *p++ = ' ';
13126 +                       DWC_SPRINTF(p, " %02x", buf[i]);
13127 +                       p += 3;
13128 +               }
13129 +               *p = 0;
13130 +               DWC_DEBUG("%6x: %s\n", start, line);
13131 +               buf += num;
13132 +               start += num;
13133 +               length -= num;
13134 +       }
13135 +}
13136 +#else
13137 +static inline void dump_msg(const u8 * buf, unsigned int length)
13138 +{
13139 +}
13140 +#endif
13141 +
13142 +/**
13143 + * This function returns a pointer to cfi_ep_t object with the addr address.
13144 + */
13145 +static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi,
13146 +                                               uint8_t addr)
13147 +{
13148 +       struct cfi_ep *pcfiep;
13149 +       dwc_list_link_t *tmp;
13150 +
13151 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
13152 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
13153 +
13154 +               if (pcfiep->ep->desc->bEndpointAddress == addr) {
13155 +                       return pcfiep;
13156 +               }
13157 +       }
13158 +
13159 +       return NULL;
13160 +}
13161 +
13162 +/**
13163 + * This function returns a pointer to cfi_ep_t object that matches
13164 + * the dwc_otg_pcd_ep object.
13165 + */
13166 +static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi,
13167 +                                                 struct dwc_otg_pcd_ep *ep)
13168 +{
13169 +       struct cfi_ep *pcfiep = NULL;
13170 +       dwc_list_link_t *tmp;
13171 +
13172 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
13173 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
13174 +               if (pcfiep->ep == ep) {
13175 +                       return pcfiep;
13176 +               }
13177 +       }
13178 +       return NULL;
13179 +}
13180 +
13181 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
13182 +
13183 +#endif                         /* (__DWC_OTG_CFI_H__) */
13184 --- /dev/null
13185 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
13186 @@ -0,0 +1,5410 @@
13187 +/* ==========================================================================
13188 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
13189 + * $Revision: #159 $
13190 + * $Date: 2009/04/21 $
13191 + * $Change: 1237465 $
13192 + *
13193 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
13194 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
13195 + * otherwise expressly agreed to in writing between Synopsys and you.
13196 + * 
13197 + * The Software IS NOT an item of Licensed Software or Licensed Product under
13198 + * any End User Software License Agreement or Agreement for Licensed Product
13199 + * with Synopsys or any supplement thereto. You are permitted to use and
13200 + * redistribute this Software in source and binary forms, with or without
13201 + * modification, provided that redistributions of source code must retain this
13202 + * notice. You may not view, use, disclose, copy or distribute this file or
13203 + * any information contained herein except pursuant to this license grant from
13204 + * Synopsys. If you do not agree with this notice, including the disclaimer
13205 + * below, then you are not authorized to use the Software.
13206 + * 
13207 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
13208 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13209 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13210 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
13211 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13212 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
13213 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
13214 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13215 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13216 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
13217 + * DAMAGE.
13218 + * ========================================================================== */
13219 +
13220 +/** @file 
13221 + *
13222 + * The Core Interface Layer provides basic services for accessing and
13223 + * managing the DWC_otg hardware. These services are used by both the
13224 + * Host Controller Driver and the Peripheral Controller Driver.
13225 + *
13226 + * The CIL manages the memory map for the core so that the HCD and PCD
13227 + * don't have to do this separately. It also handles basic tasks like
13228 + * reading/writing the registers and data FIFOs in the controller.
13229 + * Some of the data access functions provide encapsulation of several
13230 + * operations required to perform a task, such as writing multiple
13231 + * registers to start a transfer. Finally, the CIL performs basic
13232 + * services that are not specific to either the host or device modes
13233 + * of operation. These services include management of the OTG Host
13234 + * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
13235 + * Diagnostic API is also provided to allow testing of the controller
13236 + * hardware.
13237 + *
13238 + * The Core Interface Layer has the following requirements:
13239 + * - Provides basic controller operations.
13240 + * - Minimal use of OS services.  
13241 + * - The OS services used will be abstracted by using inline functions
13242 + *      or macros.
13243 + *
13244 + */
13245 +
13246 +#include "dwc_os.h"
13247 +#include "dwc_otg_regs.h"
13248 +#include "dwc_otg_cil.h"
13249 +
13250 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
13251 +
13252 +/** 
13253 + * This function is called to initialize the DWC_otg CSR data
13254 + * structures. The register addresses in the device and host
13255 + * structures are initialized from the base address supplied by the
13256 + * caller.     The calling function must make the OS calls to get the
13257 + * base address of the DWC_otg controller registers.  The core_params
13258 + * argument holds the parameters that specify how the core should be
13259 + * configured.
13260 + *
13261 + * @param reg_base_addr Base address of DWC_otg core registers
13262 + *
13263 + */
13264 +dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
13265 +{
13266 +       dwc_otg_core_if_t *core_if = 0;
13267 +       dwc_otg_dev_if_t *dev_if = 0;
13268 +       dwc_otg_host_if_t *host_if = 0;
13269 +       uint8_t *reg_base = (uint8_t *) reg_base_addr;
13270 +       int i = 0;
13271 +
13272 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr);
13273 +
13274 +       core_if = dwc_alloc(sizeof(dwc_otg_core_if_t));
13275 +
13276 +       if (core_if == 0) {
13277 +               DWC_DEBUGPL(DBG_CIL,
13278 +                           "Allocation of dwc_otg_core_if_t failed\n");
13279 +               return 0;
13280 +       }
13281 +       core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
13282 +
13283 +       /*
13284 +        * Allocate the Device Mode structures.
13285 +        */
13286 +       dev_if = dwc_alloc(sizeof(dwc_otg_dev_if_t));
13287 +
13288 +       if (dev_if == 0) {
13289 +               DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");
13290 +               dwc_free(core_if);
13291 +               return 0;
13292 +       }
13293 +
13294 +       dev_if->dev_global_regs =
13295 +           (dwc_otg_device_global_regs_t *) (reg_base +
13296 +                                             DWC_DEV_GLOBAL_REG_OFFSET);
13297 +
13298 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
13299 +               dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
13300 +                   (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
13301 +                    (i * DWC_EP_REG_OFFSET));
13302 +
13303 +               dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
13304 +                   (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
13305 +                    (i * DWC_EP_REG_OFFSET));
13306 +               DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",
13307 +                           i, &dev_if->in_ep_regs[i]->diepctl);
13308 +               DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",
13309 +                           i, &dev_if->out_ep_regs[i]->doepctl);
13310 +       }
13311 +
13312 +       dev_if->speed = 0;      // unknown
13313 +
13314 +       core_if->dev_if = dev_if;
13315 +
13316 +       /*
13317 +        * Allocate the Host Mode structures.
13318 +        */
13319 +       host_if = dwc_alloc(sizeof(dwc_otg_host_if_t));
13320 +
13321 +       if (host_if == 0) {
13322 +               DWC_DEBUGPL(DBG_CIL,
13323 +                           "Allocation of dwc_otg_host_if_t failed\n");
13324 +               dwc_free(dev_if);
13325 +               dwc_free(core_if);
13326 +               return 0;
13327 +       }
13328 +
13329 +       host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
13330 +           (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
13331 +
13332 +       host_if->hprt0 =
13333 +           (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
13334 +
13335 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
13336 +               host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
13337 +                   (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
13338 +                    (i * DWC_OTG_CHAN_REGS_OFFSET));
13339 +               DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
13340 +                           i, &host_if->hc_regs[i]->hcchar);
13341 +       }
13342 +
13343 +       host_if->num_host_channels = MAX_EPS_CHANNELS;
13344 +       core_if->host_if = host_if;
13345 +
13346 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
13347 +               core_if->data_fifo[i] =
13348 +                   (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
13349 +                                 (i * DWC_OTG_DATA_FIFO_SIZE));
13350 +               DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08x\n",
13351 +                           i, (unsigned)core_if->data_fifo[i]);
13352 +       }
13353 +
13354 +       core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
13355 +
13356 +       /* Initiate lx_state to L3 disconnected state */
13357 +       core_if->lx_state = DWC_OTG_L3;
13358 +       /*
13359 +        * Store the contents of the hardware configuration registers here for
13360 +        * easy access later.
13361 +        */
13362 +       core_if->hwcfg1.d32 =
13363 +           dwc_read_reg32(&core_if->core_global_regs->ghwcfg1);
13364 +       core_if->hwcfg2.d32 =
13365 +           dwc_read_reg32(&core_if->core_global_regs->ghwcfg2);
13366 +       core_if->hwcfg3.d32 =
13367 +           dwc_read_reg32(&core_if->core_global_regs->ghwcfg3);
13368 +       core_if->hwcfg4.d32 =
13369 +           dwc_read_reg32(&core_if->core_global_regs->ghwcfg4);
13370 +
13371 +       DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
13372 +       DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);
13373 +       DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);
13374 +       DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);
13375 +
13376 +       core_if->hcfg.d32 =
13377 +           dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg);
13378 +       core_if->dcfg.d32 =
13379 +           dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg);
13380 +
13381 +       DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32);
13382 +       DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32);
13383 +
13384 +       DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
13385 +       DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);
13386 +       DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
13387 +       DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",
13388 +                   core_if->hwcfg2.b.num_host_chan);
13389 +       DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",
13390 +                   core_if->hwcfg2.b.nonperio_tx_q_depth);
13391 +       DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",
13392 +                   core_if->hwcfg2.b.host_perio_tx_q_depth);
13393 +       DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",
13394 +                   core_if->hwcfg2.b.dev_token_q_depth);
13395 +
13396 +       DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",
13397 +                   core_if->hwcfg3.b.dfifo_depth);
13398 +       DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",
13399 +                   core_if->hwcfg3.b.xfer_size_cntr_width);
13400 +
13401 +       /*
13402 +        * Set the SRP sucess bit for FS-I2c
13403 +        */
13404 +       core_if->srp_success = 0;
13405 +       core_if->srp_timer_started = 0;
13406 +
13407 +       /*
13408 +        * Create new workqueue and init works
13409 +        */
13410 +       core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg");
13411 +       if (core_if->wq_otg == 0) {
13412 +               DWC_WARN("DWC_WORKQ_ALLOC failed\n");
13413 +               dwc_free(host_if);
13414 +               dwc_free(dev_if);
13415 +               dwc_free(core_if);
13416 +               return 0;
13417 +       }
13418 +
13419 +       core_if->snpsid = dwc_read_reg32(&core_if->core_global_regs->gsnpsid);
13420 +
13421 +       DWC_PRINTF("Core Release: %x.%x%x%x\n",
13422 +                  (core_if->snpsid >> 12 & 0xF),
13423 +                  (core_if->snpsid >> 8 & 0xF),
13424 +                  (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
13425 +
13426 +       core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer",
13427 +                                            w_wakeup_detected, core_if);
13428 +       if (core_if->wkp_timer == 0) {
13429 +               DWC_WARN("DWC_TIMER_ALLOC failed\n");
13430 +               dwc_free(host_if);
13431 +               dwc_free(dev_if);
13432 +               DWC_WORKQ_FREE(core_if->wq_otg);
13433 +               dwc_free(core_if);
13434 +               return 0;
13435 +       }
13436 +
13437 +       if (dwc_otg_setup_params(core_if)) {
13438 +               DWC_WARN("Error while setting core params\n");
13439 +       }
13440 +
13441 +       return core_if;
13442 +}
13443 +
13444 +/**
13445 + * This function frees the structures allocated by dwc_otg_cil_init().
13446 + * 
13447 + * @param core_if The core interface pointer returned from
13448 + *               dwc_otg_cil_init().
13449 + *
13450 + */
13451 +void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if)
13452 +{
13453 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
13454 +
13455 +       /* Disable all interrupts */
13456 +       dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 1, 0);
13457 +       dwc_write_reg32(&core_if->core_global_regs->gintmsk, 0);
13458 +
13459 +       if (core_if->wq_otg) {
13460 +               DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500);
13461 +               DWC_WORKQ_FREE(core_if->wq_otg);
13462 +       }
13463 +       if (core_if->dev_if) {
13464 +               dwc_free(core_if->dev_if);
13465 +       }
13466 +       if (core_if->host_if) {
13467 +               dwc_free(core_if->host_if);
13468 +       }
13469 +       dwc_free(core_if);
13470 +       DWC_TIMER_FREE(core_if->wkp_timer);
13471 +       DWC_FREE(core_if->core_params);
13472 +}
13473 +
13474 +/**
13475 + * This function enables the controller's Global Interrupt in the AHB Config
13476 + * register.
13477 + *
13478 + * @param core_if Programming view of DWC_otg controller.
13479 + */
13480 +void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if)
13481 +{
13482 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
13483 +       ahbcfg.b.glblintrmsk = 1;       /* Enable interrupts */
13484 +       dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
13485 +}
13486 +
13487 +/**
13488 + * This function disables the controller's Global Interrupt in the AHB Config
13489 + * register.
13490 + *
13491 + * @param core_if Programming view of DWC_otg controller.
13492 + */
13493 +void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if)
13494 +{
13495 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
13496 +       ahbcfg.b.glblintrmsk = 1;       /* Enable interrupts */
13497 +       DWC_PRINTF("%x -> %x\n", (unsigned int)&core_if->core_global_regs->gahbcfg, ahbcfg.d32);
13498 +       dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
13499 +}
13500 +
13501 +/**
13502 + * This function initializes the commmon interrupts, used in both
13503 + * device and host modes.
13504 + *
13505 + * @param core_if Programming view of the DWC_otg controller
13506 + *
13507 + */
13508 +static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if)
13509 +{
13510 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
13511 +       gintmsk_data_t intr_mask = {.d32 = 0 };
13512 +
13513 +       /* Clear any pending OTG Interrupts */
13514 +       dwc_write_reg32(&global_regs->gotgint, 0xFFFFFFFF);
13515 +
13516 +       /* Clear any pending interrupts */
13517 +       dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF);
13518 +
13519 +       /* 
13520 +        * Enable the interrupts in the GINTMSK. 
13521 +        */
13522 +       intr_mask.b.modemismatch = 1;
13523 +       intr_mask.b.otgintr = 1;
13524 +
13525 +       if (!core_if->dma_enable) {
13526 +               intr_mask.b.rxstsqlvl = 1;
13527 +       }
13528 +
13529 +       intr_mask.b.conidstschng = 1;
13530 +       intr_mask.b.wkupintr = 1;
13531 +       intr_mask.b.disconnect = 1;
13532 +       intr_mask.b.usbsuspend = 1;
13533 +       intr_mask.b.sessreqintr = 1;
13534 +#ifdef CONFIG_USB_DWC_OTG_LPM
13535 +       if (core_if->core_params->lpm_enable) {
13536 +               intr_mask.b.lpmtranrcvd = 1;
13537 +       }
13538 +#endif
13539 +       dwc_write_reg32(&global_regs->gintmsk, intr_mask.d32);
13540 +}
13541 +
13542 +/**
13543 + * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
13544 + * type.
13545 + */
13546 +static void init_fslspclksel(dwc_otg_core_if_t * core_if)
13547 +{
13548 +       uint32_t val;
13549 +       hcfg_data_t hcfg;
13550 +
13551 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
13552 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
13553 +            (core_if->core_params->ulpi_fs_ls)) ||
13554 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
13555 +               /* Full speed PHY */
13556 +               val = DWC_HCFG_48_MHZ;
13557 +       } else {
13558 +               /* High speed PHY running at full speed or high speed */
13559 +               val = DWC_HCFG_30_60_MHZ;
13560 +       }
13561 +
13562 +       DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
13563 +       hcfg.d32 = dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg);
13564 +       hcfg.b.fslspclksel = val;
13565 +       dwc_write_reg32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
13566 +}
13567 +
13568 +/**
13569 + * Initializes the DevSpd field of the DCFG register depending on the PHY type
13570 + * and the enumeration speed of the device.
13571 + */
13572 +static void init_devspd(dwc_otg_core_if_t * core_if)
13573 +{
13574 +       uint32_t val;
13575 +       dcfg_data_t dcfg;
13576 +
13577 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
13578 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
13579 +            (core_if->core_params->ulpi_fs_ls)) ||
13580 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
13581 +               /* Full speed PHY */
13582 +               val = 0x3;
13583 +       } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
13584 +               /* High speed PHY running at full speed */
13585 +               val = 0x1;
13586 +       } else {
13587 +               /* High speed PHY running at high speed */
13588 +               val = 0x0;
13589 +       }
13590 +
13591 +       DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
13592 +
13593 +       dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg);
13594 +       dcfg.b.devspd = val;
13595 +       dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
13596 +}
13597 +
13598 +/**
13599 + * This function calculates the number of IN EPS
13600 + * using GHWCFG1 and GHWCFG2 registers values 
13601 + *
13602 + * @param core_if Programming view of the DWC_otg controller
13603 + */
13604 +static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if)
13605 +{
13606 +       uint32_t num_in_eps = 0;
13607 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
13608 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3;
13609 +       uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps;
13610 +       int i;
13611 +
13612 +       for (i = 0; i < num_eps; ++i) {
13613 +               if (!(hwcfg1 & 0x1))
13614 +                       num_in_eps++;
13615 +
13616 +               hwcfg1 >>= 2;
13617 +       }
13618 +
13619 +       if (core_if->hwcfg4.b.ded_fifo_en) {
13620 +               num_in_eps =
13621 +                   (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
13622 +       }
13623 +
13624 +       return num_in_eps;
13625 +}
13626 +
13627 +/**
13628 + * This function calculates the number of OUT EPS
13629 + * using GHWCFG1 and GHWCFG2 registers values 
13630 + *
13631 + * @param core_if Programming view of the DWC_otg controller
13632 + */
13633 +static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if)
13634 +{
13635 +       uint32_t num_out_eps = 0;
13636 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
13637 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2;
13638 +       int i;
13639 +
13640 +       for (i = 0; i < num_eps; ++i) {
13641 +               if (!(hwcfg1 & 0x1))
13642 +                       num_out_eps++;
13643 +
13644 +               hwcfg1 >>= 2;
13645 +       }
13646 +       return num_out_eps;
13647 +}
13648 +
13649 +/**
13650 + * This function initializes the DWC_otg controller registers and
13651 + * prepares the core for device mode or host mode operation.
13652 + *
13653 + * @param core_if Programming view of the DWC_otg controller
13654 + *
13655 + */
13656 +void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
13657 +{
13658 +       int i = 0;
13659 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
13660 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
13661 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
13662 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
13663 +       gi2cctl_data_t i2cctl = {.d32 = 0 };
13664 +
13665 +       DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p) regs at %p\n",
13666 +                    core_if, global_regs);
13667 +
13668 +       /* Common Initialization */
13669 +
13670 +       usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
13671 +
13672 +       /* Program the ULPI External VBUS bit if needed */
13673 +       usbcfg.b.ulpi_ext_vbus_drv =
13674 +           (core_if->core_params->phy_ulpi_ext_vbus ==
13675 +            DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
13676 +
13677 +       /* Set external TS Dline pulsing */
13678 +       usbcfg.b.term_sel_dl_pulse =
13679 +           (core_if->core_params->ts_dline == 1) ? 1 : 0;
13680 +       dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
13681 +
13682 +       /* Reset the Controller */
13683 +       dwc_otg_core_reset(core_if);
13684 +
13685 +       /* Initialize parameters from Hardware configuration registers. */
13686 +       dev_if->num_in_eps = calc_num_in_eps(core_if);
13687 +       dev_if->num_out_eps = calc_num_out_eps(core_if);
13688 +
13689 +       DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
13690 +                   core_if->hwcfg4.b.num_dev_perio_in_ep);
13691 +
13692 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
13693 +               dev_if->perio_tx_fifo_size[i] =
13694 +                   dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16;
13695 +               DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n",
13696 +                           i, dev_if->perio_tx_fifo_size[i]);
13697 +       }
13698 +
13699 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
13700 +               dev_if->tx_fifo_size[i] =
13701 +                   dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16;
13702 +               DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n",
13703 +                           i, dev_if->perio_tx_fifo_size[i]);
13704 +       }
13705 +
13706 +       core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
13707 +       core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz);
13708 +       core_if->nperio_tx_fifo_size =
13709 +           dwc_read_reg32(&global_regs->gnptxfsiz) >> 16;
13710 +
13711 +       DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size);
13712 +       DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
13713 +       DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",
13714 +                   core_if->nperio_tx_fifo_size);
13715 +
13716 +       /* This programming sequence needs to happen in FS mode before any other
13717 +        * programming occurs */
13718 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
13719 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
13720 +               /* If FS mode with FS PHY */
13721 +
13722 +               /* core_init() is now called on every switch so only call the
13723 +                * following for the first time through. */
13724 +               if (!core_if->phy_init_done) {
13725 +                       core_if->phy_init_done = 1;
13726 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
13727 +                       usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
13728 +                       usbcfg.b.physel = 1;
13729 +                       dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
13730 +
13731 +                       /* Reset after a PHY select */
13732 +                       dwc_otg_core_reset(core_if);
13733 +               }
13734 +
13735 +               /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.      Also
13736 +                * do this on HNP Dev/Host mode switches (done in dev_init and
13737 +                * host_init). */
13738 +               if (dwc_otg_is_host_mode(core_if)) {
13739 +                       init_fslspclksel(core_if);
13740 +               } else {
13741 +                       init_devspd(core_if);
13742 +               }
13743 +
13744 +               if (core_if->core_params->i2c_enable) {
13745 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
13746 +                       /* Program GUSBCFG.OtgUtmifsSel to I2C */
13747 +                       usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
13748 +                       usbcfg.b.otgutmifssel = 1;
13749 +                       dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
13750 +
13751 +                       /* Program GI2CCTL.I2CEn */
13752 +                       i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl);
13753 +                       i2cctl.b.i2cdevaddr = 1;
13754 +                       i2cctl.b.i2cen = 0;
13755 +                       dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);
13756 +                       i2cctl.b.i2cen = 1;
13757 +                       dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);
13758 +               }
13759 +
13760 +       } /* endif speed == DWC_SPEED_PARAM_FULL */
13761 +       else {
13762 +               /* High speed PHY. */
13763 +               if (!core_if->phy_init_done) {
13764 +                       core_if->phy_init_done = 1;
13765 +                       /* HS PHY parameters.  These parameters are preserved
13766 +                        * during soft reset so only program the first time.  Do
13767 +                        * a soft reset immediately after setting phyif.  */
13768 +                       usbcfg.b.ulpi_utmi_sel = core_if->core_params->phy_type;
13769 +                       if (usbcfg.b.ulpi_utmi_sel == 1) {
13770 +                               /* ULPI interface */
13771 +                               usbcfg.b.phyif = 0;
13772 +                               usbcfg.b.ddrsel =
13773 +                                   core_if->core_params->phy_ulpi_ddr;
13774 +                       } else {
13775 +                               /* UTMI+ interface */
13776 +                               if (core_if->core_params->phy_utmi_width == 16) {
13777 +                                       usbcfg.b.phyif = 1;
13778 +
13779 +                               } else {
13780 +                                       usbcfg.b.phyif = 0;
13781 +                               }
13782 +
13783 +                       }
13784 +
13785 +                       dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
13786 +                       /* Reset after setting the PHY parameters */
13787 +                       dwc_otg_core_reset(core_if);
13788 +               }
13789 +       }
13790 +
13791 +       if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
13792 +           (core_if->hwcfg2.b.fs_phy_type == 1) &&
13793 +           (core_if->core_params->ulpi_fs_ls)) {
13794 +               DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
13795 +               usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
13796 +               usbcfg.b.ulpi_fsls = 1;
13797 +               usbcfg.b.ulpi_clk_sus_m = 1;
13798 +               dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
13799 +       } else {
13800 +               usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
13801 +               usbcfg.b.ulpi_fsls = 0;
13802 +               usbcfg.b.ulpi_clk_sus_m = 0;
13803 +               dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
13804 +       }
13805 +
13806 +       /* Program the GAHBCFG Register. */
13807 +       switch (core_if->hwcfg2.b.architecture) {
13808 +
13809 +       case DWC_SLAVE_ONLY_ARCH:
13810 +               DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
13811 +               ahbcfg.b.nptxfemplvl_txfemplvl =
13812 +                   DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
13813 +               ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
13814 +               core_if->dma_enable = 0;
13815 +               core_if->dma_desc_enable = 0;
13816 +               break;
13817 +
13818 +       case DWC_EXT_DMA_ARCH:
13819 +               DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
13820 +               {
13821 +                       uint8_t brst_sz = core_if->core_params->dma_burst_size;
13822 +                       ahbcfg.b.hburstlen = 0;
13823 +                       while (brst_sz > 1) {
13824 +                               ahbcfg.b.hburstlen++;
13825 +                               brst_sz >>= 1;
13826 +                       }
13827 +               }
13828 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
13829 +               core_if->dma_desc_enable =
13830 +                   (core_if->core_params->dma_desc_enable != 0);
13831 +               break;
13832 +
13833 +       case DWC_INT_DMA_ARCH:
13834 +               DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
13835 +               /*ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR; */
13836 +               ahbcfg.b.hburstlen = (1<<3)|(0<<0); /* WRESP=1, max 4 beats */
13837 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
13838 +               core_if->dma_desc_enable =
13839 +                   (core_if->core_params->dma_desc_enable != 0);
13840 +               break;
13841 +
13842 +       }
13843 +       if (core_if->dma_enable) {
13844 +               if (core_if->dma_desc_enable) {
13845 +                       DWC_PRINTF("Using Descriptor DMA mode\n");
13846 +               } else {
13847 +                       DWC_PRINTF("Using Buffer DMA mode\n");
13848 +
13849 +               }
13850 +       } else {
13851 +               DWC_PRINTF("Using Slave mode\n");
13852 +               core_if->dma_desc_enable = 0;
13853 +       }
13854 +       
13855 +       ahbcfg.b.dmaenable = core_if->dma_enable;
13856 +       dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32);
13857 +
13858 +       core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
13859 +
13860 +       core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
13861 +       core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
13862 +       DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n",
13863 +                  ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
13864 +       DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n",
13865 +                  ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
13866 +
13867 +       /* 
13868 +        * Program the GUSBCFG register. 
13869 +        */
13870 +       usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
13871 +
13872 +       switch (core_if->hwcfg2.b.op_mode) {
13873 +       case DWC_MODE_HNP_SRP_CAPABLE:
13874 +               usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
13875 +                                  DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
13876 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
13877 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
13878 +               break;
13879 +
13880 +       case DWC_MODE_SRP_ONLY_CAPABLE:
13881 +               usbcfg.b.hnpcap = 0;
13882 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
13883 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
13884 +               break;
13885 +
13886 +       case DWC_MODE_NO_HNP_SRP_CAPABLE:
13887 +               usbcfg.b.hnpcap = 0;
13888 +               usbcfg.b.srpcap = 0;
13889 +               break;
13890 +
13891 +       case DWC_MODE_SRP_CAPABLE_DEVICE:
13892 +               usbcfg.b.hnpcap = 0;
13893 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
13894 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
13895 +               break;
13896 +
13897 +       case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
13898 +               usbcfg.b.hnpcap = 0;
13899 +               usbcfg.b.srpcap = 0;
13900 +               break;
13901 +
13902 +       case DWC_MODE_SRP_CAPABLE_HOST:
13903 +               usbcfg.b.hnpcap = 0;
13904 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
13905 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
13906 +               break;
13907 +
13908 +       case DWC_MODE_NO_SRP_CAPABLE_HOST:
13909 +               usbcfg.b.hnpcap = 0;
13910 +               usbcfg.b.srpcap = 0;
13911 +               break;
13912 +       }
13913 +
13914 +       dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
13915 +
13916 +#ifdef CONFIG_USB_DWC_OTG_LPM
13917 +       if (core_if->core_params->lpm_enable) {
13918 +               glpmcfg_data_t lpmcfg = {.d32 = 0 };
13919 +
13920 +               /* To enable LPM support set lpm_cap_en bit */
13921 +               lpmcfg.b.lpm_cap_en = 1;
13922 +
13923 +               /* Make AppL1Res ACK */
13924 +               lpmcfg.b.appl_resp = 1;
13925 +
13926 +               /* Retry 3 times */
13927 +               lpmcfg.b.retry_count = 3;
13928 +
13929 +               dwc_modify_reg32(&core_if->core_global_regs->glpmcfg,
13930 +                                0, lpmcfg.d32);
13931 +
13932 +       }
13933 +#endif
13934 +       if (core_if->core_params->ic_usb_cap) {
13935 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
13936 +               gusbcfg.b.ic_usb_cap = 1;
13937 +               dwc_modify_reg32(&core_if->core_global_regs->gusbcfg,
13938 +                                0, gusbcfg.d32);
13939 +       }
13940 +
13941 +       /* Enable common interrupts */
13942 +       dwc_otg_enable_common_interrupts(core_if);
13943 +
13944 +       /* Do device or host intialization based on mode during PCD
13945 +        * and HCD initialization  */
13946 +       if (dwc_otg_is_host_mode(core_if)) {
13947 +               DWC_DEBUGPL(DBG_ANY, "Host Mode\n");
13948 +               core_if->op_state = A_HOST;
13949 +       } else {
13950 +               DWC_DEBUGPL(DBG_ANY, "Device Mode\n");
13951 +               core_if->op_state = B_PERIPHERAL;
13952 +#ifdef DWC_DEVICE_ONLY
13953 +               dwc_otg_core_dev_init(core_if);
13954 +#endif
13955 +       }
13956 +}
13957 +
13958 +/** 
13959 + * This function enables the Device mode interrupts.
13960 + *
13961 + * @param core_if Programming view of DWC_otg controller
13962 + */
13963 +void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
13964 +{
13965 +       gintmsk_data_t intr_mask = {.d32 = 0 };
13966 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
13967 +
13968 +       DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
13969 +
13970 +       /* Disable all interrupts. */
13971 +       dwc_write_reg32(&global_regs->gintmsk, 0);
13972 +
13973 +       /* Clear any pending interrupts */
13974 +       dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF);
13975 +
13976 +       /* Enable the common interrupts */
13977 +       dwc_otg_enable_common_interrupts(core_if);
13978 +
13979 +       /* Enable interrupts */
13980 +       intr_mask.b.usbreset = 1;
13981 +       intr_mask.b.enumdone = 1;
13982 +
13983 +       if (!core_if->multiproc_int_enable) {
13984 +               intr_mask.b.inepintr = 1;
13985 +               intr_mask.b.outepintr = 1;
13986 +       }
13987 +
13988 +       intr_mask.b.erlysuspend = 1;
13989 +
13990 +       if (core_if->en_multiple_tx_fifo == 0) {
13991 +               intr_mask.b.epmismatch = 1;
13992 +       }
13993 +#ifdef DWC_EN_ISOC
13994 +       if (core_if->dma_enable) {
13995 +               if (core_if->dma_desc_enable == 0) {
13996 +                       if (core_if->pti_enh_enable) {
13997 +                               dctl_data_t dctl = {.d32 = 0 };
13998 +                               dctl.b.ifrmnum = 1;
13999 +                               dwc_modify_reg32(&core_if->dev_if->
14000 +                                                dev_global_regs->dctl, 0,
14001 +                                                dctl.d32);
14002 +                       } else {
14003 +                               intr_mask.b.incomplisoin = 1;
14004 +                               intr_mask.b.incomplisoout = 1;
14005 +                       }
14006 +               }
14007 +       } else {
14008 +               intr_mask.b.incomplisoin = 1;
14009 +               intr_mask.b.incomplisoout = 1;
14010 +       }
14011 +#endif                         /* DWC_EN_ISOC */
14012 +
14013 +       /** @todo NGS: Should this be a module parameter? */
14014 +#ifdef USE_PERIODIC_EP
14015 +       intr_mask.b.isooutdrop = 1;
14016 +       intr_mask.b.eopframe = 1;
14017 +       intr_mask.b.incomplisoin = 1;
14018 +       intr_mask.b.incomplisoout = 1;
14019 +#endif
14020 +
14021 +       dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
14022 +
14023 +       DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
14024 +                   dwc_read_reg32(&global_regs->gintmsk));
14025 +}
14026 +
14027 +/**
14028 + * This function initializes the DWC_otg controller registers for
14029 + * device mode.
14030 + * 
14031 + * @param core_if Programming view of DWC_otg controller
14032 + *
14033 + */
14034 +void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
14035 +{
14036 +       int i;
14037 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
14038 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
14039 +       dwc_otg_core_params_t *params = core_if->core_params;
14040 +       dcfg_data_t dcfg = {.d32 = 0 };
14041 +       grstctl_t resetctl = {.d32 = 0 };
14042 +       uint32_t rx_fifo_size;
14043 +       fifosize_data_t nptxfifosize;
14044 +       fifosize_data_t txfifosize;
14045 +       dthrctl_data_t dthrctl;
14046 +       fifosize_data_t ptxfifosize;
14047 +
14048 +       /* Restart the Phy Clock */
14049 +       dwc_write_reg32(core_if->pcgcctl, 0);
14050 +
14051 +       /* Device configuration register */
14052 +       init_devspd(core_if);
14053 +       dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg);
14054 +       dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0;
14055 +       dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
14056 +
14057 +       dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
14058 +
14059 +       /* Configure data FIFO sizes */
14060 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
14061 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
14062 +                           core_if->total_fifo_size);
14063 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
14064 +                           params->dev_rx_fifo_size);
14065 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
14066 +                           params->dev_nperio_tx_fifo_size);
14067 +
14068 +               /* Rx FIFO */
14069 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
14070 +                           dwc_read_reg32(&global_regs->grxfsiz));
14071 +
14072 +#ifdef DWC_UTE_CFI
14073 +               core_if->pwron_rxfsiz = dwc_read_reg32(&global_regs->grxfsiz);
14074 +               core_if->init_rxfsiz = params->dev_rx_fifo_size;
14075 +#endif
14076 +               rx_fifo_size = params->dev_rx_fifo_size;
14077 +               dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size);
14078 +
14079 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
14080 +                           dwc_read_reg32(&global_regs->grxfsiz));
14081 +
14082 +               /** Set Periodic Tx FIFO Mask all bits 0 */
14083 +               core_if->p_tx_msk = 0;
14084 +
14085 +               /** Set Tx FIFO Mask all bits 0 */
14086 +               core_if->tx_msk = 0;
14087 +
14088 +               if (core_if->en_multiple_tx_fifo == 0) {
14089 +                       /* Non-periodic Tx FIFO */
14090 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
14091 +                                   dwc_read_reg32(&global_regs->gnptxfsiz));
14092 +
14093 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
14094 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
14095 +
14096 +                       dwc_write_reg32(&global_regs->gnptxfsiz,
14097 +                                       nptxfifosize.d32);
14098 +
14099 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
14100 +                                   dwc_read_reg32(&global_regs->gnptxfsiz));
14101 +
14102 +                       /**@todo NGS: Fix Periodic FIFO Sizing! */
14103 +                       /*
14104 +                        * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.
14105 +                        * Indexes of the FIFO size module parameters in the
14106 +                        * dev_perio_tx_fifo_size array and the FIFO size registers in
14107 +                        * the dptxfsiz array run from 0 to 14.
14108 +                        */
14109 +                       /** @todo Finish debug of this */
14110 +                       ptxfifosize.b.startaddr =
14111 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
14112 +                       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep;
14113 +                            i++) {
14114 +                               ptxfifosize.b.depth =
14115 +                                   params->dev_perio_tx_fifo_size[i];
14116 +                               DWC_DEBUGPL(DBG_CIL,
14117 +                                           "initial dptxfsiz_dieptxf[%d]=%08x\n",
14118 +                                           i,
14119 +                                           dwc_read_reg32(&global_regs->
14120 +                                                          dptxfsiz_dieptxf
14121 +                                                          [i]));
14122 +                               dwc_write_reg32(&global_regs->
14123 +                                               dptxfsiz_dieptxf[i],
14124 +                                               ptxfifosize.d32);
14125 +                               DWC_DEBUGPL(DBG_CIL,
14126 +                                           "new dptxfsiz_dieptxf[%d]=%08x\n",
14127 +                                           i,
14128 +                                           dwc_read_reg32(&global_regs->
14129 +                                                          dptxfsiz_dieptxf
14130 +                                                          [i]));
14131 +                               ptxfifosize.b.startaddr += ptxfifosize.b.depth;
14132 +                       }
14133 +               } else {
14134 +                       /*
14135 +                        * Tx FIFOs These FIFOs are numbered from 1 to 15.
14136 +                        * Indexes of the FIFO size module parameters in the
14137 +                        * dev_tx_fifo_size array and the FIFO size registers in
14138 +                        * the dptxfsiz_dieptxf array run from 0 to 14.
14139 +                        */
14140 +
14141 +                       /* Non-periodic Tx FIFO */
14142 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
14143 +                                   dwc_read_reg32(&global_regs->gnptxfsiz));
14144 +
14145 +#ifdef DWC_UTE_CFI
14146 +                       core_if->pwron_gnptxfsiz =
14147 +                           (dwc_read_reg32(&global_regs->gnptxfsiz) >> 16);
14148 +                       core_if->init_gnptxfsiz =
14149 +                           params->dev_nperio_tx_fifo_size;
14150 +#endif
14151 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
14152 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
14153 +
14154 +                       dwc_write_reg32(&global_regs->gnptxfsiz,
14155 +                                       nptxfifosize.d32);
14156 +
14157 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
14158 +                                   dwc_read_reg32(&global_regs->gnptxfsiz));
14159 +
14160 +                       txfifosize.b.startaddr =
14161 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
14162 +
14163 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
14164 +
14165 +                               txfifosize.b.depth =
14166 +                                   params->dev_tx_fifo_size[i];
14167 +
14168 +                               DWC_DEBUGPL(DBG_CIL,
14169 +                                           "initial dptxfsiz_dieptxf[%d]=%08x\n",
14170 +                                           i,
14171 +                                           dwc_read_reg32(&global_regs->
14172 +                                                          dptxfsiz_dieptxf
14173 +                                                          [i]));
14174 +
14175 +#ifdef DWC_UTE_CFI
14176 +                               core_if->pwron_txfsiz[i] =
14177 +                                   (dwc_read_reg32
14178 +                                    (&global_regs->dptxfsiz_dieptxf[i]) >> 16);
14179 +                               core_if->init_txfsiz[i] =
14180 +                                   params->dev_tx_fifo_size[i];
14181 +#endif
14182 +                               dwc_write_reg32(&global_regs->
14183 +                                               dptxfsiz_dieptxf[i],
14184 +                                               txfifosize.d32);
14185 +
14186 +                               DWC_DEBUGPL(DBG_CIL,
14187 +                                           "new dptxfsiz_dieptxf[%d]=%08x\n",
14188 +                                           i,
14189 +                                           dwc_read_reg32(&global_regs->
14190 +                                                          dptxfsiz_dieptxf
14191 +                                                          [i]));
14192 +
14193 +                               txfifosize.b.startaddr += txfifosize.b.depth;
14194 +                       }
14195 +               }
14196 +       }
14197 +       /* Flush the FIFOs */
14198 +       dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
14199 +       dwc_otg_flush_rx_fifo(core_if);
14200 +
14201 +       /* Flush the Learning Queue. */
14202 +       resetctl.b.intknqflsh = 1;
14203 +       dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32);
14204 +
14205 +       /* Clear all pending Device Interrupts */
14206 +       /** @todo - if the condition needed to be checked 
14207 +        *  or in any case all pending interrutps should be cleared? 
14208 +         */
14209 +       if (core_if->multiproc_int_enable) {
14210 +               for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
14211 +                       dwc_write_reg32(&dev_if->dev_global_regs->
14212 +                                       diepeachintmsk[i], 0);
14213 +               }
14214 +
14215 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
14216 +                       dwc_write_reg32(&dev_if->dev_global_regs->
14217 +                                       doepeachintmsk[i], 0);
14218 +               }
14219 +
14220 +               dwc_write_reg32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF);
14221 +               dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk, 0);
14222 +       } else {
14223 +               dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, 0);
14224 +               dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, 0);
14225 +               dwc_write_reg32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
14226 +               dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, 0);
14227 +       }
14228 +
14229 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
14230 +               depctl_data_t depctl;
14231 +               depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl);
14232 +               if (depctl.b.epena) {
14233 +                       depctl.d32 = 0;
14234 +                       depctl.b.epdis = 1;
14235 +                       depctl.b.snak = 1;
14236 +               } else {
14237 +                       depctl.d32 = 0;
14238 +               }
14239 +
14240 +               dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
14241 +
14242 +               dwc_write_reg32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
14243 +               dwc_write_reg32(&dev_if->in_ep_regs[i]->diepdma, 0);
14244 +               dwc_write_reg32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
14245 +       }
14246 +
14247 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
14248 +               depctl_data_t depctl;
14249 +               depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl);
14250 +               if (depctl.b.epena) {
14251 +                       depctl.d32 = 0;
14252 +                       depctl.b.epdis = 1;
14253 +                       depctl.b.snak = 1;
14254 +               } else {
14255 +                       depctl.d32 = 0;
14256 +               }
14257 +
14258 +               dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32);
14259 +
14260 +               dwc_write_reg32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
14261 +               dwc_write_reg32(&dev_if->out_ep_regs[i]->doepdma, 0);
14262 +               dwc_write_reg32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
14263 +       }
14264 +
14265 +       if (core_if->en_multiple_tx_fifo && core_if->dma_enable) {
14266 +               dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1;
14267 +               dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1;
14268 +               dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1;
14269 +
14270 +               dev_if->rx_thr_length = params->rx_thr_length;
14271 +               dev_if->tx_thr_length = params->tx_thr_length;
14272 +
14273 +               dev_if->setup_desc_index = 0;
14274 +
14275 +               dthrctl.d32 = 0;
14276 +               dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;
14277 +               dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;
14278 +               dthrctl.b.tx_thr_len = dev_if->tx_thr_length;
14279 +               dthrctl.b.rx_thr_en = dev_if->rx_thr_en;
14280 +               dthrctl.b.rx_thr_len = dev_if->rx_thr_length;
14281 +               dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio;
14282 +
14283 +               dwc_write_reg32(&dev_if->dev_global_regs->dtknqr3_dthrctl,
14284 +                               dthrctl.d32);
14285 +
14286 +               DWC_DEBUGPL(DBG_CIL,
14287 +                           "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",
14288 +                           dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,
14289 +                           dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,
14290 +                           dthrctl.b.rx_thr_len);
14291 +
14292 +       }
14293 +
14294 +       dwc_otg_enable_device_interrupts(core_if);
14295 +
14296 +       {
14297 +               diepmsk_data_t msk = {.d32 = 0 };
14298 +               msk.b.txfifoundrn = 1;
14299 +               if (core_if->multiproc_int_enable) {
14300 +                       dwc_modify_reg32(&dev_if->dev_global_regs->
14301 +                                        diepeachintmsk[0], msk.d32, msk.d32);
14302 +               } else {
14303 +                       dwc_modify_reg32(&dev_if->dev_global_regs->diepmsk,
14304 +                                        msk.d32, msk.d32);
14305 +               }
14306 +       }
14307 +
14308 +       if (core_if->multiproc_int_enable) {
14309 +               /* Set NAK on Babble */
14310 +               dctl_data_t dctl = {.d32 = 0 };
14311 +               dctl.b.nakonbble = 1;
14312 +               dwc_modify_reg32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
14313 +       }
14314 +}
14315 +
14316 +/** 
14317 + * This function enables the Host mode interrupts.
14318 + *
14319 + * @param core_if Programming view of DWC_otg controller
14320 + */
14321 +void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if)
14322 +{
14323 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
14324 +       gintmsk_data_t intr_mask = {.d32 = 0 };
14325 +
14326 +       DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if);
14327 +
14328 +       /* Disable all interrupts. */
14329 +       dwc_write_reg32(&global_regs->gintmsk, 0);
14330 +
14331 +       /* Clear any pending interrupts. */
14332 +       dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF);
14333 +
14334 +       /* Enable the common interrupts */
14335 +       dwc_otg_enable_common_interrupts(core_if);
14336 +
14337 +       /*
14338 +        * Enable host mode interrupts without disturbing common
14339 +        * interrupts.
14340 +        */
14341 +        
14342 +       /* Do not need sof interrupt for Descriptor DMA*/ 
14343 +       if (!core_if->dma_desc_enable) 
14344 +       intr_mask.b.sofintr = 1;
14345 +       intr_mask.b.portintr = 1;
14346 +       intr_mask.b.hcintr = 1;
14347 +
14348 +       dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
14349 +}
14350 +
14351 +/** 
14352 + * This function disables the Host Mode interrupts.
14353 + *
14354 + * @param core_if Programming view of DWC_otg controller
14355 + */
14356 +void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if)
14357 +{
14358 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
14359 +       gintmsk_data_t intr_mask = {.d32 = 0 };
14360 +
14361 +       DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);
14362 +
14363 +       /*
14364 +        * Disable host mode interrupts without disturbing common
14365 +        * interrupts.
14366 +        */
14367 +       intr_mask.b.sofintr = 1;
14368 +       intr_mask.b.portintr = 1;
14369 +       intr_mask.b.hcintr = 1;
14370 +       intr_mask.b.ptxfempty = 1;
14371 +       intr_mask.b.nptxfempty = 1;
14372 +
14373 +       dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 0);
14374 +}
14375 +
14376 +/**
14377 + * This function initializes the DWC_otg controller registers for
14378 + * host mode.
14379 + *
14380 + * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
14381 + * request queues. Host channels are reset to ensure that they are ready for
14382 + * performing transfers.
14383 + *
14384 + * @param core_if Programming view of DWC_otg controller
14385 + *
14386 + */
14387 +void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if)
14388 +{
14389 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
14390 +       dwc_otg_host_if_t *host_if = core_if->host_if;
14391 +       dwc_otg_core_params_t *params = core_if->core_params;
14392 +       hprt0_data_t hprt0 = {.d32 = 0 };
14393 +       fifosize_data_t nptxfifosize;
14394 +       fifosize_data_t ptxfifosize;
14395 +       int i;
14396 +       hcchar_data_t hcchar;
14397 +       hcfg_data_t hcfg;
14398 +       dwc_otg_hc_regs_t *hc_regs;
14399 +       int num_channels;
14400 +       gotgctl_data_t gotgctl = {.d32 = 0 };
14401 +
14402 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
14403 +
14404 +       /* Restart the Phy Clock */
14405 +       dwc_write_reg32(core_if->pcgcctl, 0);
14406 +
14407 +       /* Initialize Host Configuration Register */
14408 +       init_fslspclksel(core_if);
14409 +       if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
14410 +               hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg);
14411 +               hcfg.b.fslssupp = 1;
14412 +               dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32);
14413 +               
14414 +       }
14415 +
14416 +       if (core_if->core_params->dma_desc_enable) {
14417 +               uint8_t op_mode = core_if->hwcfg2.b.op_mode;    
14418 +               if (!(core_if->hwcfg4.b.desc_dma && (core_if->snpsid >= OTG_CORE_REV_2_90a) &&
14419 +                               ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ||
14420 +                               (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) || 
14421 +                               (op_mode == DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG) ||
14422 +                               (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST) ||
14423 +                               (op_mode == DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
14424 +                               
14425 +                               DWC_ERROR("Host can't operate in Descriptor DMA mode.\n"
14426 +                                         "Either core version is below 2.90a or "
14427 +                                         "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
14428 +                                         "To run the driver in Buffer DMA host mode set dma_desc_enable "
14429 +                                         "module parameter to 0.\n");
14430 +                               return;
14431 +               }               
14432 +               hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg);
14433 +               hcfg.b.descdma = 1;
14434 +               dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32);
14435 +       }
14436 +       
14437 +       /* Configure data FIFO sizes */
14438 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
14439 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
14440 +                           core_if->total_fifo_size);
14441 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
14442 +                           params->host_rx_fifo_size);
14443 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
14444 +                           params->host_nperio_tx_fifo_size);
14445 +               DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n",
14446 +                           params->host_perio_tx_fifo_size);
14447 +
14448 +               /* Rx FIFO */
14449 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
14450 +                           dwc_read_reg32(&global_regs->grxfsiz));
14451 +               dwc_write_reg32(&global_regs->grxfsiz,
14452 +                               params->host_rx_fifo_size);
14453 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
14454 +                           dwc_read_reg32(&global_regs->grxfsiz));
14455 +
14456 +               /* Non-periodic Tx FIFO */
14457 +               DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
14458 +                           dwc_read_reg32(&global_regs->gnptxfsiz));
14459 +               nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
14460 +               nptxfifosize.b.startaddr = params->host_rx_fifo_size;
14461 +               dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);
14462 +               DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
14463 +                           dwc_read_reg32(&global_regs->gnptxfsiz));
14464 +
14465 +               /* Periodic Tx FIFO */
14466 +               DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",
14467 +                           dwc_read_reg32(&global_regs->hptxfsiz));
14468 +               ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
14469 +               ptxfifosize.b.startaddr =
14470 +                   nptxfifosize.b.startaddr + nptxfifosize.b.depth;
14471 +               dwc_write_reg32(&global_regs->hptxfsiz, ptxfifosize.d32);
14472 +               DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",
14473 +                           dwc_read_reg32(&global_regs->hptxfsiz));
14474 +       }
14475 +
14476 +       /* Clear Host Set HNP Enable in the OTG Control Register */
14477 +       gotgctl.b.hstsethnpen = 1;
14478 +       dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0);
14479 +
14480 +       /* Make sure the FIFOs are flushed. */
14481 +       dwc_otg_flush_tx_fifo(core_if, 0x10 /* all Tx FIFOs */ );
14482 +       dwc_otg_flush_rx_fifo(core_if);
14483 +
14484 +       if(!core_if->core_params->dma_desc_enable) {
14485 +               /* Flush out any leftover queued requests. */
14486 +               num_channels = core_if->core_params->host_channels;
14487 +       
14488 +               for (i = 0; i < num_channels; i++) {
14489 +                       hc_regs = core_if->host_if->hc_regs[i];
14490 +                       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
14491 +                       hcchar.b.chen = 0;
14492 +                       hcchar.b.chdis = 1;
14493 +                       hcchar.b.epdir = 0;
14494 +                       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
14495 +               }
14496 +
14497 +               /* Halt all channels to put them into a known state. */
14498 +               for (i = 0; i < num_channels; i++) {
14499 +                       int count = 0;
14500 +                       hc_regs = core_if->host_if->hc_regs[i];
14501 +                       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
14502 +                       hcchar.b.chen = 1;
14503 +                       hcchar.b.chdis = 1;
14504 +                       hcchar.b.epdir = 0;
14505 +                       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
14506 +                       DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
14507 +                       do {
14508 +                               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
14509 +                               if (++count > 1000) {
14510 +                                       DWC_ERROR
14511 +                                           ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
14512 +                                            __func__, i, hcchar.d32, &hc_regs->hcchar);
14513 +                                       break;
14514 +                               }
14515 +                               dwc_udelay(1);
14516 +                       } while (hcchar.b.chen);
14517 +               }
14518 +       }
14519 +       
14520 +       /* Turn on the vbus power. */
14521 +       DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state);
14522 +       if (core_if->op_state == A_HOST) {
14523 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
14524 +               DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr);
14525 +               if (hprt0.b.prtpwr == 0) {
14526 +                       hprt0.b.prtpwr = 1;
14527 +                       dwc_write_reg32(host_if->hprt0, hprt0.d32);
14528 +               }
14529 +       }
14530 +
14531 +       dwc_otg_enable_host_interrupts(core_if);
14532 +}
14533 +
14534 +/**
14535 + * Prepares a host channel for transferring packets to/from a specific
14536 + * endpoint. The HCCHARn register is set up with the characteristics specified
14537 + * in _hc. Host channel interrupts that may need to be serviced while this
14538 + * transfer is in progress are enabled.
14539 + *
14540 + * @param core_if Programming view of DWC_otg controller
14541 + * @param hc Information needed to initialize the host channel
14542 + */
14543 +void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
14544 +{
14545 +       uint32_t intr_enable;
14546 +       hcintmsk_data_t hc_intr_mask;
14547 +       gintmsk_data_t gintmsk = {.d32 = 0 };
14548 +       hcchar_data_t hcchar;
14549 +       hcsplt_data_t hcsplt;
14550 +
14551 +       uint8_t hc_num = hc->hc_num;
14552 +       dwc_otg_host_if_t *host_if = core_if->host_if;
14553 +       dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
14554 +
14555 +       /* Clear old interrupt conditions for this host channel. */
14556 +       hc_intr_mask.d32 = 0xFFFFFFFF;
14557 +       hc_intr_mask.b.reserved14_31 = 0;
14558 +       dwc_write_reg32(&hc_regs->hcint, hc_intr_mask.d32);
14559 +
14560 +       /* Enable channel interrupts required for this transfer. */
14561 +       hc_intr_mask.d32 = 0;
14562 +       hc_intr_mask.b.chhltd = 1;
14563 +       if (core_if->dma_enable) {
14564 +               /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */
14565 +               if (!core_if->dma_desc_enable)
14566 +                       hc_intr_mask.b.ahberr = 1;
14567 +               else {
14568 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) 
14569 +                               hc_intr_mask.b.xfercompl = 1;
14570 +               }
14571 +               
14572 +               if (hc->error_state && !hc->do_split &&
14573 +                   hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
14574 +                       hc_intr_mask.b.ack = 1;
14575 +                       if (hc->ep_is_in) {
14576 +                               hc_intr_mask.b.datatglerr = 1;
14577 +                               if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
14578 +                                       hc_intr_mask.b.nak = 1;
14579 +                               }
14580 +                       }
14581 +               }
14582 +       } else {
14583 +               switch (hc->ep_type) {
14584 +               case DWC_OTG_EP_TYPE_CONTROL:
14585 +               case DWC_OTG_EP_TYPE_BULK:
14586 +                       hc_intr_mask.b.xfercompl = 1;
14587 +                       hc_intr_mask.b.stall = 1;
14588 +                       hc_intr_mask.b.xacterr = 1;
14589 +                       hc_intr_mask.b.datatglerr = 1;
14590 +                       if (hc->ep_is_in) {
14591 +                               hc_intr_mask.b.bblerr = 1;
14592 +                       } else {
14593 +                               hc_intr_mask.b.nak = 1;
14594 +                               hc_intr_mask.b.nyet = 1;
14595 +                               if (hc->do_ping) {
14596 +                                       hc_intr_mask.b.ack = 1;
14597 +                               }
14598 +                       }
14599 +
14600 +                       if (hc->do_split) {
14601 +                               hc_intr_mask.b.nak = 1;
14602 +                               if (hc->complete_split) {
14603 +                                       hc_intr_mask.b.nyet = 1;
14604 +                               } else {
14605 +                                       hc_intr_mask.b.ack = 1;
14606 +                               }
14607 +                       }
14608 +
14609 +                       if (hc->error_state) {
14610 +                               hc_intr_mask.b.ack = 1;
14611 +                       }
14612 +                       break;
14613 +               case DWC_OTG_EP_TYPE_INTR:
14614 +                       hc_intr_mask.b.xfercompl = 1;
14615 +                       hc_intr_mask.b.nak = 1;
14616 +                       hc_intr_mask.b.stall = 1;
14617 +                       hc_intr_mask.b.xacterr = 1;
14618 +                       hc_intr_mask.b.datatglerr = 1;
14619 +                       hc_intr_mask.b.frmovrun = 1;
14620 +
14621 +                       if (hc->ep_is_in) {
14622 +                               hc_intr_mask.b.bblerr = 1;
14623 +                       }
14624 +                       if (hc->error_state) {
14625 +                               hc_intr_mask.b.ack = 1;
14626 +                       }
14627 +                       if (hc->do_split) {
14628 +                               if (hc->complete_split) {
14629 +                                       hc_intr_mask.b.nyet = 1;
14630 +                               } else {
14631 +                                       hc_intr_mask.b.ack = 1;
14632 +                               }
14633 +                       }
14634 +                       break;
14635 +               case DWC_OTG_EP_TYPE_ISOC:
14636 +                       hc_intr_mask.b.xfercompl = 1;
14637 +                       hc_intr_mask.b.frmovrun = 1;
14638 +                       hc_intr_mask.b.ack = 1;
14639 +
14640 +                       if (hc->ep_is_in) {
14641 +                               hc_intr_mask.b.xacterr = 1;
14642 +                               hc_intr_mask.b.bblerr = 1;
14643 +                       }
14644 +                       break;
14645 +               }
14646 +       }
14647 +       dwc_write_reg32(&hc_regs->hcintmsk, hc_intr_mask.d32);
14648 +
14649 +       /* Enable the top level host channel interrupt. */
14650 +       intr_enable = (1 << hc_num);
14651 +       dwc_modify_reg32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
14652 +
14653 +       /* Make sure host channel interrupts are enabled. */
14654 +       gintmsk.b.hcintr = 1;
14655 +       dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
14656 +
14657 +       /*
14658 +        * Program the HCCHARn register with the endpoint characteristics for
14659 +        * the current transfer.
14660 +        */
14661 +       hcchar.d32 = 0;
14662 +       hcchar.b.devaddr = hc->dev_addr;
14663 +       hcchar.b.epnum = hc->ep_num;
14664 +       hcchar.b.epdir = hc->ep_is_in;
14665 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
14666 +       hcchar.b.eptype = hc->ep_type;
14667 +       hcchar.b.mps = hc->max_packet;
14668 +
14669 +       dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
14670 +
14671 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
14672 +       DWC_DEBUGPL(DBG_HCDV, "  Dev Addr: %d\n", hcchar.b.devaddr);
14673 +       DWC_DEBUGPL(DBG_HCDV, "  Ep Num: %d\n", hcchar.b.epnum);
14674 +       DWC_DEBUGPL(DBG_HCDV, "  Is In: %d\n", hcchar.b.epdir);
14675 +       DWC_DEBUGPL(DBG_HCDV, "  Is Low Speed: %d\n", hcchar.b.lspddev);
14676 +       DWC_DEBUGPL(DBG_HCDV, "  Ep Type: %d\n", hcchar.b.eptype);
14677 +       DWC_DEBUGPL(DBG_HCDV, "  Max Pkt: %d\n", hcchar.b.mps);
14678 +       DWC_DEBUGPL(DBG_HCDV, "  Multi Cnt: %d\n", hcchar.b.multicnt);
14679 +
14680 +       /*
14681 +        * Program the HCSPLIT register for SPLITs
14682 +        */
14683 +       hcsplt.d32 = 0;
14684 +       if (hc->do_split) {
14685 +               DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n",
14686 +                           hc->hc_num,
14687 +                           hc->complete_split ? "CSPLIT" : "SSPLIT");
14688 +               hcsplt.b.compsplt = hc->complete_split;
14689 +               hcsplt.b.xactpos = hc->xact_pos;
14690 +               hcsplt.b.hubaddr = hc->hub_addr;
14691 +               hcsplt.b.prtaddr = hc->port_addr;
14692 +               DWC_DEBUGPL(DBG_HCDV, "   comp split %d\n", hc->complete_split);
14693 +               DWC_DEBUGPL(DBG_HCDV, "   xact pos %d\n", hc->xact_pos);
14694 +               DWC_DEBUGPL(DBG_HCDV, "   hub addr %d\n", hc->hub_addr);
14695 +               DWC_DEBUGPL(DBG_HCDV, "   port addr %d\n", hc->port_addr);
14696 +               DWC_DEBUGPL(DBG_HCDV, "   is_in %d\n", hc->ep_is_in);
14697 +               DWC_DEBUGPL(DBG_HCDV, "   Max Pkt: %d\n", hcchar.b.mps);
14698 +               DWC_DEBUGPL(DBG_HCDV, "   xferlen: %d\n", hc->xfer_len);
14699 +       }
14700 +       dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
14701 +
14702 +}
14703 +
14704 +/**
14705 + * Attempts to halt a host channel. This function should only be called in
14706 + * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
14707 + * normal circumstances in DMA mode, the controller halts the channel when the
14708 + * transfer is complete or a condition occurs that requires application
14709 + * intervention.
14710 + *
14711 + * In slave mode, checks for a free request queue entry, then sets the Channel
14712 + * Enable and Channel Disable bits of the Host Channel Characteristics
14713 + * register of the specified channel to intiate the halt. If there is no free
14714 + * request queue entry, sets only the Channel Disable bit of the HCCHARn
14715 + * register to flush requests for this channel. In the latter case, sets a
14716 + * flag to indicate that the host channel needs to be halted when a request
14717 + * queue slot is open.
14718 + *
14719 + * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
14720 + * HCCHARn register. The controller ensures there is space in the request
14721 + * queue before submitting the halt request.
14722 + *
14723 + * Some time may elapse before the core flushes any posted requests for this
14724 + * host channel and halts. The Channel Halted interrupt handler completes the
14725 + * deactivation of the host channel.
14726 + *
14727 + * @param core_if Controller register interface.
14728 + * @param hc Host channel to halt.
14729 + * @param halt_status Reason for halting the channel.
14730 + */
14731 +void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if,
14732 +                    dwc_hc_t * hc, dwc_otg_halt_status_e halt_status)
14733 +{
14734 +       gnptxsts_data_t nptxsts;
14735 +       hptxsts_data_t hptxsts;
14736 +       hcchar_data_t hcchar;
14737 +       dwc_otg_hc_regs_t *hc_regs;
14738 +       dwc_otg_core_global_regs_t *global_regs;
14739 +       dwc_otg_host_global_regs_t *host_global_regs;
14740 +
14741 +       DWC_DEBUGPL(DBG_HW2937, "  dwc_otg_hc_halt(%d)\n", hc->hc_num);
14742 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
14743 +       global_regs = core_if->core_global_regs;
14744 +       host_global_regs = core_if->host_if->host_global_regs;
14745 +
14746 +       DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS),
14747 +                  "halt_status = %d\n", halt_status);
14748 +
14749 +       if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
14750 +           halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
14751 +               /*
14752 +                * Disable all channel interrupts except Ch Halted. The QTD
14753 +                * and QH state associated with this transfer has been cleared
14754 +                * (in the case of URB_DEQUEUE), so the channel needs to be
14755 +                * shut down carefully to prevent crashes.
14756 +                */
14757 +               hcintmsk_data_t hcintmsk;
14758 +               hcintmsk.d32 = 0;
14759 +               hcintmsk.b.chhltd = 1;
14760 +               dwc_write_reg32(&hc_regs->hcintmsk, hcintmsk.d32);
14761 +
14762 +               /*
14763 +                * Make sure no other interrupts besides halt are currently
14764 +                * pending. Handling another interrupt could cause a crash due
14765 +                * to the QTD and QH state.
14766 +                */
14767 +               dwc_write_reg32(&hc_regs->hcint, ~hcintmsk.d32);
14768 +
14769 +               /*
14770 +                * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
14771 +                * even if the channel was already halted for some other
14772 +                * reason.
14773 +                */
14774 +               hc->halt_status = halt_status;
14775 +
14776 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
14777 +               if (hcchar.b.chen == 0) {
14778 +                       /*
14779 +                        * The channel is either already halted or it hasn't
14780 +                        * started yet. In DMA mode, the transfer may halt if
14781 +                        * it finishes normally or a condition occurs that
14782 +                        * requires driver intervention. Don't want to halt
14783 +                        * the channel again. In either Slave or DMA mode,
14784 +                        * it's possible that the transfer has been assigned
14785 +                        * to a channel, but not started yet when an URB is
14786 +                        * dequeued. Don't want to halt a channel that hasn't
14787 +                        * started yet.
14788 +                        */
14789 +                       return;
14790 +               }
14791 +       }
14792 +       if (hc->halt_pending) {
14793 +               /*
14794 +                * A halt has already been issued for this channel. This might
14795 +                * happen when a transfer is aborted by a higher level in
14796 +                * the stack.
14797 +                */
14798 +#ifdef DEBUG
14799 +               DWC_PRINTF
14800 +                   ("*** %s: Channel %d, _hc->halt_pending already set ***\n",
14801 +                    __func__, hc->hc_num);
14802 +
14803 +#endif
14804 +               return;
14805 +       }
14806 +
14807 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
14808 +       
14809 +       /* No need to set the bit in DDMA for disabling the channel */
14810 +       //TODO check it everywhere channel is disabled          
14811 +       if(!core_if->core_params->dma_desc_enable)
14812 +               hcchar.b.chen = 1;
14813 +       hcchar.b.chdis = 1;
14814 +       
14815 +       if (!core_if->dma_enable) {
14816 +               /* Check for space in the request queue to issue the halt. */
14817 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
14818 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
14819 +                       nptxsts.d32 = dwc_read_reg32(&global_regs->gnptxsts);
14820 +                       if (nptxsts.b.nptxqspcavail == 0) {
14821 +                               hcchar.b.chen = 0;
14822 +                       }
14823 +               } else {
14824 +                       hptxsts.d32 =
14825 +                           dwc_read_reg32(&host_global_regs->hptxsts);
14826 +                       if ((hptxsts.b.ptxqspcavail == 0)
14827 +                           || (core_if->queuing_high_bandwidth)) {
14828 +                               hcchar.b.chen = 0;
14829 +                       }
14830 +               }
14831 +       }
14832 +       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
14833 +
14834 +       hc->halt_status = halt_status;
14835 +
14836 +       if (hcchar.b.chen) {
14837 +               hc->halt_pending = 1;
14838 +               hc->halt_on_queue = 0;
14839 +       } else {
14840 +               hc->halt_on_queue = 1;
14841 +       }
14842 +
14843 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
14844 +       DWC_DEBUGPL(DBG_HCDV, "  hcchar: 0x%08x\n", hcchar.d32);
14845 +       DWC_DEBUGPL(DBG_HCDV, "  halt_pending: %d\n", hc->halt_pending);
14846 +       DWC_DEBUGPL(DBG_HCDV, "  halt_on_queue: %d\n", hc->halt_on_queue);
14847 +       DWC_DEBUGPL(DBG_HCDV, "  halt_status: %d\n", hc->halt_status);
14848 +
14849 +       return;
14850 +}
14851 +
14852 +/**
14853 + * Clears the transfer state for a host channel. This function is normally
14854 + * called after a transfer is done and the host channel is being released.
14855 + *
14856 + * @param core_if Programming view of DWC_otg controller.
14857 + * @param hc Identifies the host channel to clean up.
14858 + */
14859 +void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
14860 +{
14861 +       dwc_otg_hc_regs_t *hc_regs;
14862 +
14863 +       hc->xfer_started = 0;
14864 +
14865 +       /*
14866 +        * Clear channel interrupt enables and any unhandled channel interrupt
14867 +        * conditions.
14868 +        */
14869 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
14870 +       dwc_write_reg32(&hc_regs->hcintmsk, 0);
14871 +       dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF);
14872 +#ifdef DEBUG
14873 +       DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]);
14874 +#endif
14875 +}
14876 +
14877 +/**
14878 + * Sets the channel property that indicates in which frame a periodic transfer
14879 + * should occur. This is always set to the _next_ frame. This function has no
14880 + * effect on non-periodic transfers.
14881 + *
14882 + * @param core_if Programming view of DWC_otg controller.
14883 + * @param hc Identifies the host channel to set up and its properties.
14884 + * @param hcchar Current value of the HCCHAR register for the specified host
14885 + * channel.
14886 + */
14887 +static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if,
14888 +                                        dwc_hc_t * hc, hcchar_data_t * hcchar)
14889 +{
14890 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
14891 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
14892 +               hfnum_data_t hfnum;
14893 +               hfnum.d32 =
14894 +                   dwc_read_reg32(&core_if->host_if->host_global_regs->hfnum);
14895 +
14896 +               /* 1 if _next_ frame is odd, 0 if it's even */
14897 +               hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
14898 +#ifdef DEBUG
14899 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split
14900 +                   && !hc->complete_split) {
14901 +                       switch (hfnum.b.frnum & 0x7) {
14902 +                       case 7:
14903 +                               core_if->hfnum_7_samples++;
14904 +                               core_if->hfnum_7_frrem_accum += hfnum.b.frrem;
14905 +                               break;
14906 +                       case 0:
14907 +                               core_if->hfnum_0_samples++;
14908 +                               core_if->hfnum_0_frrem_accum += hfnum.b.frrem;
14909 +                               break;
14910 +                       default:
14911 +                               core_if->hfnum_other_samples++;
14912 +                               core_if->hfnum_other_frrem_accum +=
14913 +                                   hfnum.b.frrem;
14914 +                               break;
14915 +                       }
14916 +               }
14917 +#endif
14918 +       }
14919 +}
14920 +
14921 +#ifdef DEBUG
14922 +void hc_xfer_timeout(void *ptr)
14923 +{
14924 +       hc_xfer_info_t *xfer_info = (hc_xfer_info_t *) ptr;
14925 +       int hc_num = xfer_info->hc->hc_num;
14926 +       DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);
14927 +       DWC_WARN("      start_hcchar_val 0x%08x\n",
14928 +                xfer_info->core_if->start_hcchar_val[hc_num]);
14929 +}
14930 +#endif
14931 +
14932 +void set_pid_isoc(dwc_hc_t * hc)
14933 +{
14934 +       /* Set up the initial PID for the transfer. */
14935 +       if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {
14936 +               if (hc->ep_is_in) {
14937 +                       if (hc->multi_count == 1) {
14938 +                               hc->data_pid_start =
14939 +                                   DWC_OTG_HC_PID_DATA0;
14940 +                       } else if (hc->multi_count == 2) {
14941 +                               hc->data_pid_start =
14942 +                                   DWC_OTG_HC_PID_DATA1;
14943 +                       } else {
14944 +                               hc->data_pid_start =
14945 +                                   DWC_OTG_HC_PID_DATA2;
14946 +                       }
14947 +               } else {
14948 +                       if (hc->multi_count == 1) {
14949 +                               hc->data_pid_start =
14950 +                                   DWC_OTG_HC_PID_DATA0;
14951 +                       } else {
14952 +                               hc->data_pid_start =
14953 +                                   DWC_OTG_HC_PID_MDATA;
14954 +                       }
14955 +               }
14956 +       } else {
14957 +               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
14958 +       }
14959 +}
14960 +
14961 +/**
14962 + * This function does the setup for a data transfer for a host channel and
14963 + * starts the transfer. May be called in either Slave mode or DMA mode. In
14964 + * Slave mode, the caller must ensure that there is sufficient space in the
14965 + * request queue and Tx Data FIFO.
14966 + *
14967 + * For an OUT transfer in Slave mode, it loads a data packet into the
14968 + * appropriate FIFO. If necessary, additional data packets will be loaded in
14969 + * the Host ISR.
14970 + *
14971 + * For an IN transfer in Slave mode, a data packet is requested. The data
14972 + * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
14973 + * additional data packets are requested in the Host ISR.
14974 + *
14975 + * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
14976 + * register along with a packet count of 1 and the channel is enabled. This
14977 + * causes a single PING transaction to occur. Other fields in HCTSIZ are
14978 + * simply set to 0 since no data transfer occurs in this case.
14979 + *
14980 + * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
14981 + * all the information required to perform the subsequent data transfer. In
14982 + * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
14983 + * controller performs the entire PING protocol, then starts the data
14984 + * transfer.
14985 + *
14986 + * @param core_if Programming view of DWC_otg controller.
14987 + * @param hc Information needed to initialize the host channel. The xfer_len
14988 + * value may be reduced to accommodate the max widths of the XferSize and
14989 + * PktCnt fields in the HCTSIZn register. The multi_count value may be changed
14990 + * to reflect the final xfer_len value.
14991 + */
14992 +void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
14993 +{
14994 +       hcchar_data_t hcchar;
14995 +       hctsiz_data_t hctsiz;
14996 +       uint16_t num_packets;
14997 +       uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size;
14998 +       uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count;
14999 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
15000 +
15001 +       hctsiz.d32 = 0;
15002 +
15003 +       if (hc->do_ping) {
15004 +               if (!core_if->dma_enable) {
15005 +                       dwc_otg_hc_do_ping(core_if, hc);
15006 +                       hc->xfer_started = 1;
15007 +                       return;
15008 +               } else {
15009 +                       hctsiz.b.dopng = 1;
15010 +               }
15011 +       }
15012 +
15013 +       if (hc->do_split) {
15014 +               num_packets = 1;
15015 +
15016 +               if (hc->complete_split && !hc->ep_is_in) {
15017 +                       /* For CSPLIT OUT Transfer, set the size to 0 so the
15018 +                        * core doesn't expect any data written to the FIFO */
15019 +                       hc->xfer_len = 0;
15020 +               } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
15021 +                       hc->xfer_len = hc->max_packet;
15022 +               } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
15023 +                       hc->xfer_len = 188;
15024 +               }
15025 +
15026 +               hctsiz.b.xfersize = hc->xfer_len;
15027 +       } else {
15028 +               /*
15029 +                * Ensure that the transfer length and packet count will fit
15030 +                * in the widths allocated for them in the HCTSIZn register.
15031 +                */
15032 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
15033 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
15034 +                       /*
15035 +                        * Make sure the transfer size is no larger than one
15036 +                        * (micro)frame's worth of data. (A check was done
15037 +                        * when the periodic transfer was accepted to ensure
15038 +                        * that a (micro)frame's worth of data can be
15039 +                        * programmed into a channel.)
15040 +                        */
15041 +                       uint32_t max_periodic_len =
15042 +                           hc->multi_count * hc->max_packet;
15043 +                       if (hc->xfer_len > max_periodic_len) {
15044 +                               hc->xfer_len = max_periodic_len;
15045 +                       } else {
15046 +                       }
15047 +               } else if (hc->xfer_len > max_hc_xfer_size) {
15048 +                       /* Make sure that xfer_len is a multiple of max packet size. */
15049 +                       hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;
15050 +               }
15051 +
15052 +               if (hc->xfer_len > 0) {
15053 +                       num_packets =
15054 +                           (hc->xfer_len + hc->max_packet -
15055 +                            1) / hc->max_packet;
15056 +                       if (num_packets > max_hc_pkt_count) {
15057 +                               num_packets = max_hc_pkt_count;
15058 +                               hc->xfer_len = num_packets * hc->max_packet;
15059 +                       }
15060 +               } else {
15061 +                       /* Need 1 packet for transfer length of 0. */
15062 +                       num_packets = 1;
15063 +               }
15064 +
15065 +               if (hc->ep_is_in) {
15066 +                       /* Always program an integral # of max packets for IN transfers. */
15067 +                       hc->xfer_len = num_packets * hc->max_packet;
15068 +               }
15069 +
15070 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
15071 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
15072 +                       /*
15073 +                        * Make sure that the multi_count field matches the
15074 +                        * actual transfer length.
15075 +                        */
15076 +                       hc->multi_count = num_packets;
15077 +               }
15078 +
15079 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
15080 +                       set_pid_isoc(hc);
15081 +
15082 +               hctsiz.b.xfersize = hc->xfer_len;
15083 +       }
15084 +
15085 +       hc->start_pkt_count = num_packets;
15086 +       hctsiz.b.pktcnt = num_packets;
15087 +       hctsiz.b.pid = hc->data_pid_start;
15088 +       dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
15089 +
15090 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
15091 +       DWC_DEBUGPL(DBG_HCDV, "  Xfer Size: %d\n", hctsiz.b.xfersize);
15092 +       DWC_DEBUGPL(DBG_HCDV, "  Num Pkts: %d\n", hctsiz.b.pktcnt);
15093 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
15094 +
15095 +       if (core_if->dma_enable) {
15096 +               dwc_dma_t dma_addr;
15097 +               if (hc->align_buff) {
15098 +                       dma_addr = hc->align_buff;
15099 +               } else {
15100 +                       dma_addr = (uint32_t)hc->xfer_buff;
15101 +               }
15102 +               dwc_write_reg32(&hc_regs->hcdma, dma_addr);
15103 +       }
15104 +
15105 +       /* Start the split */
15106 +       if (hc->do_split) {
15107 +               hcsplt_data_t hcsplt;
15108 +               hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt);
15109 +               hcsplt.b.spltena = 1;
15110 +               dwc_write_reg32(&hc_regs->hcsplt, hcsplt.d32);
15111 +       }
15112 +
15113 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
15114 +       hcchar.b.multicnt = hc->multi_count;
15115 +       hc_set_even_odd_frame(core_if, hc, &hcchar);
15116 +#ifdef DEBUG
15117 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
15118 +       if (hcchar.b.chdis) {
15119 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
15120 +                        __func__, hc->hc_num, hcchar.d32);
15121 +       }
15122 +#endif
15123 +
15124 +       /* Set host channel enable after all other setup is complete. */
15125 +       hcchar.b.chen = 1;
15126 +       hcchar.b.chdis = 0;
15127 +       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
15128 +
15129 +       hc->xfer_started = 1;
15130 +       hc->requests++;
15131 +
15132 +       if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) {
15133 +               /* Load OUT packet into the appropriate Tx FIFO. */
15134 +               dwc_otg_hc_write_packet(core_if, hc);
15135 +       }
15136 +#ifdef DEBUG
15137 +       if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
15138 +                DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n",
15139 +                            hc->hc_num, core_if);//GRAYG
15140 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
15141 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
15142 +               /* Start a timer for this transfer. */
15143 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
15144 +       }
15145 +#endif
15146 +}
15147 +
15148 +/**
15149 + * This function does the setup for a data transfer for a host channel 
15150 + * and starts the transfer in Descriptor DMA mode.
15151 + *
15152 + * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.
15153 + * Sets PID and NTD values. For periodic transfers
15154 + * initializes SCHED_INFO field with micro-frame bitmap.
15155 + *
15156 + * Initializes HCDMA register with descriptor list address and CTD value
15157 + * then starts the transfer via enabling the channel.
15158 + *
15159 + * @param core_if Programming view of DWC_otg controller.
15160 + * @param hc Information needed to initialize the host channel.
15161 + */
15162 +void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
15163 +{
15164 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];     
15165 +       hcchar_data_t hcchar;
15166 +       hctsiz_data_t hctsiz;
15167 +       hcdma_data_t  hcdma;
15168 +       
15169 +       hctsiz.d32 = 0;
15170 +
15171 +       if (hc->do_ping && !hc->ep_is_in)
15172 +               hctsiz.b_ddma.dopng = 1;
15173 +
15174 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
15175 +               set_pid_isoc(hc);
15176 +       
15177 +       /* Packet Count and Xfer Size are not used in Descriptor DMA mode */
15178 +       hctsiz.b_ddma.pid = hc->data_pid_start;
15179 +       hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */
15180 +       hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */
15181 +       
15182 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
15183 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
15184 +       DWC_DEBUGPL(DBG_HCDV, "  NTD: %d\n", hctsiz.b_ddma.ntd);        
15185 +
15186 +       dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
15187 +
15188 +       hcdma.d32 = 0;
15189 +       hcdma.b.dma_addr = ((uint32_t)hc->desc_list_addr) >> 11;
15190 +               
15191 +       /* Always start from first descriptor. */
15192 +       hcdma.b.ctd = 0;
15193 +       dwc_write_reg32(&hc_regs->hcdma, hcdma.d32);
15194 +
15195 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
15196 +       hcchar.b.multicnt = hc->multi_count;
15197 +       
15198 +#ifdef DEBUG
15199 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
15200 +       if (hcchar.b.chdis) {
15201 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
15202 +                        __func__, hc->hc_num, hcchar.d32);
15203 +       }
15204 +#endif
15205 +
15206 +       /* Set host channel enable after all other setup is complete. */
15207 +       hcchar.b.chen = 1;
15208 +       hcchar.b.chdis = 0;
15209 +       
15210 +       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
15211 +
15212 +       hc->xfer_started = 1;
15213 +       hc->requests++;
15214 +       
15215 +#ifdef DEBUG
15216 +       if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) {
15217 +                DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n",
15218 +                            hc->hc_num, core_if);//GRAYG
15219 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
15220 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
15221 +               /* Start a timer for this transfer. */
15222 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
15223 +       }
15224 +
15225 +#endif
15226 +       
15227 +}
15228 +       
15229 +/**
15230 + * This function continues a data transfer that was started by previous call
15231 + * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is
15232 + * sufficient space in the request queue and Tx Data FIFO. This function
15233 + * should only be called in Slave mode. In DMA mode, the controller acts
15234 + * autonomously to complete transfers programmed to a host channel.
15235 + *
15236 + * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
15237 + * if there is any data remaining to be queued. For an IN transfer, another
15238 + * data packet is always requested. For the SETUP phase of a control transfer,
15239 + * this function does nothing.
15240 + *
15241 + * @return 1 if a new request is queued, 0 if no more requests are required
15242 + * for this transfer.
15243 + */
15244 +int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
15245 +{
15246 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
15247 +
15248 +       if (hc->do_split) {
15249 +               /* SPLITs always queue just once per channel */
15250 +               return 0;
15251 +       } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
15252 +               /* SETUPs are queued only once since they can't be NAKed. */
15253 +               return 0;
15254 +       } else if (hc->ep_is_in) {
15255 +               /*
15256 +                * Always queue another request for other IN transfers. If
15257 +                * back-to-back INs are issued and NAKs are received for both,
15258 +                * the driver may still be processing the first NAK when the
15259 +                * second NAK is received. When the interrupt handler clears
15260 +                * the NAK interrupt for the first NAK, the second NAK will
15261 +                * not be seen. So we can't depend on the NAK interrupt
15262 +                * handler to requeue a NAKed request. Instead, IN requests
15263 +                * are issued each time this function is called. When the
15264 +                * transfer completes, the extra requests for the channel will
15265 +                * be flushed.
15266 +                */
15267 +               hcchar_data_t hcchar;
15268 +               dwc_otg_hc_regs_t *hc_regs =
15269 +                   core_if->host_if->hc_regs[hc->hc_num];
15270 +
15271 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
15272 +               hc_set_even_odd_frame(core_if, hc, &hcchar);
15273 +               hcchar.b.chen = 1;
15274 +               hcchar.b.chdis = 0;
15275 +               DWC_DEBUGPL(DBG_HCDV, "  IN xfer: hcchar = 0x%08x\n",
15276 +                           hcchar.d32);
15277 +               dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
15278 +               hc->requests++;
15279 +               return 1;
15280 +       } else {
15281 +               /* OUT transfers. */
15282 +               if (hc->xfer_count < hc->xfer_len) {
15283 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
15284 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
15285 +                               hcchar_data_t hcchar;
15286 +                               dwc_otg_hc_regs_t *hc_regs;
15287 +                               hc_regs = core_if->host_if->hc_regs[hc->hc_num];
15288 +                               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
15289 +                               hc_set_even_odd_frame(core_if, hc, &hcchar);
15290 +                       }
15291 +
15292 +                       /* Load OUT packet into the appropriate Tx FIFO. */
15293 +                       dwc_otg_hc_write_packet(core_if, hc);
15294 +                       hc->requests++;
15295 +                       return 1;
15296 +               } else {
15297 +                       return 0;
15298 +               }
15299 +       }
15300 +}
15301 +
15302 +/**
15303 + * Starts a PING transfer. This function should only be called in Slave mode.
15304 + * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
15305 + */
15306 +void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
15307 +{
15308 +       hcchar_data_t hcchar;
15309 +       hctsiz_data_t hctsiz;
15310 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
15311 +
15312 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
15313 +
15314 +       hctsiz.d32 = 0;
15315 +       hctsiz.b.dopng = 1;
15316 +       hctsiz.b.pktcnt = 1;
15317 +       dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
15318 +
15319 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
15320 +       hcchar.b.chen = 1;
15321 +       hcchar.b.chdis = 0;
15322 +       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
15323 +}
15324 +
15325 +/*
15326 + * This function writes a packet into the Tx FIFO associated with the Host
15327 + * Channel. For a channel associated with a non-periodic EP, the non-periodic
15328 + * Tx FIFO is written. For a channel associated with a periodic EP, the
15329 + * periodic Tx FIFO is written. This function should only be called in Slave
15330 + * mode.
15331 + *
15332 + * Upon return the xfer_buff and xfer_count fields in _hc are incremented by
15333 + * then number of bytes written to the Tx FIFO.
15334 + */
15335 +void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
15336 +{
15337 +       uint32_t i;
15338 +       uint32_t remaining_count;
15339 +       uint32_t byte_count;
15340 +       uint32_t dword_count;
15341 +
15342 +       uint32_t *data_buff = (uint32_t *) (hc->xfer_buff);
15343 +       uint32_t *data_fifo = core_if->data_fifo[hc->hc_num];
15344 +
15345 +       remaining_count = hc->xfer_len - hc->xfer_count;
15346 +       if (remaining_count > hc->max_packet) {
15347 +               byte_count = hc->max_packet;
15348 +       } else {
15349 +               byte_count = remaining_count;
15350 +       }
15351 +
15352 +       dword_count = (byte_count + 3) / 4;
15353 +
15354 +       if ((((unsigned long)data_buff) & 0x3) == 0) {
15355 +               /* xfer_buff is DWORD aligned. */
15356 +               for (i = 0; i < dword_count; i++, data_buff++) {
15357 +                       dwc_write_reg32(data_fifo, *data_buff);
15358 +               }
15359 +       } else {
15360 +               /* xfer_buff is not DWORD aligned. */
15361 +               for (i = 0; i < dword_count; i++, data_buff++) {
15362 +                       uint32_t data;
15363 +                       data =
15364 +                           (data_buff[0] | data_buff[1] << 8 | data_buff[2] <<
15365 +                            16 | data_buff[3] << 24);
15366 +                       dwc_write_reg32(data_fifo, data);
15367 +               }
15368 +       }
15369 +
15370 +       hc->xfer_count += byte_count;
15371 +       hc->xfer_buff += byte_count;
15372 +}
15373 +
15374 +/**
15375 + * Gets the current USB frame number. This is the frame number from the last 
15376 + * SOF packet. 
15377 + */
15378 +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if)
15379 +{
15380 +       dsts_data_t dsts;
15381 +       dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
15382 +
15383 +       /* read current frame/microframe number from DSTS register */
15384 +       return dsts.b.soffn;
15385 +}
15386 +
15387 +/**
15388 + * This function reads a setup packet from the Rx FIFO into the destination 
15389 + * buffer.     This function is called from the Rx Status Queue Level (RxStsQLvl)
15390 + * Interrupt routine when a SETUP packet has been received in Slave mode.
15391 + *
15392 + * @param core_if Programming view of DWC_otg controller.
15393 + * @param dest Destination buffer for packet data.
15394 + */
15395 +void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
15396 +{
15397 +       /* Get the 8 bytes of a setup transaction data */
15398 +
15399 +       /* Pop 2 DWORDS off the receive data FIFO into memory */
15400 +       dest[0] = dwc_read_reg32(core_if->data_fifo[0]);
15401 +       dest[1] = dwc_read_reg32(core_if->data_fifo[0]);
15402 +}
15403 +
15404 +/**
15405 + * This function enables EP0 OUT to receive SETUP packets and configures EP0 
15406 + * IN for transmitting packets.         It is normally called when the
15407 + * "Enumeration Done" interrupt occurs.
15408 + *
15409 + * @param core_if Programming view of DWC_otg controller.
15410 + * @param ep The EP0 data.
15411 + */
15412 +void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
15413 +{
15414 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
15415 +       dsts_data_t dsts;
15416 +       depctl_data_t diepctl;
15417 +       depctl_data_t doepctl;
15418 +       dctl_data_t dctl = {.d32 = 0 };
15419 +
15420 +       /* Read the Device Status and Endpoint 0 Control registers */
15421 +       dsts.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dsts);
15422 +       diepctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl);
15423 +       doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl);
15424 +
15425 +       /* Set the MPS of the IN EP based on the enumeration speed */
15426 +       switch (dsts.b.enumspd) {
15427 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
15428 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
15429 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
15430 +               diepctl.b.mps = DWC_DEP0CTL_MPS_64;
15431 +               break;
15432 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
15433 +               diepctl.b.mps = DWC_DEP0CTL_MPS_8;
15434 +               break;
15435 +       }
15436 +
15437 +       dwc_write_reg32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
15438 +
15439 +       /* Enable OUT EP for receive */
15440 +       doepctl.b.epena = 1;
15441 +       dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
15442 +
15443 +#ifdef VERBOSE
15444 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
15445 +                   dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));
15446 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
15447 +                   dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl));
15448 +#endif
15449 +       dctl.b.cgnpinnak = 1;
15450 +
15451 +       dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
15452 +       DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n",
15453 +                   dwc_read_reg32(&dev_if->dev_global_regs->dctl));
15454 +}
15455 +
15456 +/**
15457 + * This function activates an EP.  The Device EP control register for
15458 + * the EP is configured as defined in the ep structure.         Note: This
15459 + * function is not used for EP0.
15460 + *
15461 + * @param core_if Programming view of DWC_otg controller.
15462 + * @param ep The EP to activate.
15463 + */
15464 +void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
15465 +{
15466 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
15467 +       depctl_data_t depctl;
15468 +       volatile uint32_t *addr;
15469 +       daint_data_t daintmsk = {.d32 = 0 };
15470 +
15471 +       DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num,
15472 +                   (ep->is_in ? "IN" : "OUT"));
15473 +
15474 +       /* Read DEPCTLn register */
15475 +       if (ep->is_in == 1) {
15476 +               addr = &dev_if->in_ep_regs[ep->num]->diepctl;
15477 +               daintmsk.ep.in = 1 << ep->num;
15478 +       } else {
15479 +               addr = &dev_if->out_ep_regs[ep->num]->doepctl;
15480 +               daintmsk.ep.out = 1 << ep->num;
15481 +       }
15482 +
15483 +       /* If the EP is already active don't change the EP Control
15484 +        * register. */
15485 +       depctl.d32 = dwc_read_reg32(addr);
15486 +       if (!depctl.b.usbactep) {
15487 +               depctl.b.mps = ep->maxpacket;
15488 +               depctl.b.eptype = ep->type;
15489 +               depctl.b.txfnum = ep->tx_fifo_num;
15490 +
15491 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
15492 +                       depctl.b.setd0pid = 1;  // ??? 
15493 +               } else {
15494 +                       depctl.b.setd0pid = 1;
15495 +               }
15496 +               depctl.b.usbactep = 1;
15497 +
15498 +               dwc_write_reg32(addr, depctl.d32);
15499 +               DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", dwc_read_reg32(addr));
15500 +       }
15501 +
15502 +       /* Enable the Interrupt for this EP */
15503 +       if (core_if->multiproc_int_enable) {
15504 +               if (ep->is_in == 1) {
15505 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
15506 +                       diepmsk.b.xfercompl = 1;
15507 +                       diepmsk.b.timeout = 1;
15508 +                       diepmsk.b.epdisabled = 1;
15509 +                       diepmsk.b.ahberr = 1;
15510 +                       diepmsk.b.intknepmis = 1;
15511 +                       diepmsk.b.txfifoundrn = 1;      //?????
15512 +
15513 +                       if (core_if->dma_desc_enable) {
15514 +                               diepmsk.b.bna = 1;
15515 +                       }
15516 +/*                     
15517 +                       if(core_if->dma_enable) {
15518 +                               doepmsk.b.nak = 1;
15519 +                       }
15520 +*/
15521 +                       dwc_write_reg32(&dev_if->dev_global_regs->
15522 +                                       diepeachintmsk[ep->num], diepmsk.d32);
15523 +
15524 +               } else {
15525 +                       doepmsk_data_t doepmsk = {.d32 = 0 };
15526 +                       doepmsk.b.xfercompl = 1;
15527 +                       doepmsk.b.ahberr = 1;
15528 +                       doepmsk.b.epdisabled = 1;
15529 +
15530 +                       if (core_if->dma_desc_enable) {
15531 +                               doepmsk.b.bna = 1;
15532 +                       }
15533 +/*                     
15534 +                       doepmsk.b.babble = 1;
15535 +                       doepmsk.b.nyet = 1;
15536 +                       doepmsk.b.nak = 1;
15537 +*/
15538 +                       dwc_write_reg32(&dev_if->dev_global_regs->
15539 +                                       doepeachintmsk[ep->num], doepmsk.d32);
15540 +               }
15541 +               dwc_modify_reg32(&dev_if->dev_global_regs->deachintmsk,
15542 +                                0, daintmsk.d32);
15543 +       } else {
15544 +               dwc_modify_reg32(&dev_if->dev_global_regs->daintmsk,
15545 +                                0, daintmsk.d32);
15546 +       }
15547 +
15548 +       DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n",
15549 +                   dwc_read_reg32(&dev_if->dev_global_regs->daintmsk));
15550 +
15551 +       ep->stall_clear_flag = 0;
15552 +       return;
15553 +}
15554 +
15555 +/**
15556 + * This function deactivates an EP. This is done by clearing the USB Active 
15557 + * EP bit in the Device EP control register. Note: This function is not used 
15558 + * for EP0. EP0 cannot be deactivated.
15559 + *
15560 + * @param core_if Programming view of DWC_otg controller.
15561 + * @param ep The EP to deactivate.
15562 + */
15563 +void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
15564 +{
15565 +       depctl_data_t depctl = {.d32 = 0 };
15566 +       volatile uint32_t *addr;
15567 +       daint_data_t daintmsk = {.d32 = 0 };
15568 +
15569 +       /* Read DEPCTLn register */
15570 +       if (ep->is_in == 1) {
15571 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
15572 +               daintmsk.ep.in = 1 << ep->num;
15573 +       } else {
15574 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
15575 +               daintmsk.ep.out = 1 << ep->num;
15576 +       }
15577 +
15578 +       depctl.d32 = dwc_read_reg32(addr);
15579 +
15580 +       depctl.b.usbactep = 0;
15581 +
15582 +       if (core_if->dma_desc_enable)
15583 +               depctl.b.epdis = 1;
15584 +
15585 +       dwc_write_reg32(addr, depctl.d32);
15586 +
15587 +       /* Disable the Interrupt for this EP */
15588 +       if (core_if->multiproc_int_enable) {
15589 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->deachintmsk,
15590 +                                daintmsk.d32, 0);
15591 +
15592 +               if (ep->is_in == 1) {
15593 +                       dwc_write_reg32(&core_if->dev_if->dev_global_regs->
15594 +                                       diepeachintmsk[ep->num], 0);
15595 +               } else {
15596 +                       dwc_write_reg32(&core_if->dev_if->dev_global_regs->
15597 +                                       doepeachintmsk[ep->num], 0);
15598 +               }
15599 +       } else {
15600 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->daintmsk,
15601 +                                daintmsk.d32, 0);
15602 +       }
15603 +}
15604 +
15605 +/**
15606 + * This function initializes dma descriptor chain.
15607 + *
15608 + * @param core_if Programming view of DWC_otg controller.
15609 + * @param ep The EP to start the transfer on.
15610 + */
15611 +static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
15612 +{
15613 +       dwc_otg_dev_dma_desc_t *dma_desc;
15614 +       uint32_t offset;
15615 +       uint32_t xfer_est;
15616 +       int i;
15617 +
15618 +       ep->desc_cnt = (ep->total_len / ep->maxxfer) +
15619 +           ((ep->total_len % ep->maxxfer) ? 1 : 0);
15620 +       if (!ep->desc_cnt)
15621 +               ep->desc_cnt = 1;
15622 +
15623 +       dma_desc = ep->desc_addr;
15624 +       xfer_est = ep->total_len;
15625 +       offset = 0;
15626 +       for (i = 0; i < ep->desc_cnt; ++i) {
15627 +               /** DMA Descriptor Setup */
15628 +               if (xfer_est > ep->maxxfer) {
15629 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
15630 +                       dma_desc->status.b.l = 0;
15631 +                       dma_desc->status.b.ioc = 0;
15632 +                       dma_desc->status.b.sp = 0;
15633 +                       dma_desc->status.b.bytes = ep->maxxfer;
15634 +                       dma_desc->buf = ep->dma_addr + offset;
15635 +                       dma_desc->status.b.bs = BS_HOST_READY;
15636 +
15637 +                       xfer_est -= ep->maxxfer;
15638 +                       offset += ep->maxxfer;
15639 +               } else {
15640 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
15641 +                       dma_desc->status.b.l = 1;
15642 +                       dma_desc->status.b.ioc = 1;
15643 +                       if (ep->is_in) {
15644 +                               dma_desc->status.b.sp =
15645 +                                   (xfer_est %
15646 +                                    ep->maxpacket) ? 1 : ((ep->
15647 +                                                           sent_zlp) ? 1 : 0);
15648 +                               dma_desc->status.b.bytes = xfer_est;
15649 +                       } else {
15650 +                               dma_desc->status.b.bytes =
15651 +                                   xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
15652 +                       }
15653 +
15654 +                       dma_desc->buf = ep->dma_addr + offset;
15655 +                       dma_desc->status.b.bs = BS_HOST_READY;
15656 +               }
15657 +               dma_desc++;
15658 +       }
15659 +}
15660 +
15661 +/**
15662 + * This function does the setup for a data transfer for an EP and
15663 + * starts the transfer.         For an IN transfer, the packets will be
15664 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
15665 + * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.
15666 + *
15667 + * @param core_if Programming view of DWC_otg controller.
15668 + * @param ep The EP to start the transfer on.
15669 + */
15670 +
15671 +void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
15672 +{
15673 +       depctl_data_t depctl;
15674 +       deptsiz_data_t deptsiz;
15675 +       gintmsk_data_t intr_mask = {.d32 = 0 };
15676 +
15677 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
15678 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
15679 +                   "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n",
15680 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
15681 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff,
15682 +                   ep->total_len);
15683 +       /* IN endpoint */
15684 +       if (ep->is_in == 1) {
15685 +               dwc_otg_dev_in_ep_regs_t *in_regs =
15686 +                   core_if->dev_if->in_ep_regs[ep->num];
15687 +
15688 +               gnptxsts_data_t gtxstatus;
15689 +
15690 +               gtxstatus.d32 =
15691 +                   dwc_read_reg32(&core_if->core_global_regs->gnptxsts);
15692 +
15693 +               if (core_if->en_multiple_tx_fifo == 0
15694 +                   && gtxstatus.b.nptxqspcavail == 0) {
15695 +#ifdef DEBUG
15696 +                       DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32);
15697 +#endif
15698 +                       return;
15699 +               }
15700 +
15701 +               depctl.d32 = dwc_read_reg32(&(in_regs->diepctl));
15702 +               deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz));
15703 +
15704 +               ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
15705 +                   ep->maxxfer : (ep->total_len - ep->xfer_len);
15706 +
15707 +               /* Zero Length Packet? */
15708 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
15709 +                       deptsiz.b.xfersize = 0;
15710 +                       deptsiz.b.pktcnt = 1;
15711 +               } else {
15712 +                       /* Program the transfer size and packet count
15713 +                        *      as follows: xfersize = N * maxpacket +
15714 +                        *      short_packet pktcnt = N + (short_packet
15715 +                        *      exist ? 1 : 0)  
15716 +                        */
15717 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
15718 +                       deptsiz.b.pktcnt =
15719 +                           (ep->xfer_len - ep->xfer_count - 1 +
15720 +                            ep->maxpacket) / ep->maxpacket;
15721 +               }
15722 +
15723 +               /* Write the DMA register */
15724 +               if (core_if->dma_enable) {
15725 +                       if (core_if->dma_desc_enable == 0) {
15726 +                               dwc_write_reg32(&in_regs->dieptsiz,
15727 +                                               deptsiz.d32);
15728 +                               dwc_write_reg32(&(in_regs->diepdma),
15729 +                                               (uint32_t) ep->dma_addr);
15730 +                       } else {
15731 +#ifdef DWC_UTE_CFI
15732 +                               /* The descriptor chain should be already initialized by now */
15733 +                               if (ep->buff_mode != BM_STANDARD) {
15734 +                                       dwc_write_reg32(&in_regs->diepdma,
15735 +                                                       ep->descs_dma_addr);
15736 +                               } else {
15737 +#endif
15738 +                               init_dma_desc_chain(core_if, ep);
15739 +                               /** DIEPDMAn Register write */
15740 +                               dwc_write_reg32(&in_regs->diepdma,
15741 +                                               ep->dma_desc_addr);
15742 +#ifdef DWC_UTE_CFI
15743 +                       }
15744 +#endif
15745 +                       }
15746 +               } else {
15747 +                       dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
15748 +                       if (ep->type != DWC_OTG_EP_TYPE_ISOC) {
15749 +                               /** 
15750 +                                * Enable the Non-Periodic Tx FIFO empty interrupt,
15751 +                                * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
15752 +                                * the data will be written into the fifo by the ISR.
15753 +                                */
15754 +                               if (core_if->en_multiple_tx_fifo == 0) {
15755 +                                       intr_mask.b.nptxfempty = 1;
15756 +                                       dwc_modify_reg32(&core_if->
15757 +                                                        core_global_regs->
15758 +                                                        gintmsk, intr_mask.d32,
15759 +                                                        intr_mask.d32);
15760 +                               } else {
15761 +                                       /* Enable the Tx FIFO Empty Interrupt for this EP */
15762 +                                       if (ep->xfer_len > 0) {
15763 +                                               uint32_t fifoemptymsk = 0;
15764 +                                               fifoemptymsk = 1 << ep->num;
15765 +                                               dwc_modify_reg32(&core_if->
15766 +                                                                dev_if->
15767 +                                                                dev_global_regs->
15768 +                                                                dtknqr4_fifoemptymsk,
15769 +                                                                0,
15770 +                                                                fifoemptymsk);
15771 +
15772 +                                       }
15773 +                               }
15774 +                       }
15775 +               }
15776 +
15777 +               /* EP enable, IN data in FIFO */
15778 +               depctl.b.cnak = 1;
15779 +               depctl.b.epena = 1;
15780 +               dwc_write_reg32(&in_regs->diepctl, depctl.d32);
15781 +
15782 +               depctl.d32 =
15783 +                   dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl);
15784 +               depctl.b.nextep = ep->num;
15785 +               dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl,
15786 +                               depctl.d32);
15787 +
15788 +       } else {
15789 +               /* OUT endpoint */
15790 +               dwc_otg_dev_out_ep_regs_t *out_regs =
15791 +                   core_if->dev_if->out_ep_regs[ep->num];
15792 +
15793 +               depctl.d32 = dwc_read_reg32(&(out_regs->doepctl));
15794 +               deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz));
15795 +
15796 +               ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
15797 +                   ep->maxxfer : (ep->total_len - ep->xfer_len);
15798 +
15799 +               /* Program the transfer size and packet count as follows:
15800 +                * 
15801 +                *      pktcnt = N                                                                                 
15802 +                *      xfersize = N * maxpacket
15803 +                */
15804 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
15805 +                       /* Zero Length Packet */
15806 +                       deptsiz.b.xfersize = ep->maxpacket;
15807 +                       deptsiz.b.pktcnt = 1;
15808 +               } else {
15809 +                       deptsiz.b.pktcnt =
15810 +                           (ep->xfer_len - ep->xfer_count +
15811 +                            (ep->maxpacket - 1)) / ep->maxpacket;
15812 +                       ep->xfer_len =
15813 +                           deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
15814 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
15815 +               }
15816 +
15817 +               DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",
15818 +                           ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);
15819 +
15820 +               if (core_if->dma_enable) {
15821 +                       if (!core_if->dma_desc_enable) {
15822 +                               dwc_write_reg32(&out_regs->doeptsiz,
15823 +                                               deptsiz.d32);
15824 +
15825 +                               dwc_write_reg32(&(out_regs->doepdma),
15826 +                                               (uint32_t) ep->dma_addr);
15827 +                       } else {
15828 +#ifdef DWC_UTE_CFI
15829 +                               /* The descriptor chain should be already initialized by now */
15830 +                               if (ep->buff_mode != BM_STANDARD) {
15831 +                                       dwc_write_reg32(&out_regs->doepdma,
15832 +                                                       ep->descs_dma_addr);
15833 +                               } else {
15834 +#endif
15835 +
15836 +                               init_dma_desc_chain(core_if, ep);
15837 +
15838 +                               /** DOEPDMAn Register write */
15839 +                               dwc_write_reg32(&out_regs->doepdma,
15840 +                                               ep->dma_desc_addr);
15841 +#ifdef DWC_UTE_CFI
15842 +                               }
15843 +#endif
15844 +                       }
15845 +               } else {
15846 +                       dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
15847 +               }
15848 +
15849 +               /* EP enable */
15850 +               depctl.b.cnak = 1;
15851 +               depctl.b.epena = 1;
15852 +
15853 +               dwc_write_reg32(&out_regs->doepctl, depctl.d32);
15854 +
15855 +               DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
15856 +                           dwc_read_reg32(&out_regs->doepctl),
15857 +                           dwc_read_reg32(&out_regs->doeptsiz));
15858 +               DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
15859 +                           dwc_read_reg32(&core_if->dev_if->dev_global_regs->
15860 +                                          daintmsk),
15861 +                           dwc_read_reg32(&core_if->core_global_regs->
15862 +                                          gintmsk));
15863 +       }
15864 +}
15865 +
15866 +/**
15867 + * This function setup a zero length transfer in Buffer DMA and
15868 + * Slave modes for usb requests with zero field set
15869 + *
15870 + * @param core_if Programming view of DWC_otg controller.
15871 + * @param ep The EP to start the transfer on.
15872 + *
15873 + */
15874 +void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
15875 +{
15876 +
15877 +       depctl_data_t depctl;
15878 +       deptsiz_data_t deptsiz;
15879 +       gintmsk_data_t intr_mask = {.d32 = 0 };
15880 +
15881 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
15882 +       DWC_PRINTF("zero length transfer is called\n");
15883 +
15884 +       /* IN endpoint */
15885 +       if (ep->is_in == 1) {
15886 +               dwc_otg_dev_in_ep_regs_t *in_regs =
15887 +                   core_if->dev_if->in_ep_regs[ep->num];
15888 +
15889 +               depctl.d32 = dwc_read_reg32(&(in_regs->diepctl));
15890 +               deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz));
15891 +
15892 +               deptsiz.b.xfersize = 0;
15893 +               deptsiz.b.pktcnt = 1;
15894 +
15895 +               /* Write the DMA register */
15896 +               if (core_if->dma_enable) {
15897 +                       if (core_if->dma_desc_enable == 0) {
15898 +                               dwc_write_reg32(&in_regs->dieptsiz,
15899 +                                               deptsiz.d32);
15900 +                               dwc_write_reg32(&(in_regs->diepdma),
15901 +                                               (uint32_t) ep->dma_addr);
15902 +                       }
15903 +               } else {
15904 +                       dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
15905 +                       /** 
15906 +                        * Enable the Non-Periodic Tx FIFO empty interrupt,
15907 +                        * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
15908 +                        * the data will be written into the fifo by the ISR.
15909 +                        */
15910 +                       if (core_if->en_multiple_tx_fifo == 0) {
15911 +                               intr_mask.b.nptxfempty = 1;
15912 +                               dwc_modify_reg32(&core_if->core_global_regs->
15913 +                                                gintmsk, intr_mask.d32,
15914 +                                                intr_mask.d32);
15915 +                       } else {
15916 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
15917 +                               if (ep->xfer_len > 0) {
15918 +                                       uint32_t fifoemptymsk = 0;
15919 +                                       fifoemptymsk = 1 << ep->num;
15920 +                                       dwc_modify_reg32(&core_if->dev_if->
15921 +                                                        dev_global_regs->
15922 +                                                        dtknqr4_fifoemptymsk,
15923 +                                                        0, fifoemptymsk);
15924 +                               }
15925 +                       }
15926 +               }
15927 +
15928 +               /* EP enable, IN data in FIFO */
15929 +               depctl.b.cnak = 1;
15930 +               depctl.b.epena = 1;
15931 +               dwc_write_reg32(&in_regs->diepctl, depctl.d32);
15932 +
15933 +               depctl.d32 =
15934 +                   dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl);
15935 +               depctl.b.nextep = ep->num;
15936 +               dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl,
15937 +                               depctl.d32);
15938 +
15939 +       } else {
15940 +               /* OUT endpoint */
15941 +               dwc_otg_dev_out_ep_regs_t *out_regs =
15942 +                   core_if->dev_if->out_ep_regs[ep->num];
15943 +
15944 +               depctl.d32 = dwc_read_reg32(&(out_regs->doepctl));
15945 +               deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz));
15946 +
15947 +               /* Zero Length Packet */
15948 +               deptsiz.b.xfersize = ep->maxpacket;
15949 +               deptsiz.b.pktcnt = 1;
15950 +
15951 +               if (core_if->dma_enable) {
15952 +                       if (!core_if->dma_desc_enable) {
15953 +                               dwc_write_reg32(&out_regs->doeptsiz,
15954 +                                               deptsiz.d32);
15955 +
15956 +                               dwc_write_reg32(&(out_regs->doepdma),
15957 +                                               (uint32_t) ep->dma_addr);
15958 +                       }
15959 +               } else {
15960 +                       dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
15961 +               }
15962 +
15963 +               /* EP enable */
15964 +               depctl.b.cnak = 1;
15965 +               depctl.b.epena = 1;
15966 +
15967 +               dwc_write_reg32(&out_regs->doepctl, depctl.d32);
15968 +
15969 +       }
15970 +}
15971 +
15972 +/**
15973 + * This function does the setup for a data transfer for EP0 and starts
15974 + * the transfer.  For an IN transfer, the packets will be loaded into
15975 + * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
15976 + * unloaded from the Rx FIFO in the ISR.
15977 + *
15978 + * @param core_if Programming view of DWC_otg controller.
15979 + * @param ep The EP0 data.
15980 + */
15981 +void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
15982 +{
15983 +       depctl_data_t depctl;
15984 +       deptsiz0_data_t deptsiz;
15985 +       gintmsk_data_t intr_mask = {.d32 = 0 };
15986 +       dwc_otg_dev_dma_desc_t *dma_desc;
15987 +
15988 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
15989 +                   "xfer_buff=%p start_xfer_buff=%p \n",
15990 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
15991 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff);
15992 +
15993 +       ep->total_len = ep->xfer_len;
15994 +
15995 +       /* IN endpoint */
15996 +       if (ep->is_in == 1) {
15997 +               dwc_otg_dev_in_ep_regs_t *in_regs =
15998 +                   core_if->dev_if->in_ep_regs[0];
15999 +
16000 +               gnptxsts_data_t gtxstatus;
16001 +
16002 +               gtxstatus.d32 =
16003 +                   dwc_read_reg32(&core_if->core_global_regs->gnptxsts);
16004 +
16005 +               if (core_if->en_multiple_tx_fifo == 0
16006 +                   && gtxstatus.b.nptxqspcavail == 0) {
16007 +#ifdef DEBUG
16008 +                       deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz);
16009 +                       DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n",
16010 +                                   dwc_read_reg32(&in_regs->diepctl));
16011 +                       DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",
16012 +                                   deptsiz.d32,
16013 +                                   deptsiz.b.xfersize, deptsiz.b.pktcnt);
16014 +                       DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n",
16015 +                                  gtxstatus.d32);
16016 +#endif
16017 +                       return;
16018 +               }
16019 +
16020 +               depctl.d32 = dwc_read_reg32(&in_regs->diepctl);
16021 +               deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz);
16022 +
16023 +               /* Zero Length Packet? */
16024 +               if (ep->xfer_len == 0) {
16025 +                       deptsiz.b.xfersize = 0;
16026 +                       deptsiz.b.pktcnt = 1;
16027 +               } else {
16028 +                       /* Program the transfer size and packet count
16029 +                        *      as follows: xfersize = N * maxpacket +
16030 +                        *      short_packet pktcnt = N + (short_packet
16031 +                        *      exist ? 1 : 0)  
16032 +                        */
16033 +                       if (ep->xfer_len > ep->maxpacket) {
16034 +                               ep->xfer_len = ep->maxpacket;
16035 +                               deptsiz.b.xfersize = ep->maxpacket;
16036 +                       } else {
16037 +                               deptsiz.b.xfersize = ep->xfer_len;
16038 +                       }
16039 +                       deptsiz.b.pktcnt = 1;
16040 +
16041 +               }
16042 +               DWC_DEBUGPL(DBG_PCDV,
16043 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
16044 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
16045 +                           deptsiz.d32);
16046 +
16047 +               /* Write the DMA register */
16048 +               if (core_if->dma_enable) {
16049 +                       if (core_if->dma_desc_enable == 0) {
16050 +                               dwc_write_reg32(&in_regs->dieptsiz,
16051 +                                               deptsiz.d32);
16052 +
16053 +                               dwc_write_reg32(&(in_regs->diepdma),
16054 +                                               (uint32_t) ep->dma_addr);
16055 +                       } else {
16056 +                               dma_desc = core_if->dev_if->in_desc_addr;
16057 +
16058 +                               /** DMA Descriptor Setup */
16059 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
16060 +                               dma_desc->status.b.l = 1;
16061 +                               dma_desc->status.b.ioc = 1;
16062 +                               dma_desc->status.b.sp =
16063 +                                   (ep->xfer_len == ep->maxpacket) ? 0 : 1;
16064 +                               dma_desc->status.b.bytes = ep->xfer_len;
16065 +                               dma_desc->buf = ep->dma_addr;
16066 +                               dma_desc->status.b.bs = BS_HOST_READY;
16067 +
16068 +                               /** DIEPDMA0 Register write */
16069 +                               dwc_write_reg32(&in_regs->diepdma,
16070 +                                               core_if->dev_if->
16071 +                                               dma_in_desc_addr);
16072 +                       }
16073 +               } else {
16074 +                       dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
16075 +               }
16076 +
16077 +               /* EP enable, IN data in FIFO */
16078 +               depctl.b.cnak = 1;
16079 +               depctl.b.epena = 1;
16080 +               dwc_write_reg32(&in_regs->diepctl, depctl.d32);
16081 +
16082 +               /** 
16083 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
16084 +                * data will be written into the fifo by the ISR.
16085 +                */
16086 +               if (!core_if->dma_enable) {
16087 +                       if (core_if->en_multiple_tx_fifo == 0) {
16088 +                               intr_mask.b.nptxfempty = 1;
16089 +                               dwc_modify_reg32(&core_if->core_global_regs->
16090 +                                                gintmsk, intr_mask.d32,
16091 +                                                intr_mask.d32);
16092 +                       } else {
16093 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
16094 +                               if (ep->xfer_len > 0) {
16095 +                                       uint32_t fifoemptymsk = 0;
16096 +                                       fifoemptymsk |= 1 << ep->num;
16097 +                                       dwc_modify_reg32(&core_if->dev_if->
16098 +                                                        dev_global_regs->
16099 +                                                        dtknqr4_fifoemptymsk,
16100 +                                                        0, fifoemptymsk);
16101 +                               }
16102 +                       }
16103 +               }
16104 +       } else {
16105 +               /* OUT endpoint */
16106 +               dwc_otg_dev_out_ep_regs_t *out_regs =
16107 +                   core_if->dev_if->out_ep_regs[0];
16108 +
16109 +               depctl.d32 = dwc_read_reg32(&out_regs->doepctl);
16110 +               deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz);
16111 +
16112 +               /* Program the transfer size and packet count as follows:
16113 +                *      xfersize = N * (maxpacket + 4 - (maxpacket % 4))
16114 +                *      pktcnt = N                                                                                      */
16115 +               /* Zero Length Packet */
16116 +               deptsiz.b.xfersize = ep->maxpacket;
16117 +               deptsiz.b.pktcnt = 1;
16118 +
16119 +               DWC_DEBUGPL(DBG_PCDV, "len=%d  xfersize=%d pktcnt=%d\n",
16120 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt);
16121 +
16122 +               if (core_if->dma_enable) {
16123 +                       if (!core_if->dma_desc_enable) {
16124 +                               dwc_write_reg32(&out_regs->doeptsiz,
16125 +                                               deptsiz.d32);
16126 +
16127 +                               dwc_write_reg32(&(out_regs->doepdma),
16128 +                                               (uint32_t) ep->dma_addr);
16129 +                       } else {
16130 +                               dma_desc = core_if->dev_if->out_desc_addr;
16131 +
16132 +                               /** DMA Descriptor Setup */
16133 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
16134 +                               dma_desc->status.b.l = 1;
16135 +                               dma_desc->status.b.ioc = 1;
16136 +                               dma_desc->status.b.bytes = ep->maxpacket;
16137 +                               dma_desc->buf = ep->dma_addr;
16138 +                               dma_desc->status.b.bs = BS_HOST_READY;
16139 +
16140 +                               /** DOEPDMA0 Register write */
16141 +                               dwc_write_reg32(&out_regs->doepdma,
16142 +                                               core_if->dev_if->
16143 +                                               dma_out_desc_addr);
16144 +                       }
16145 +               } else {
16146 +                       dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
16147 +               }
16148 +
16149 +               /* EP enable */
16150 +               depctl.b.cnak = 1;
16151 +               depctl.b.epena = 1;
16152 +               dwc_write_reg32(&(out_regs->doepctl), depctl.d32);
16153 +       }
16154 +}
16155 +
16156 +/**
16157 + * This function continues control IN transfers started by
16158 + * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
16159 + * single packet.  NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
16160 + * bit for the packet count.
16161 + *
16162 + * @param core_if Programming view of DWC_otg controller.
16163 + * @param ep The EP0 data.
16164 + */
16165 +void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
16166 +{
16167 +       depctl_data_t depctl;
16168 +       deptsiz0_data_t deptsiz;
16169 +       gintmsk_data_t intr_mask = {.d32 = 0 };
16170 +       dwc_otg_dev_dma_desc_t *dma_desc;
16171 +
16172 +       if (ep->is_in == 1) {
16173 +               dwc_otg_dev_in_ep_regs_t *in_regs =
16174 +                   core_if->dev_if->in_ep_regs[0];
16175 +               gnptxsts_data_t tx_status = {.d32 = 0 };
16176 +
16177 +               tx_status.d32 =
16178 +                   dwc_read_reg32(&core_if->core_global_regs->gnptxsts);
16179 +               /** @todo Should there be check for room in the Tx
16180 +                * Status Queue.  If not remove the code above this comment. */
16181 +
16182 +               depctl.d32 = dwc_read_reg32(&in_regs->diepctl);
16183 +               deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz);
16184 +
16185 +               /* Program the transfer size and packet count
16186 +                *      as follows: xfersize = N * maxpacket +
16187 +                *      short_packet pktcnt = N + (short_packet
16188 +                *      exist ? 1 : 0)  
16189 +                */
16190 +
16191 +               if (core_if->dma_desc_enable == 0) {
16192 +                       deptsiz.b.xfersize =
16193 +                           (ep->total_len - ep->xfer_count) >
16194 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
16195 +                                                            ep->xfer_count);
16196 +                       deptsiz.b.pktcnt = 1;
16197 +                       if (core_if->dma_enable == 0) {
16198 +                               ep->xfer_len += deptsiz.b.xfersize;
16199 +                       } else {
16200 +                               ep->xfer_len = deptsiz.b.xfersize;
16201 +                       }
16202 +                       dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
16203 +               } else {
16204 +                       ep->xfer_len =
16205 +                           (ep->total_len - ep->xfer_count) >
16206 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
16207 +                                                            ep->xfer_count);
16208 +
16209 +                       dma_desc = core_if->dev_if->in_desc_addr;
16210 +
16211 +                       /** DMA Descriptor Setup */
16212 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
16213 +                       dma_desc->status.b.l = 1;
16214 +                       dma_desc->status.b.ioc = 1;
16215 +                       dma_desc->status.b.sp =
16216 +                           (ep->xfer_len == ep->maxpacket) ? 0 : 1;
16217 +                       dma_desc->status.b.bytes = ep->xfer_len;
16218 +                       dma_desc->buf = ep->dma_addr;
16219 +                       dma_desc->status.b.bs = BS_HOST_READY;
16220 +
16221 +                       /** DIEPDMA0 Register write */
16222 +                       dwc_write_reg32(&in_regs->diepdma,
16223 +                                       core_if->dev_if->dma_in_desc_addr);
16224 +               }
16225 +
16226 +               DWC_DEBUGPL(DBG_PCDV,
16227 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
16228 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
16229 +                           deptsiz.d32);
16230 +
16231 +               /* Write the DMA register */
16232 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
16233 +                       if (core_if->dma_desc_enable == 0)
16234 +                               dwc_write_reg32(&(in_regs->diepdma),
16235 +                                               (uint32_t) ep->dma_addr);
16236 +               }
16237 +
16238 +               /* EP enable, IN data in FIFO */
16239 +               depctl.b.cnak = 1;
16240 +               depctl.b.epena = 1;
16241 +               dwc_write_reg32(&in_regs->diepctl, depctl.d32);
16242 +
16243 +               /** 
16244 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
16245 +                * data will be written into the fifo by the ISR.
16246 +                */
16247 +               if (!core_if->dma_enable) {
16248 +                       if (core_if->en_multiple_tx_fifo == 0) {
16249 +                               /* First clear it from GINTSTS */
16250 +                               intr_mask.b.nptxfempty = 1;
16251 +                               dwc_modify_reg32(&core_if->core_global_regs->
16252 +                                                gintmsk, intr_mask.d32,
16253 +                                                intr_mask.d32);
16254 +
16255 +                       } else {
16256 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
16257 +                               if (ep->xfer_len > 0) {
16258 +                                       uint32_t fifoemptymsk = 0;
16259 +                                       fifoemptymsk |= 1 << ep->num;
16260 +                                       dwc_modify_reg32(&core_if->dev_if->
16261 +                                                        dev_global_regs->
16262 +                                                        dtknqr4_fifoemptymsk,
16263 +                                                        0, fifoemptymsk);
16264 +                               }
16265 +                       }
16266 +               }
16267 +       } else {
16268 +               dwc_otg_dev_out_ep_regs_t *out_regs =
16269 +                   core_if->dev_if->out_ep_regs[0];
16270 +
16271 +               depctl.d32 = dwc_read_reg32(&out_regs->doepctl);
16272 +               deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz);
16273 +
16274 +               /* Program the transfer size and packet count
16275 +                *      as follows: xfersize = N * maxpacket +
16276 +                *      short_packet pktcnt = N + (short_packet
16277 +                *      exist ? 1 : 0)  
16278 +                */
16279 +               deptsiz.b.xfersize = ep->maxpacket;
16280 +               deptsiz.b.pktcnt = 1;
16281 +
16282 +               if (core_if->dma_desc_enable == 0) {
16283 +                       dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
16284 +               } else {
16285 +                       dma_desc = core_if->dev_if->out_desc_addr;
16286 +
16287 +                       /** DMA Descriptor Setup */
16288 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
16289 +                       dma_desc->status.b.l = 1;
16290 +                       dma_desc->status.b.ioc = 1;
16291 +                       dma_desc->status.b.bytes = ep->maxpacket;
16292 +                       dma_desc->buf = ep->dma_addr;
16293 +                       dma_desc->status.b.bs = BS_HOST_READY;
16294 +
16295 +                       /** DOEPDMA0 Register write */
16296 +                       dwc_write_reg32(&out_regs->doepdma,
16297 +                                       core_if->dev_if->dma_out_desc_addr);
16298 +               }
16299 +
16300 +               DWC_DEBUGPL(DBG_PCDV,
16301 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
16302 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
16303 +                           deptsiz.d32);
16304 +
16305 +               /* Write the DMA register */
16306 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
16307 +                       if (core_if->dma_desc_enable == 0)
16308 +                               dwc_write_reg32(&(out_regs->doepdma),
16309 +                                               (uint32_t) ep->dma_addr);
16310 +               }
16311 +
16312 +               /* EP enable, IN data in FIFO */
16313 +               depctl.b.cnak = 1;
16314 +               depctl.b.epena = 1;
16315 +               dwc_write_reg32(&out_regs->doepctl, depctl.d32);
16316 +
16317 +       }
16318 +}
16319 +
16320 +#ifdef DEBUG
16321 +void dump_msg(const u8 * buf, unsigned int length)
16322 +{
16323 +       unsigned int start, num, i;
16324 +       char line[52], *p;
16325 +
16326 +       if (length >= 512)
16327 +               return;
16328 +       start = 0;
16329 +       while (length > 0) {
16330 +               num = length < 16u ? length : 16u;
16331 +               p = line;
16332 +               for (i = 0; i < num; ++i) {
16333 +                       if (i == 8)
16334 +                               *p++ = ' ';
16335 +                       DWC_SPRINTF(p, " %02x", buf[i]);
16336 +                       p += 3;
16337 +               }
16338 +               *p = 0;
16339 +               DWC_PRINTF("%6x: %s\n", start, line);
16340 +               buf += num;
16341 +               start += num;
16342 +               length -= num;
16343 +       }
16344 +}
16345 +#else
16346 +static inline void dump_msg(const u8 * buf, unsigned int length)
16347 +{
16348 +}
16349 +#endif
16350 +
16351 +/**
16352 + * This function writes a packet into the Tx FIFO associated with the
16353 + * EP. For non-periodic EPs the non-periodic Tx FIFO is written.  For
16354 + * periodic EPs the periodic Tx FIFO associated with the EP is written
16355 + * with all packets for the next micro-frame.
16356 + *
16357 + * @param core_if Programming view of DWC_otg controller.
16358 + * @param ep The EP to write packet for.
16359 + * @param dma Indicates if DMA is being used.
16360 + */
16361 +void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
16362 +                            int dma)
16363 +{
16364 +       /**
16365 +        * The buffer is padded to DWORD on a per packet basis in
16366 +        * slave/dma mode if the MPS is not DWORD aligned.      The last
16367 +        * packet, if short, is also padded to a multiple of DWORD.
16368 +        *
16369 +        * ep->xfer_buff always starts DWORD aligned in memory and is a 
16370 +        * multiple of DWORD in length
16371 +        *
16372 +        * ep->xfer_len can be any number of bytes
16373 +        *
16374 +        * ep->xfer_count is a multiple of ep->maxpacket until the last 
16375 +        *      packet
16376 +        *
16377 +        * FIFO access is DWORD */
16378 +
16379 +       uint32_t i;
16380 +       uint32_t byte_count;
16381 +       uint32_t dword_count;
16382 +       uint32_t *fifo;
16383 +       uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
16384 +
16385 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if,
16386 +                   ep);
16387 +       if (ep->xfer_count >= ep->xfer_len) {
16388 +               DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num);
16389 +               return;
16390 +       }
16391 +
16392 +       /* Find the byte length of the packet either short packet or MPS */
16393 +       if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) {
16394 +               byte_count = ep->xfer_len - ep->xfer_count;
16395 +       } else {
16396 +               byte_count = ep->maxpacket;
16397 +       }
16398 +
16399 +       /* Find the DWORD length, padded by extra bytes as neccessary if MPS
16400 +        * is not a multiple of DWORD */
16401 +       dword_count = (byte_count + 3) / 4;
16402 +
16403 +#ifdef VERBOSE
16404 +       dump_msg(ep->xfer_buff, byte_count);
16405 +#endif
16406 +
16407 +       /**@todo NGS Where are the Periodic Tx FIFO addresses
16408 +        * intialized?  What should this be? */
16409 +
16410 +       fifo = core_if->data_fifo[ep->num];
16411 +
16412 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n",
16413 +                   fifo, data_buff, *data_buff, byte_count);
16414 +
16415 +       if (!dma) {
16416 +               for (i = 0; i < dword_count; i++, data_buff++) {
16417 +                       dwc_write_reg32(fifo, *data_buff);
16418 +               }
16419 +       }
16420 +
16421 +       ep->xfer_count += byte_count;
16422 +       ep->xfer_buff += byte_count;
16423 +       ep->dma_addr += byte_count;
16424 +}
16425 +
16426 +/** 
16427 + * Set the EP STALL.
16428 + *
16429 + * @param core_if Programming view of DWC_otg controller.
16430 + * @param ep The EP to set the stall on.
16431 + */
16432 +void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
16433 +{
16434 +       depctl_data_t depctl;
16435 +       volatile uint32_t *depctl_addr;
16436 +
16437 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
16438 +                   (ep->is_in ? "IN" : "OUT"));
16439 +
16440 +       if (ep->is_in == 1) {
16441 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
16442 +               depctl.d32 = dwc_read_reg32(depctl_addr);
16443 +
16444 +               /* set the disable and stall bits */
16445 +               if (depctl.b.epena) {
16446 +                       depctl.b.epdis = 1;
16447 +               }
16448 +               depctl.b.stall = 1;
16449 +               dwc_write_reg32(depctl_addr, depctl.d32);
16450 +       } else {
16451 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
16452 +               depctl.d32 = dwc_read_reg32(depctl_addr);
16453 +
16454 +               /* set the stall bit */
16455 +               depctl.b.stall = 1;
16456 +               dwc_write_reg32(depctl_addr, depctl.d32);
16457 +       }
16458 +
16459 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr));
16460 +
16461 +       return;
16462 +}
16463 +
16464 +/** 
16465 + * Clear the EP STALL.
16466 + *
16467 + * @param core_if Programming view of DWC_otg controller.
16468 + * @param ep The EP to clear stall from.
16469 + */
16470 +void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
16471 +{
16472 +       depctl_data_t depctl;
16473 +       volatile uint32_t *depctl_addr;
16474 +
16475 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
16476 +                   (ep->is_in ? "IN" : "OUT"));
16477 +
16478 +       if (ep->is_in == 1) {
16479 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
16480 +       } else {
16481 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
16482 +       }
16483 +
16484 +       depctl.d32 = dwc_read_reg32(depctl_addr);
16485 +
16486 +       /* clear the stall bits */
16487 +       depctl.b.stall = 0;
16488 +
16489 +       /* 
16490 +        * USB Spec 9.4.5: For endpoints using data toggle, regardless
16491 +        * of whether an endpoint has the Halt feature set, a
16492 +        * ClearFeature(ENDPOINT_HALT) request always results in the
16493 +        * data toggle being reinitialized to DATA0.
16494 +        */
16495 +       if (ep->type == DWC_OTG_EP_TYPE_INTR ||
16496 +           ep->type == DWC_OTG_EP_TYPE_BULK) {
16497 +               depctl.b.setd0pid = 1;  /* DATA0 */
16498 +       }
16499 +
16500 +       dwc_write_reg32(depctl_addr, depctl.d32);
16501 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr));
16502 +       return;
16503 +}
16504 +
16505 +/** 
16506 + * This function reads a packet from the Rx FIFO into the destination
16507 + * buffer.     To read SETUP data use dwc_otg_read_setup_packet.
16508 + *
16509 + * @param core_if Programming view of DWC_otg controller.
16510 + * @param dest   Destination buffer for the packet.
16511 + * @param bytes  Number of bytes to copy to the destination.
16512 + */
16513 +void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
16514 +                        uint8_t * dest, uint16_t bytes)
16515 +{
16516 +       int i;
16517 +       int word_count = (bytes + 3) / 4;
16518 +
16519 +       volatile uint32_t *fifo = core_if->data_fifo[0];
16520 +       uint32_t *data_buff = (uint32_t *) dest;
16521 +
16522 +       /**
16523 +        * @todo Account for the case where _dest is not dword aligned. This
16524 +        * requires reading data from the FIFO into a uint32_t temp buffer,
16525 +        * then moving it into the data buffer.
16526 +        */
16527 +
16528 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__,
16529 +                   core_if, dest, bytes);
16530 +
16531 +       for (i = 0; i < word_count; i++, data_buff++) {
16532 +               *data_buff = dwc_read_reg32(fifo);
16533 +       }
16534 +
16535 +       return;
16536 +}
16537 +
16538 +/**
16539 + * This functions reads the device registers and prints them
16540 + *
16541 + * @param core_if Programming view of DWC_otg controller.
16542 + */
16543 +void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if)
16544 +{
16545 +       int i;
16546 +       volatile uint32_t *addr;
16547 +
16548 +       DWC_PRINTF("Device Global Registers\n");
16549 +       addr = &core_if->dev_if->dev_global_regs->dcfg;
16550 +       DWC_PRINTF("DCFG                 @0x%08X : 0x%08X\n", (uint32_t) addr,
16551 +                  dwc_read_reg32(addr));
16552 +       addr = &core_if->dev_if->dev_global_regs->dctl;
16553 +       DWC_PRINTF("DCTL                 @0x%08X : 0x%08X\n", (uint32_t) addr,
16554 +                  dwc_read_reg32(addr));
16555 +       addr = &core_if->dev_if->dev_global_regs->dsts;
16556 +       DWC_PRINTF("DSTS                 @0x%08X : 0x%08X\n", (uint32_t) addr,
16557 +                  dwc_read_reg32(addr));
16558 +       addr = &core_if->dev_if->dev_global_regs->diepmsk;
16559 +       DWC_PRINTF("DIEPMSK      @0x%08X : 0x%08X\n", (uint32_t) addr,
16560 +                  dwc_read_reg32(addr));
16561 +       addr = &core_if->dev_if->dev_global_regs->doepmsk;
16562 +       DWC_PRINTF("DOEPMSK      @0x%08X : 0x%08X\n", (uint32_t) addr,
16563 +                  dwc_read_reg32(addr));
16564 +       addr = &core_if->dev_if->dev_global_regs->daint;
16565 +       DWC_PRINTF("DAINT        @0x%08X : 0x%08X\n", (uint32_t) addr,
16566 +                  dwc_read_reg32(addr));
16567 +       addr = &core_if->dev_if->dev_global_regs->daintmsk;
16568 +       DWC_PRINTF("DAINTMSK     @0x%08X : 0x%08X\n", (uint32_t) addr,
16569 +                  dwc_read_reg32(addr));
16570 +       addr = &core_if->dev_if->dev_global_regs->dtknqr1;
16571 +       DWC_PRINTF("DTKNQR1      @0x%08X : 0x%08X\n", (uint32_t) addr,
16572 +                  dwc_read_reg32(addr));
16573 +       if (core_if->hwcfg2.b.dev_token_q_depth > 6) {
16574 +               addr = &core_if->dev_if->dev_global_regs->dtknqr2;
16575 +               DWC_PRINTF("DTKNQR2      @0x%08X : 0x%08X\n",
16576 +                          (uint32_t) addr, dwc_read_reg32(addr));
16577 +       }
16578 +
16579 +       addr = &core_if->dev_if->dev_global_regs->dvbusdis;
16580 +       DWC_PRINTF("DVBUSID      @0x%08X : 0x%08X\n", (uint32_t) addr,
16581 +                  dwc_read_reg32(addr));
16582 +
16583 +       addr = &core_if->dev_if->dev_global_regs->dvbuspulse;
16584 +       DWC_PRINTF("DVBUSPULSE  @0x%08X : 0x%08X\n",
16585 +                  (uint32_t) addr, dwc_read_reg32(addr));
16586 +
16587 +               addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl;
16588 +               DWC_PRINTF("DTKNQR3_DTHRCTL      @0x%08X : 0x%08X\n",
16589 +                          (uint32_t) addr, dwc_read_reg32(addr));
16590 +
16591 +       if (core_if->hwcfg2.b.dev_token_q_depth > 22) {
16592 +               addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
16593 +               DWC_PRINTF("DTKNQR4      @0x%08X : 0x%08X\n",
16594 +                          (uint32_t) addr, dwc_read_reg32(addr));
16595 +       }
16596 +
16597 +       addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
16598 +       DWC_PRINTF("FIFOEMPMSK   @0x%08X : 0x%08X\n", (uint32_t) addr,
16599 +                  dwc_read_reg32(addr));
16600 +
16601 +       addr = &core_if->dev_if->dev_global_regs->deachint;
16602 +       DWC_PRINTF("DEACHINT     @0x%08X : 0x%08X\n", (uint32_t) addr,
16603 +                  dwc_read_reg32(addr));
16604 +       addr = &core_if->dev_if->dev_global_regs->deachintmsk;
16605 +       DWC_PRINTF("DEACHINTMSK  @0x%08X : 0x%08X\n", (uint32_t) addr,
16606 +                  dwc_read_reg32(addr));
16607 +
16608 +       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
16609 +               addr = &core_if->dev_if->dev_global_regs->diepeachintmsk[i];
16610 +               DWC_PRINTF("DIEPEACHINTMSK[%d]   @0x%08X : 0x%08X\n", i,
16611 +                          (uint32_t) addr, dwc_read_reg32(addr));
16612 +       }
16613 +
16614 +       for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
16615 +               addr = &core_if->dev_if->dev_global_regs->doepeachintmsk[i];
16616 +               DWC_PRINTF("DOEPEACHINTMSK[%d]   @0x%08X : 0x%08X\n", i,
16617 +                          (uint32_t) addr, dwc_read_reg32(addr));
16618 +       }
16619 +
16620 +       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
16621 +               DWC_PRINTF("Device IN EP %d Registers\n", i);
16622 +               addr = &core_if->dev_if->in_ep_regs[i]->diepctl;
16623 +               DWC_PRINTF("DIEPCTL      @0x%08X : 0x%08X\n", (uint32_t) addr,
16624 +                          dwc_read_reg32(addr));
16625 +               addr = &core_if->dev_if->in_ep_regs[i]->diepint;
16626 +               DWC_PRINTF("DIEPINT      @0x%08X : 0x%08X\n", (uint32_t) addr,
16627 +                          dwc_read_reg32(addr));
16628 +               addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz;
16629 +               DWC_PRINTF("DIETSIZ      @0x%08X : 0x%08X\n", (uint32_t) addr,
16630 +                          dwc_read_reg32(addr));
16631 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdma;
16632 +               DWC_PRINTF("DIEPDMA      @0x%08X : 0x%08X\n", (uint32_t) addr,
16633 +                          dwc_read_reg32(addr));
16634 +               addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts;
16635 +               DWC_PRINTF("DTXFSTS      @0x%08X : 0x%08X\n", (uint32_t) addr,
16636 +                          dwc_read_reg32(addr));
16637 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdmab;
16638 +               DWC_PRINTF("DIEPDMAB     @0x%08X : 0x%08X\n", (uint32_t) addr,
16639 +                          0 /*dwc_read_reg32(addr) */ );
16640 +       }
16641 +
16642 +       for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
16643 +               DWC_PRINTF("Device OUT EP %d Registers\n", i);
16644 +               addr = &core_if->dev_if->out_ep_regs[i]->doepctl;
16645 +               DWC_PRINTF("DOEPCTL      @0x%08X : 0x%08X\n", (uint32_t) addr,
16646 +                          dwc_read_reg32(addr));
16647 +               addr = &core_if->dev_if->out_ep_regs[i]->doepfn;
16648 +               DWC_PRINTF("DOEPFN       @0x%08X : 0x%08X\n", (uint32_t) addr,
16649 +                          dwc_read_reg32(addr));
16650 +               addr = &core_if->dev_if->out_ep_regs[i]->doepint;
16651 +               DWC_PRINTF("DOEPINT      @0x%08X : 0x%08X\n", (uint32_t) addr,
16652 +                          dwc_read_reg32(addr));
16653 +               addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz;
16654 +               DWC_PRINTF("DOETSIZ      @0x%08X : 0x%08X\n", (uint32_t) addr,
16655 +                          dwc_read_reg32(addr));
16656 +               addr = &core_if->dev_if->out_ep_regs[i]->doepdma;
16657 +               DWC_PRINTF("DOEPDMA      @0x%08X : 0x%08X\n", (uint32_t) addr,
16658 +                          dwc_read_reg32(addr));
16659 +               if (core_if->dma_enable) {      /* Don't access this register in SLAVE mode */
16660 +                       addr = &core_if->dev_if->out_ep_regs[i]->doepdmab;
16661 +                       DWC_PRINTF("DOEPDMAB     @0x%08X : 0x%08X\n",
16662 +                                  (uint32_t) addr, dwc_read_reg32(addr));
16663 +               }
16664 +
16665 +       }
16666 +}
16667 +
16668 +/**
16669 + * This functions reads the SPRAM and prints its content
16670 + *
16671 + * @param core_if Programming view of DWC_otg controller.
16672 + */
16673 +void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if)
16674 +{
16675 +       volatile uint8_t *addr, *start_addr, *end_addr;
16676 +
16677 +       DWC_PRINTF("SPRAM Data:\n");
16678 +       start_addr = (void *)core_if->core_global_regs;
16679 +       DWC_PRINTF("Base Address: 0x%8X\n", (uint32_t) start_addr);
16680 +       start_addr += 0x00028000;
16681 +       end_addr = (void *)core_if->core_global_regs;
16682 +       end_addr += 0x000280e0;
16683 +
16684 +       for (addr = start_addr; addr < end_addr; addr += 16) {
16685 +               DWC_PRINTF
16686 +                   ("0x%8X:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",
16687 +                    (uint32_t) addr, addr[0], addr[1], addr[2], addr[3],
16688 +                    addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],
16689 +                    addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]
16690 +                   );
16691 +       }
16692 +
16693 +       return;
16694 +}
16695 +
16696 +/**
16697 + * This function reads the host registers and prints them
16698 + *
16699 + * @param core_if Programming view of DWC_otg controller.
16700 + */
16701 +void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if)
16702 +{
16703 +       int i;
16704 +       volatile uint32_t *addr;
16705 +
16706 +       DWC_PRINTF("Host Global Registers\n");
16707 +       addr = &core_if->host_if->host_global_regs->hcfg;
16708 +       DWC_PRINTF("HCFG                 @0x%08X : 0x%08X\n", (uint32_t) addr,
16709 +                  dwc_read_reg32(addr));
16710 +       addr = &core_if->host_if->host_global_regs->hfir;
16711 +       DWC_PRINTF("HFIR                 @0x%08X : 0x%08X\n", (uint32_t) addr,
16712 +                  dwc_read_reg32(addr));
16713 +       addr = &core_if->host_if->host_global_regs->hfnum;
16714 +       DWC_PRINTF("HFNUM        @0x%08X : 0x%08X\n", (uint32_t) addr,
16715 +                  dwc_read_reg32(addr));
16716 +       addr = &core_if->host_if->host_global_regs->hptxsts;
16717 +       DWC_PRINTF("HPTXSTS      @0x%08X : 0x%08X\n", (uint32_t) addr,
16718 +                  dwc_read_reg32(addr));
16719 +       addr = &core_if->host_if->host_global_regs->haint;
16720 +       DWC_PRINTF("HAINT        @0x%08X : 0x%08X\n", (uint32_t) addr,
16721 +                  dwc_read_reg32(addr));
16722 +       addr = &core_if->host_if->host_global_regs->haintmsk;
16723 +       DWC_PRINTF("HAINTMSK     @0x%08X : 0x%08X\n", (uint32_t) addr,
16724 +                  dwc_read_reg32(addr));
16725 +       if (core_if->dma_desc_enable) {
16726 +               addr = &core_if->host_if->host_global_regs->hflbaddr;
16727 +               DWC_PRINTF("HFLBADDR     @0x%08X : 0x%08X\n",(uint32_t) addr,
16728 +                          dwc_read_reg32(addr));
16729 +       }
16730 +       
16731 +       addr = core_if->host_if->hprt0;
16732 +       DWC_PRINTF("HPRT0        @0x%08X : 0x%08X\n", (uint32_t) addr,
16733 +                  dwc_read_reg32(addr));
16734 +
16735 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
16736 +               DWC_PRINTF("Host Channel %d Specific Registers\n", i);
16737 +               addr = &core_if->host_if->hc_regs[i]->hcchar;
16738 +               DWC_PRINTF("HCCHAR       @0x%08X : 0x%08X\n", (uint32_t) addr,
16739 +                          dwc_read_reg32(addr));
16740 +               addr = &core_if->host_if->hc_regs[i]->hcsplt;
16741 +               DWC_PRINTF("HCSPLT       @0x%08X : 0x%08X\n", (uint32_t) addr,
16742 +                          dwc_read_reg32(addr));
16743 +               addr = &core_if->host_if->hc_regs[i]->hcint;
16744 +               DWC_PRINTF("HCINT        @0x%08X : 0x%08X\n", (uint32_t) addr,
16745 +                          dwc_read_reg32(addr));
16746 +               addr = &core_if->host_if->hc_regs[i]->hcintmsk;
16747 +               DWC_PRINTF("HCINTMSK     @0x%08X : 0x%08X\n", (uint32_t) addr,
16748 +                          dwc_read_reg32(addr));
16749 +               addr = &core_if->host_if->hc_regs[i]->hctsiz;
16750 +               DWC_PRINTF("HCTSIZ       @0x%08X : 0x%08X\n", (uint32_t) addr,
16751 +                          dwc_read_reg32(addr));
16752 +               addr = &core_if->host_if->hc_regs[i]->hcdma;
16753 +               DWC_PRINTF("HCDMA        @0x%08X : 0x%08X\n", (uint32_t) addr,
16754 +                          dwc_read_reg32(addr));
16755 +               if (core_if->dma_desc_enable) {
16756 +                       addr=&core_if->host_if->hc_regs[i]->hcdmab;
16757 +                       DWC_PRINTF("HCDMAB       @0x%08X : 0x%08X\n",(uint32_t) addr, dwc_read_reg32(addr));
16758 +       }
16759 +
16760 +       }
16761 +       return;
16762 +}
16763 +
16764 +/**
16765 + * This function reads the core global registers and prints them
16766 + *
16767 + * @param core_if Programming view of DWC_otg controller.
16768 + */
16769 +void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if)
16770 +{
16771 +       int i;
16772 +       volatile uint32_t *addr;
16773 +
16774 +       DWC_PRINTF("Core Global Registers\n");
16775 +       addr = &core_if->core_global_regs->gotgctl;
16776 +       DWC_PRINTF("GOTGCTL      @0x%08X : 0x%08X\n", (uint32_t) addr,
16777 +                  dwc_read_reg32(addr));
16778 +       addr = &core_if->core_global_regs->gotgint;
16779 +       DWC_PRINTF("GOTGINT      @0x%08X : 0x%08X\n", (uint32_t) addr,
16780 +                  dwc_read_reg32(addr));
16781 +       addr = &core_if->core_global_regs->gahbcfg;
16782 +       DWC_PRINTF("GAHBCFG      @0x%08X : 0x%08X\n", (uint32_t) addr,
16783 +                  dwc_read_reg32(addr));
16784 +       addr = &core_if->core_global_regs->gusbcfg;
16785 +       DWC_PRINTF("GUSBCFG      @0x%08X : 0x%08X\n", (uint32_t) addr,
16786 +                  dwc_read_reg32(addr));
16787 +       addr = &core_if->core_global_regs->grstctl;
16788 +       DWC_PRINTF("GRSTCTL      @0x%08X : 0x%08X\n", (uint32_t) addr,
16789 +                  dwc_read_reg32(addr));
16790 +       addr = &core_if->core_global_regs->gintsts;
16791 +       DWC_PRINTF("GINTSTS      @0x%08X : 0x%08X\n", (uint32_t) addr,
16792 +                  dwc_read_reg32(addr));
16793 +       addr = &core_if->core_global_regs->gintmsk;
16794 +       DWC_PRINTF("GINTMSK      @0x%08X : 0x%08X\n", (uint32_t) addr,
16795 +                  dwc_read_reg32(addr));
16796 +       addr = &core_if->core_global_regs->grxstsr;
16797 +       DWC_PRINTF("GRXSTSR      @0x%08X : 0x%08X\n", (uint32_t) addr,
16798 +                  dwc_read_reg32(addr));
16799 +       addr = &core_if->core_global_regs->grxfsiz;
16800 +       DWC_PRINTF("GRXFSIZ      @0x%08X : 0x%08X\n", (uint32_t) addr,
16801 +                  dwc_read_reg32(addr));
16802 +       addr = &core_if->core_global_regs->gnptxfsiz;
16803 +       DWC_PRINTF("GNPTXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr,
16804 +                  dwc_read_reg32(addr));
16805 +       addr = &core_if->core_global_regs->gnptxsts;
16806 +       DWC_PRINTF("GNPTXSTS     @0x%08X : 0x%08X\n", (uint32_t) addr,
16807 +                  dwc_read_reg32(addr));
16808 +       addr = &core_if->core_global_regs->gi2cctl;
16809 +       DWC_PRINTF("GI2CCTL      @0x%08X : 0x%08X\n", (uint32_t) addr,
16810 +                  dwc_read_reg32(addr));
16811 +       addr = &core_if->core_global_regs->gpvndctl;
16812 +       DWC_PRINTF("GPVNDCTL     @0x%08X : 0x%08X\n", (uint32_t) addr,
16813 +                  dwc_read_reg32(addr));
16814 +       addr = &core_if->core_global_regs->ggpio;
16815 +       DWC_PRINTF("GGPIO        @0x%08X : 0x%08X\n", (uint32_t) addr,
16816 +                  dwc_read_reg32(addr));
16817 +       addr = &core_if->core_global_regs->guid;
16818 +       DWC_PRINTF("GUID                 @0x%08X : 0x%08X\n", (uint32_t) addr,
16819 +                  dwc_read_reg32(addr));
16820 +       addr = &core_if->core_global_regs->gsnpsid;
16821 +       DWC_PRINTF("GSNPSID      @0x%08X : 0x%08X\n", (uint32_t) addr,
16822 +                  dwc_read_reg32(addr));
16823 +       addr = &core_if->core_global_regs->ghwcfg1;
16824 +       DWC_PRINTF("GHWCFG1      @0x%08X : 0x%08X\n", (uint32_t) addr,
16825 +                  dwc_read_reg32(addr));
16826 +       addr = &core_if->core_global_regs->ghwcfg2;
16827 +       DWC_PRINTF("GHWCFG2      @0x%08X : 0x%08X\n", (uint32_t) addr,
16828 +                  dwc_read_reg32(addr));
16829 +       addr = &core_if->core_global_regs->ghwcfg3;
16830 +       DWC_PRINTF("GHWCFG3      @0x%08X : 0x%08X\n", (uint32_t) addr,
16831 +                  dwc_read_reg32(addr));
16832 +       addr = &core_if->core_global_regs->ghwcfg4;
16833 +       DWC_PRINTF("GHWCFG4      @0x%08X : 0x%08X\n", (uint32_t) addr,
16834 +                  dwc_read_reg32(addr));
16835 +       addr = &core_if->core_global_regs->glpmcfg;
16836 +       DWC_PRINTF("GLPMCFG      @0x%08X : 0x%08X\n", (uint32_t) addr,
16837 +                  dwc_read_reg32(addr));
16838 +       addr = &core_if->core_global_regs->hptxfsiz;
16839 +       DWC_PRINTF("HPTXFSIZ     @0x%08X : 0x%08X\n", (uint32_t) addr,
16840 +                  dwc_read_reg32(addr));
16841 +
16842 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
16843 +               addr = &core_if->core_global_regs->dptxfsiz_dieptxf[i];
16844 +               DWC_PRINTF("DPTXFSIZ[%d] @0x%08X : 0x%08X\n", i,
16845 +                          (uint32_t) addr, dwc_read_reg32(addr));
16846 +       }
16847 +       addr = core_if->pcgcctl;
16848 +       DWC_PRINTF("PCGCCTL      @0x%08X : 0x%08X\n", (uint32_t) addr,
16849 +                  dwc_read_reg32(addr));
16850 +}
16851 +
16852 +/**
16853 + * Flush a Tx FIFO.
16854 + *
16855 + * @param core_if Programming view of DWC_otg controller.
16856 + * @param num Tx FIFO to flush.
16857 + */
16858 +void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
16859 +{
16860 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
16861 +       volatile grstctl_t greset = {.d32 = 0 };
16862 +       int count = 0;
16863 +
16864 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num);
16865 +
16866 +       greset.b.txfflsh = 1;
16867 +       greset.b.txfnum = num;
16868 +       dwc_write_reg32(&global_regs->grstctl, greset.d32);
16869 +
16870 +       do {
16871 +               greset.d32 = dwc_read_reg32(&global_regs->grstctl);
16872 +               if (++count > 10000) {
16873 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
16874 +                                __func__, greset.d32,
16875 +                                dwc_read_reg32(&global_regs->gnptxsts));
16876 +                       break;
16877 +               }
16878 +               dwc_udelay(1);
16879 +       } while (greset.b.txfflsh == 1);
16880 +
16881 +       /* Wait for 3 PHY Clocks */
16882 +       dwc_udelay(1);
16883 +}
16884 +
16885 +/**
16886 + * Flush Rx FIFO.
16887 + *
16888 + * @param core_if Programming view of DWC_otg controller.
16889 + */
16890 +void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
16891 +{
16892 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
16893 +       volatile grstctl_t greset = {.d32 = 0 };
16894 +       int count = 0;
16895 +
16896 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__);
16897 +       /*
16898 +        * 
16899 +        */
16900 +       greset.b.rxfflsh = 1;
16901 +       dwc_write_reg32(&global_regs->grstctl, greset.d32);
16902 +
16903 +       do {
16904 +               greset.d32 = dwc_read_reg32(&global_regs->grstctl);
16905 +               if (++count > 10000) {
16906 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__,
16907 +                                greset.d32);
16908 +                       break;
16909 +               }
16910 +               dwc_udelay(1);
16911 +       } while (greset.b.rxfflsh == 1);
16912 +
16913 +       /* Wait for 3 PHY Clocks */
16914 +       dwc_udelay(1);
16915 +}
16916 +
16917 +/**
16918 + * Do core a soft reset of the core.  Be careful with this because it
16919 + * resets all the internal state machines of the core.
16920 + */
16921 +void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
16922 +{
16923 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
16924 +       volatile grstctl_t greset = {.d32 = 0 };
16925 +       int count = 0;
16926 +
16927 +       DWC_DEBUGPL(DBG_CILV, "%s\n", __func__);
16928 +       /* Wait for AHB master IDLE state. */
16929 +       do {
16930 +               dwc_udelay(10);
16931 +               greset.d32 = dwc_read_reg32(&global_regs->grstctl);
16932 +               if (++count > 100000) {
16933 +                       DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
16934 +                                greset.d32);
16935 +                       return;
16936 +               }
16937 +       }
16938 +       while (greset.b.ahbidle == 0);
16939 +
16940 +       /* Core Soft Reset */
16941 +       count = 0;
16942 +       greset.b.csftrst = 1;
16943 +       dwc_write_reg32(&global_regs->grstctl, greset.d32);
16944 +       do {
16945 +               greset.d32 = dwc_read_reg32(&global_regs->grstctl);
16946 +               if (++count > 10000) {
16947 +                       DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n",
16948 +                                __func__, greset.d32);
16949 +                       break;
16950 +               }
16951 +               dwc_udelay(1);
16952 +       }
16953 +       while (greset.b.csftrst == 1);
16954 +
16955 +       /* Wait for 3 PHY Clocks */
16956 +       dwc_mdelay(100);
16957 +}
16958 +
16959 +uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if)
16960 +{
16961 +       return (dwc_otg_mode(_core_if) != DWC_HOST_MODE);
16962 +}
16963 +
16964 +uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if)
16965 +{
16966 +       return (dwc_otg_mode(_core_if) == DWC_HOST_MODE);
16967 +}
16968 +
16969 +/**
16970 + * Register HCD callbacks.     The callbacks are used to start and stop
16971 + * the HCD for interrupt processing.
16972 + *
16973 + * @param core_if Programming view of DWC_otg controller.
16974 + * @param cb the HCD callback structure.
16975 + * @param p pointer to be passed to callback function (usb_hcd*).
16976 + */
16977 +void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if,
16978 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
16979 +{
16980 +       core_if->hcd_cb = cb;
16981 +       cb->p = p;
16982 +}
16983 +
16984 +/**
16985 + * Register PCD callbacks.     The callbacks are used to start and stop
16986 + * the PCD for interrupt processing.
16987 + *
16988 + * @param core_if Programming view of DWC_otg controller.
16989 + * @param cb the PCD callback structure.
16990 + * @param p pointer to be passed to callback function (pcd*).
16991 + */
16992 +void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if,
16993 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
16994 +{
16995 +       core_if->pcd_cb = cb;
16996 +       cb->p = p;
16997 +}
16998 +
16999 +#ifdef DWC_EN_ISOC
17000 +
17001 +/**
17002 + * This function writes isoc data per 1 (micro)frame into tx fifo
17003 + *
17004 + * @param core_if Programming view of DWC_otg controller.
17005 + * @param ep The EP to start the transfer on.
17006 + *
17007 + */
17008 +void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
17009 +{
17010 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
17011 +       dtxfsts_data_t txstatus = {.d32 = 0 };
17012 +       uint32_t len = 0;
17013 +       uint32_t dwords;
17014 +
17015 +       ep->xfer_len = ep->data_per_frame;
17016 +       ep->xfer_count = 0;
17017 +
17018 +       ep_regs = core_if->dev_if->in_ep_regs[ep->num];
17019 +
17020 +       len = ep->xfer_len - ep->xfer_count;
17021 +
17022 +       if (len > ep->maxpacket) {
17023 +               len = ep->maxpacket;
17024 +       }
17025 +
17026 +       dwords = (len + 3) / 4;
17027 +
17028 +       /* While there is space in the queue and space in the FIFO and
17029 +        * More data to tranfer, Write packets to the Tx FIFO */
17030 +       txstatus.d32 =
17031 +           dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts);
17032 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32);
17033 +
17034 +       while (txstatus.b.txfspcavail > dwords &&
17035 +              ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) {
17036 +               /* Write the FIFO */
17037 +               dwc_otg_ep_write_packet(core_if, ep, 0);
17038 +
17039 +               len = ep->xfer_len - ep->xfer_count;
17040 +               if (len > ep->maxpacket) {
17041 +                       len = ep->maxpacket;
17042 +               }
17043 +
17044 +               dwords = (len + 3) / 4;
17045 +               txstatus.d32 =
17046 +                   dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->
17047 +                                  dtxfsts);
17048 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num,
17049 +                           txstatus.d32);
17050 +       }
17051 +}
17052 +
17053 +/**
17054 + * This function initializes a descriptor chain for Isochronous transfer
17055 + *
17056 + * @param core_if Programming view of DWC_otg controller.
17057 + * @param ep The EP to start the transfer on.
17058 + *
17059 + */
17060 +void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
17061 +                                      dwc_ep_t * ep)
17062 +{
17063 +       deptsiz_data_t deptsiz = {.d32 = 0 };
17064 +       depctl_data_t depctl = {.d32 = 0 };
17065 +       dsts_data_t dsts = {.d32 = 0 };
17066 +       volatile uint32_t *addr;
17067 +
17068 +       if (ep->is_in) {
17069 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
17070 +       } else {
17071 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
17072 +       }
17073 +
17074 +       ep->xfer_len = ep->data_per_frame;
17075 +       ep->xfer_count = 0;
17076 +       ep->xfer_buff = ep->cur_pkt_addr;
17077 +       ep->dma_addr = ep->cur_pkt_dma_addr;
17078 +
17079 +       if (ep->is_in) {
17080 +               /* Program the transfer size and packet count
17081 +                *      as follows: xfersize = N * maxpacket +
17082 +                *      short_packet pktcnt = N + (short_packet
17083 +                *      exist ? 1 : 0)  
17084 +                */
17085 +               deptsiz.b.xfersize = ep->xfer_len;
17086 +               deptsiz.b.pktcnt =
17087 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
17088 +               deptsiz.b.mc = deptsiz.b.pktcnt;
17089 +               dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz,
17090 +                               deptsiz.d32);
17091 +
17092 +               /* Write the DMA register */
17093 +               if (core_if->dma_enable) {
17094 +                       dwc_write_reg32(&
17095 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
17096 +                                        diepdma), (uint32_t) ep->dma_addr);
17097 +               }
17098 +       } else {
17099 +               deptsiz.b.pktcnt =
17100 +                   (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;
17101 +               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
17102 +
17103 +               dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]->
17104 +                               doeptsiz, deptsiz.d32);
17105 +
17106 +               if (core_if->dma_enable) {
17107 +                       dwc_write_reg32(&
17108 +                                       (core_if->dev_if->out_ep_regs[ep->num]->
17109 +                                        doepdma), (uint32_t) ep->dma_addr);
17110 +               }
17111 +       }
17112 +
17113 +       /** Enable endpoint, clear nak  */
17114 +
17115 +       depctl.d32 = 0;
17116 +       if (ep->bInterval == 1) {
17117 +               dsts.d32 =
17118 +                   dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
17119 +               ep->next_frame = dsts.b.soffn + ep->bInterval;
17120 +
17121 +               if (ep->next_frame & 0x1) {
17122 +                       depctl.b.setd1pid = 1;
17123 +               } else {
17124 +                       depctl.b.setd0pid = 1;
17125 +               }
17126 +       } else {
17127 +               ep->next_frame += ep->bInterval;
17128 +
17129 +               if (ep->next_frame & 0x1) {
17130 +                       depctl.b.setd1pid = 1;
17131 +               } else {
17132 +                       depctl.b.setd0pid = 1;
17133 +               }
17134 +       }
17135 +       depctl.b.epena = 1;
17136 +       depctl.b.cnak = 1;
17137 +
17138 +       dwc_modify_reg32(addr, 0, depctl.d32);
17139 +       depctl.d32 = dwc_read_reg32(addr);
17140 +
17141 +       if (ep->is_in && core_if->dma_enable == 0) {
17142 +               write_isoc_frame_data(core_if, ep);
17143 +       }
17144 +
17145 +}
17146 +#endif                         /* DWC_EN_ISOC */
17147 +
17148 +static void dwc_otg_set_uninitialized(int32_t * p, int size)
17149 +{
17150 +       int i;
17151 +       for (i = 0; i < size; i++) {
17152 +               p[i] = -1;
17153 +       }
17154 +}
17155 +
17156 +static int dwc_otg_param_initialized(int32_t val)
17157 +{
17158 +       return val != -1;
17159 +}
17160 +
17161 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
17162 +{
17163 +       int i;
17164 +       core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params));
17165 +       if (!core_if->core_params) {
17166 +               return -DWC_E_NO_MEMORY;
17167 +       }
17168 +       dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
17169 +                                 sizeof(*core_if->core_params) /
17170 +                                 sizeof(int32_t));
17171 +       DWC_PRINTF("Setting default values for core params\n");
17172 +       dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
17173 +       dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
17174 +       dwc_otg_set_param_dma_desc_enable(core_if,
17175 +                                         dwc_param_dma_desc_enable_default);
17176 +       dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
17177 +       dwc_otg_set_param_dma_burst_size(core_if,
17178 +                                        dwc_param_dma_burst_size_default);
17179 +       dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
17180 +                                                      dwc_param_host_support_fs_ls_low_power_default);
17181 +       dwc_otg_set_param_enable_dynamic_fifo(core_if,
17182 +                                             dwc_param_enable_dynamic_fifo_default);
17183 +       dwc_otg_set_param_data_fifo_size(core_if,
17184 +                                        dwc_param_data_fifo_size_default);
17185 +       dwc_otg_set_param_dev_rx_fifo_size(core_if,
17186 +                                          dwc_param_dev_rx_fifo_size_default);
17187 +       dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
17188 +                                                 dwc_param_dev_nperio_tx_fifo_size_default);
17189 +       dwc_otg_set_param_host_rx_fifo_size(core_if,
17190 +                                           dwc_param_host_rx_fifo_size_default);
17191 +       dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
17192 +                                                  dwc_param_host_nperio_tx_fifo_size_default);
17193 +       dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
17194 +                                                 dwc_param_host_perio_tx_fifo_size_default);
17195 +       dwc_otg_set_param_max_transfer_size(core_if,
17196 +                                           dwc_param_max_transfer_size_default);
17197 +       dwc_otg_set_param_max_packet_count(core_if,
17198 +                                          dwc_param_max_packet_count_default);
17199 +       dwc_otg_set_param_host_channels(core_if,
17200 +                                       dwc_param_host_channels_default);
17201 +       dwc_otg_set_param_dev_endpoints(core_if,
17202 +                                       dwc_param_dev_endpoints_default);
17203 +       dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
17204 +       dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
17205 +       dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
17206 +                                                   dwc_param_host_ls_low_power_phy_clk_default);
17207 +       dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
17208 +       dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
17209 +                                           dwc_param_phy_ulpi_ext_vbus_default);
17210 +       dwc_otg_set_param_phy_utmi_width(core_if,
17211 +                                        dwc_param_phy_utmi_width_default);
17212 +       dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
17213 +       dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
17214 +       dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
17215 +       dwc_otg_set_param_en_multiple_tx_fifo(core_if,
17216 +                                             dwc_param_en_multiple_tx_fifo_default);
17217 +       for (i = 0; i < 15; i++) {
17218 +               dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
17219 +                                                        dwc_param_dev_perio_tx_fifo_size_default,
17220 +                                                        i);
17221 +       }
17222 +
17223 +       for (i = 0; i < 15; i++) {
17224 +               dwc_otg_set_param_dev_tx_fifo_size(core_if,
17225 +                                                  dwc_param_dev_tx_fifo_size_default,
17226 +                                                  i);
17227 +       }
17228 +       dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
17229 +       dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
17230 +       dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
17231 +       dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
17232 +       dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
17233 +       dwc_otg_set_param_tx_thr_length(core_if,
17234 +                                       dwc_param_tx_thr_length_default);
17235 +       dwc_otg_set_param_rx_thr_length(core_if,
17236 +                                       dwc_param_rx_thr_length_default);
17237 +       dwc_otg_set_param_ahb_thr_ratio(core_if, dwc_param_ahb_thr_ratio_default);
17238 +       DWC_PRINTF("Finished setting default values for core params\n");
17239 +       return 0;
17240 +}
17241 +
17242 +uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if)
17243 +{
17244 +       return core_if->dma_enable;
17245 +}
17246 +
17247 +/* Checks if the parameter is outside of its valid range of values */
17248 +#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
17249 +               (((_param_) < (_low_)) || \
17250 +               ((_param_) > (_high_)))
17251 +
17252 +/* Parameter access functions */
17253 +int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val)
17254 +{
17255 +       int valid;
17256 +       int retval = 0;
17257 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
17258 +               DWC_WARN("Wrong value for otg_cap parameter\n");
17259 +               DWC_WARN("otg_cap parameter must be 0,1 or 2\n");
17260 +               retval = -DWC_E_INVALID;
17261 +               goto out;
17262 +       }
17263 +
17264 +       valid = 1;
17265 +       switch (val) {
17266 +       case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
17267 +               if (core_if->hwcfg2.b.op_mode !=
17268 +                   DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
17269 +                       valid = 0;
17270 +               break;
17271 +       case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
17272 +               if ((core_if->hwcfg2.b.op_mode !=
17273 +                    DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
17274 +                   && (core_if->hwcfg2.b.op_mode !=
17275 +                       DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
17276 +                   && (core_if->hwcfg2.b.op_mode !=
17277 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
17278 +                   && (core_if->hwcfg2.b.op_mode !=
17279 +                     DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
17280 +                       valid = 0;
17281 +               }
17282 +               break;
17283 +       case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
17284 +               /* always valid */
17285 +               break;
17286 +       }
17287 +       if (!valid) {
17288 +               if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
17289 +                       DWC_ERROR
17290 +                           ("%d invalid for otg_cap paremter. Check HW configuration.\n",
17291 +                            val);
17292 +               }
17293 +               val =
17294 +                   (((core_if->hwcfg2.b.op_mode ==
17295 +                      DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
17296 +                     || (core_if->hwcfg2.b.op_mode ==
17297 +                         DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
17298 +                     || (core_if->hwcfg2.b.op_mode ==
17299 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
17300 +                     || (core_if->hwcfg2.b.op_mode ==
17301 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
17302 +                    DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
17303 +                    DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
17304 +               retval = -DWC_E_INVALID;
17305 +       }
17306 +
17307 +       core_if->core_params->otg_cap = val;
17308 +      out:
17309 +       return retval;
17310 +}
17311 +
17312 +int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if)
17313 +{
17314 +       return core_if->core_params->otg_cap;
17315 +}
17316 +
17317 +int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val)
17318 +{
17319 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17320 +               DWC_WARN("Wrong value for opt parameter\n");
17321 +               return -DWC_E_INVALID;
17322 +       }
17323 +       core_if->core_params->opt = val;
17324 +       return 0;
17325 +}
17326 +
17327 +int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if)
17328 +{
17329 +       return core_if->core_params->opt;
17330 +}
17331 +
17332 +int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val)
17333 +{
17334 +       int retval = 0;
17335 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17336 +               DWC_WARN("Wrong value for dma enable\n");
17337 +               return -DWC_E_INVALID;
17338 +       }
17339 +
17340 +       if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
17341 +               if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
17342 +                       DWC_ERROR
17343 +                           ("%d invalid for dma_enable paremter. Check HW configuration.\n",
17344 +                            val);
17345 +               }
17346 +               val = 0;
17347 +               retval = -DWC_E_INVALID;
17348 +       }
17349 +
17350 +       core_if->core_params->dma_enable = val;
17351 +       if (val == 0) {
17352 +               dwc_otg_set_param_dma_desc_enable(core_if, 0);
17353 +       }
17354 +       return retval;
17355 +}
17356 +
17357 +int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if)
17358 +{
17359 +       return core_if->core_params->dma_enable;
17360 +}
17361 +
17362 +int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val)
17363 +{
17364 +       int retval = 0;
17365 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17366 +               DWC_WARN("Wrong value for dma_enable\n");
17367 +               DWC_WARN("dma_desc_enable must be 0 or 1\n");
17368 +               return -DWC_E_INVALID;
17369 +       }
17370 +
17371 +       if ((val == 1)
17372 +           && ((dwc_otg_get_param_dma_enable(core_if) == 0)
17373 +               || (core_if->hwcfg4.b.desc_dma == 0))) {
17374 +               if (dwc_otg_param_initialized
17375 +                   (core_if->core_params->dma_desc_enable)) {
17376 +                       DWC_ERROR
17377 +                           ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n",
17378 +                            val);
17379 +               }
17380 +               val = 0;
17381 +               retval = -DWC_E_INVALID;
17382 +       }
17383 +       core_if->core_params->dma_desc_enable = val;
17384 +       return retval;
17385 +}
17386 +
17387 +int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if)
17388 +{
17389 +       return core_if->core_params->dma_desc_enable;
17390 +}
17391 +
17392 +int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if,
17393 +                                                  int32_t val)
17394 +{
17395 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17396 +               DWC_WARN("Wrong value for host_support_fs_low_power\n");
17397 +               DWC_WARN("host_support_fs_low_power must be 0 or 1\n");
17398 +               return -DWC_E_INVALID;
17399 +       }
17400 +       core_if->core_params->host_support_fs_ls_low_power = val;
17401 +       return 0;
17402 +}
17403 +
17404 +int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
17405 +                                                      core_if)
17406 +{
17407 +       return core_if->core_params->host_support_fs_ls_low_power;
17408 +}
17409 +
17410 +int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
17411 +                                         int32_t val)
17412 +{
17413 +       int retval = 0;
17414 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17415 +               DWC_WARN("Wrong value for enable_dynamic_fifo\n");
17416 +               DWC_WARN("enable_dynamic_fifo must be 0 or 1\n");
17417 +               return -DWC_E_INVALID;
17418 +       }
17419 +
17420 +       if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
17421 +               if (dwc_otg_param_initialized
17422 +                   (core_if->core_params->enable_dynamic_fifo)) {
17423 +                       DWC_ERROR
17424 +                           ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
17425 +                            val);
17426 +               }
17427 +               val = 0;
17428 +               retval = -DWC_E_INVALID;
17429 +       }
17430 +       core_if->core_params->enable_dynamic_fifo = val;
17431 +       return retval;
17432 +}
17433 +
17434 +int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if)
17435 +{
17436 +       return core_if->core_params->enable_dynamic_fifo;
17437 +}
17438 +
17439 +int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
17440 +{
17441 +       int retval = 0;
17442 +       if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
17443 +               DWC_WARN("Wrong value for data_fifo_size\n");
17444 +               DWC_WARN("data_fifo_size must be 32-32768\n");
17445 +               return -DWC_E_INVALID;
17446 +       }
17447 +
17448 +       if (val > core_if->hwcfg3.b.dfifo_depth) {
17449 +               if (dwc_otg_param_initialized
17450 +                   (core_if->core_params->data_fifo_size)) {
17451 +                       DWC_ERROR
17452 +                           ("%d invalid for data_fifo_size parameter. Check HW configuration.\n",
17453 +                            val);
17454 +               }
17455 +               val = core_if->hwcfg3.b.dfifo_depth;
17456 +               retval = -DWC_E_INVALID;
17457 +       }
17458 +
17459 +       core_if->core_params->data_fifo_size = val;
17460 +       return retval;
17461 +}
17462 +
17463 +int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if)
17464 +{
17465 +       return core_if->core_params->data_fifo_size;
17466 +}
17467 +
17468 +int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
17469 +{
17470 +       int retval = 0;
17471 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
17472 +               DWC_WARN("Wrong value for dev_rx_fifo_size\n");
17473 +               DWC_WARN("dev_rx_fifo_size must be 16-32768\n");
17474 +               return -DWC_E_INVALID;
17475 +       }
17476 +
17477 +       if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) {
17478 +               if(dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
17479 +               DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val);
17480 +               }
17481 +               val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
17482 +               retval = -DWC_E_INVALID;
17483 +       }
17484 +
17485 +       core_if->core_params->dev_rx_fifo_size = val;
17486 +       return retval;
17487 +}
17488 +
17489 +int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if)
17490 +{
17491 +       return core_if->core_params->dev_rx_fifo_size;
17492 +}
17493 +
17494 +int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
17495 +                                             int32_t val)
17496 +{
17497 +       int retval = 0;
17498 +
17499 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
17500 +               DWC_WARN("Wrong value for dev_nperio_tx_fifo\n");
17501 +               DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n");
17502 +               return -DWC_E_INVALID;
17503 +       }
17504 +
17505 +       if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
17506 +               if (dwc_otg_param_initialized
17507 +                   (core_if->core_params->dev_nperio_tx_fifo_size)) {
17508 +                       DWC_ERROR
17509 +                           ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
17510 +                            val);
17511 +               }
17512 +               val =
17513 +                   (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >>
17514 +                    16);
17515 +               retval = -DWC_E_INVALID;
17516 +       }
17517 +
17518 +       core_if->core_params->dev_nperio_tx_fifo_size = val;
17519 +       return retval;
17520 +}
17521 +
17522 +int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
17523 +{
17524 +       return core_if->core_params->dev_nperio_tx_fifo_size;
17525 +}
17526 +
17527 +int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
17528 +                                       int32_t val)
17529 +{
17530 +       int retval = 0;
17531 +
17532 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
17533 +               DWC_WARN("Wrong value for host_rx_fifo_size\n");
17534 +               DWC_WARN("host_rx_fifo_size must be 16-32768\n");
17535 +               return -DWC_E_INVALID;
17536 +       }
17537 +
17538 +       if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) {
17539 +               if (dwc_otg_param_initialized
17540 +                   (core_if->core_params->host_rx_fifo_size)) {
17541 +                       DWC_ERROR
17542 +                           ("%d invalid for host_rx_fifo_size. Check HW configuration.\n",
17543 +                            val);
17544 +               }
17545 +               val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
17546 +               retval = -DWC_E_INVALID;
17547 +       }
17548 +
17549 +       core_if->core_params->host_rx_fifo_size = val;
17550 +       return retval;
17551 +
17552 +}
17553 +
17554 +int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if)
17555 +{
17556 +       return core_if->core_params->host_rx_fifo_size;
17557 +}
17558 +
17559 +int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
17560 +                                              int32_t val)
17561 +{
17562 +       int retval = 0;
17563 +
17564 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
17565 +               DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n");
17566 +               DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n");
17567 +               return -DWC_E_INVALID;
17568 +       }
17569 +
17570 +       if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
17571 +               if (dwc_otg_param_initialized
17572 +                   (core_if->core_params->host_nperio_tx_fifo_size)) {
17573 +                       DWC_ERROR
17574 +                           ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
17575 +                            val);
17576 +               }
17577 +               val =
17578 +                   (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >>
17579 +                    16);
17580 +               retval = -DWC_E_INVALID;
17581 +       }
17582 +
17583 +       core_if->core_params->host_nperio_tx_fifo_size = val;
17584 +       return retval;
17585 +}
17586 +
17587 +int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
17588 +{
17589 +       return core_if->core_params->host_nperio_tx_fifo_size;
17590 +}
17591 +
17592 +int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
17593 +                                             int32_t val)
17594 +{
17595 +       int retval = 0;
17596 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
17597 +               DWC_WARN("Wrong value for host_perio_tx_fifo_size\n");
17598 +               DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n");
17599 +               return -DWC_E_INVALID;
17600 +       }
17601 +
17602 +       if (val >
17603 +           ((dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16))) {
17604 +               if (dwc_otg_param_initialized
17605 +                   (core_if->core_params->host_perio_tx_fifo_size)) {
17606 +                       DWC_ERROR
17607 +                           ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
17608 +                            val);
17609 +               }
17610 +               val =
17611 +                   (dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >>
17612 +                    16);
17613 +               retval = -DWC_E_INVALID;
17614 +       }
17615 +
17616 +       core_if->core_params->host_perio_tx_fifo_size = val;
17617 +       return retval;
17618 +}
17619 +
17620 +int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if)
17621 +{
17622 +       return core_if->core_params->host_perio_tx_fifo_size;
17623 +}
17624 +
17625 +int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
17626 +                                       int32_t val)
17627 +{
17628 +       int retval = 0;
17629 +
17630 +       if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
17631 +               DWC_WARN("Wrong value for max_transfer_size\n");
17632 +               DWC_WARN("max_transfer_size must be 2047-524288\n");
17633 +               return -DWC_E_INVALID;
17634 +       }
17635 +
17636 +       if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
17637 +               if (dwc_otg_param_initialized
17638 +                   (core_if->core_params->max_transfer_size)) {
17639 +                       DWC_ERROR
17640 +                           ("%d invalid for max_transfer_size. Check HW configuration.\n",
17641 +                            val);
17642 +               }
17643 +               val =
17644 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
17645 +                    1);
17646 +               retval = -DWC_E_INVALID;
17647 +       }
17648 +
17649 +       core_if->core_params->max_transfer_size = val;
17650 +       return retval;
17651 +}
17652 +
17653 +int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if)
17654 +{
17655 +       return core_if->core_params->max_transfer_size;
17656 +}
17657 +
17658 +int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val)
17659 +{
17660 +       int retval = 0;
17661 +
17662 +       if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
17663 +               DWC_WARN("Wrong value for max_packet_count\n");
17664 +               DWC_WARN("max_packet_count must be 15-511\n");
17665 +               return -DWC_E_INVALID;
17666 +       }
17667 +
17668 +       if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
17669 +               if (dwc_otg_param_initialized
17670 +                   (core_if->core_params->max_packet_count)) {
17671 +                       DWC_ERROR
17672 +                           ("%d invalid for max_packet_count. Check HW configuration.\n",
17673 +                            val);
17674 +               }
17675 +               val =
17676 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
17677 +               retval = -DWC_E_INVALID;
17678 +       }
17679 +
17680 +       core_if->core_params->max_packet_count = val;
17681 +       return retval;
17682 +}
17683 +
17684 +int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if)
17685 +{
17686 +       return core_if->core_params->max_packet_count;
17687 +}
17688 +
17689 +int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val)
17690 +{
17691 +       int retval = 0;
17692 +
17693 +       if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
17694 +               DWC_WARN("Wrong value for host_channels\n");
17695 +               DWC_WARN("host_channels must be 1-16\n");
17696 +               return -DWC_E_INVALID;
17697 +       }
17698 +
17699 +       if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
17700 +               if (dwc_otg_param_initialized
17701 +                   (core_if->core_params->host_channels)) {
17702 +                       DWC_ERROR
17703 +                           ("%d invalid for host_channels. Check HW configurations.\n",
17704 +                            val);
17705 +               }
17706 +               val = (core_if->hwcfg2.b.num_host_chan + 1);
17707 +               retval = -DWC_E_INVALID;
17708 +       }
17709 +
17710 +       core_if->core_params->host_channels = val;
17711 +       return retval;
17712 +}
17713 +
17714 +int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if)
17715 +{
17716 +       return core_if->core_params->host_channels;
17717 +}
17718 +
17719 +int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val)
17720 +{
17721 +       int retval = 0;
17722 +
17723 +       if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
17724 +               DWC_WARN("Wrong value for dev_endpoints\n");
17725 +               DWC_WARN("dev_endpoints must be 1-15\n");
17726 +               return -DWC_E_INVALID;
17727 +       }
17728 +
17729 +       if (val > (core_if->hwcfg2.b.num_dev_ep)) {
17730 +               if (dwc_otg_param_initialized
17731 +                   (core_if->core_params->dev_endpoints)) {
17732 +                       DWC_ERROR
17733 +                           ("%d invalid for dev_endpoints. Check HW configurations.\n",
17734 +                            val);
17735 +               }
17736 +               val = core_if->hwcfg2.b.num_dev_ep;
17737 +               retval = -DWC_E_INVALID;
17738 +       }
17739 +
17740 +       core_if->core_params->dev_endpoints = val;
17741 +       return retval;
17742 +}
17743 +
17744 +int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if)
17745 +{
17746 +       return core_if->core_params->dev_endpoints;
17747 +}
17748 +
17749 +int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val)
17750 +{
17751 +       int retval = 0;
17752 +       int valid = 0;
17753 +
17754 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
17755 +               DWC_WARN("Wrong value for phy_type\n");
17756 +               DWC_WARN("phy_type must be 0,1 or 2\n");
17757 +               return -DWC_E_INVALID;
17758 +       }
17759 +#ifndef NO_FS_PHY_HW_CHECKS
17760 +       if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
17761 +           ((core_if->hwcfg2.b.hs_phy_type == 1) ||
17762 +            (core_if->hwcfg2.b.hs_phy_type == 3))) {
17763 +               valid = 1;
17764 +       } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
17765 +                  ((core_if->hwcfg2.b.hs_phy_type == 2) ||
17766 +                   (core_if->hwcfg2.b.hs_phy_type == 3))) {
17767 +               valid = 1;
17768 +       } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
17769 +                  (core_if->hwcfg2.b.fs_phy_type == 1)) {
17770 +               valid = 1;
17771 +       }
17772 +       if (!valid) {
17773 +               if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
17774 +                       DWC_ERROR
17775 +                           ("%d invalid for phy_type. Check HW configurations.\n",
17776 +                            val);
17777 +               }
17778 +               if (core_if->hwcfg2.b.hs_phy_type) {
17779 +                       if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
17780 +                           (core_if->hwcfg2.b.hs_phy_type == 1)) {
17781 +                               val = DWC_PHY_TYPE_PARAM_UTMI;
17782 +                       } else {
17783 +                               val = DWC_PHY_TYPE_PARAM_ULPI;
17784 +                       }
17785 +               }
17786 +               retval = -DWC_E_INVALID;
17787 +       }
17788 +#endif
17789 +       core_if->core_params->phy_type = val;
17790 +       return retval;
17791 +}
17792 +
17793 +int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if)
17794 +{
17795 +       return core_if->core_params->phy_type;
17796 +}
17797 +
17798 +int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val)
17799 +{
17800 +       int retval = 0;
17801 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17802 +               DWC_WARN("Wrong value for speed parameter\n");
17803 +               DWC_WARN("max_speed parameter must be 0 or 1\n");
17804 +               return -DWC_E_INVALID;
17805 +       }
17806 +       if ((val == 0)
17807 +           && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
17808 +               if (dwc_otg_param_initialized(core_if->core_params->speed)) {
17809 +                       DWC_ERROR
17810 +                           ("%d invalid for speed paremter. Check HW configuration.\n",
17811 +                            val);
17812 +               }
17813 +               val =
17814 +                   (dwc_otg_get_param_phy_type(core_if) ==
17815 +                    DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
17816 +               retval = -DWC_E_INVALID;
17817 +       }
17818 +       core_if->core_params->speed = val;
17819 +       return retval;
17820 +}
17821 +
17822 +int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if)
17823 +{
17824 +       return core_if->core_params->speed;
17825 +}
17826 +
17827 +int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if,
17828 +                                               int32_t val)
17829 +{
17830 +       int retval = 0;
17831 +
17832 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17833 +               DWC_WARN
17834 +                   ("Wrong value for host_ls_low_power_phy_clk parameter\n");
17835 +               DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n");
17836 +               return -DWC_E_INVALID;
17837 +       }
17838 +
17839 +       if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
17840 +           && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
17841 +               if(dwc_otg_param_initialized(core_if->core_params->host_ls_low_power_phy_clk)) {
17842 +                       DWC_ERROR("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
17843 +                    val);
17844 +               }
17845 +               val =
17846 +                   (dwc_otg_get_param_phy_type(core_if) ==
17847 +                    DWC_PHY_TYPE_PARAM_FS) ?
17848 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
17849 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
17850 +               retval = -DWC_E_INVALID;
17851 +       }
17852 +
17853 +       core_if->core_params->host_ls_low_power_phy_clk = val;
17854 +       return retval;
17855 +}
17856 +
17857 +int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if)
17858 +{
17859 +       return core_if->core_params->host_ls_low_power_phy_clk;
17860 +}
17861 +
17862 +int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val)
17863 +{
17864 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17865 +               DWC_WARN("Wrong value for phy_ulpi_ddr\n");
17866 +               DWC_WARN("phy_upli_ddr must be 0 or 1\n");
17867 +               return -DWC_E_INVALID;
17868 +       }
17869 +
17870 +       core_if->core_params->phy_ulpi_ddr = val;
17871 +       return 0;
17872 +}
17873 +
17874 +int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if)
17875 +{
17876 +       return core_if->core_params->phy_ulpi_ddr;
17877 +}
17878 +
17879 +int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
17880 +                                       int32_t val)
17881 +{
17882 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17883 +               DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n");
17884 +               DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n");
17885 +               return -DWC_E_INVALID;
17886 +       }
17887 +
17888 +       core_if->core_params->phy_ulpi_ext_vbus = val;
17889 +       return 0;
17890 +}
17891 +
17892 +int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if)
17893 +{
17894 +       return core_if->core_params->phy_ulpi_ext_vbus;
17895 +}
17896 +
17897 +int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val)
17898 +{
17899 +       if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
17900 +               DWC_WARN("Wrong valaue for phy_utmi_width\n");
17901 +               DWC_WARN("phy_utmi_width must be 8 or 16\n");
17902 +               return -DWC_E_INVALID;
17903 +       }
17904 +
17905 +       core_if->core_params->phy_utmi_width = val;
17906 +       return 0;
17907 +}
17908 +
17909 +int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if)
17910 +{
17911 +       return core_if->core_params->phy_utmi_width;
17912 +}
17913 +
17914 +int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val)
17915 +{
17916 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17917 +               DWC_WARN("Wrong valaue for ulpi_fs_ls\n");
17918 +               DWC_WARN("ulpi_fs_ls must be 0 or 1\n");
17919 +               return -DWC_E_INVALID;
17920 +       }
17921 +
17922 +       core_if->core_params->ulpi_fs_ls = val;
17923 +       return 0;
17924 +}
17925 +
17926 +int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if)
17927 +{
17928 +       return core_if->core_params->ulpi_fs_ls;
17929 +}
17930 +
17931 +int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val)
17932 +{
17933 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17934 +               DWC_WARN("Wrong valaue for ts_dline\n");
17935 +               DWC_WARN("ts_dline must be 0 or 1\n");
17936 +               return -DWC_E_INVALID;
17937 +       }
17938 +
17939 +       core_if->core_params->ts_dline = val;
17940 +       return 0;
17941 +}
17942 +
17943 +int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if)
17944 +{
17945 +       return core_if->core_params->ts_dline;
17946 +}
17947 +
17948 +int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val)
17949 +{
17950 +       int retval = 0;
17951 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
17952 +               DWC_WARN("Wrong valaue for i2c_enable\n");
17953 +               DWC_WARN("i2c_enable must be 0 or 1\n");
17954 +               return -DWC_E_INVALID;
17955 +       }
17956 +#ifndef NO_FS_PHY_HW_CHECK
17957 +       if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
17958 +               if(dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
17959 +                       DWC_ERROR("%d invalid for i2c_enable. Check HW configuration.\n",
17960 +                    val);
17961 +               }
17962 +               val = 0;
17963 +               retval = -DWC_E_INVALID;
17964 +       }
17965 +#endif
17966 +
17967 +       core_if->core_params->i2c_enable = val;
17968 +       return retval;
17969 +}
17970 +
17971 +int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if)
17972 +{
17973 +       return core_if->core_params->i2c_enable;
17974 +}
17975 +
17976 +int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
17977 +                                            int32_t val, int fifo_num)
17978 +{
17979 +       int retval = 0;
17980 +
17981 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
17982 +               DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n");
17983 +               DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n");
17984 +               return -DWC_E_INVALID;
17985 +       }
17986 +
17987 +       if (val > (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]))) {
17988 +               if(dwc_otg_param_initialized(core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
17989 +                       DWC_ERROR("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
17990 +                    val, fifo_num);
17991 +               }
17992 +               val = (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]));
17993 +               retval = -DWC_E_INVALID;
17994 +       }
17995 +
17996 +       core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
17997 +       return retval;
17998 +}
17999 +
18000 +int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
18001 +                                                int fifo_num)
18002 +{
18003 +       return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
18004 +}
18005 +
18006 +int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
18007 +                                         int32_t val)
18008 +{
18009 +       int retval = 0;
18010 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
18011 +               DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n");
18012 +               DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n");
18013 +               return -DWC_E_INVALID;
18014 +       }
18015 +
18016 +       if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
18017 +               if(dwc_otg_param_initialized(core_if->core_params->en_multiple_tx_fifo)) {
18018 +                       DWC_ERROR("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
18019 +                    val);
18020 +               }
18021 +               val = 0;
18022 +               retval = -DWC_E_INVALID;
18023 +       }
18024 +
18025 +       core_if->core_params->en_multiple_tx_fifo = val;
18026 +       return retval;
18027 +}
18028 +
18029 +int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if)
18030 +{
18031 +       return core_if->core_params->en_multiple_tx_fifo;
18032 +}
18033 +
18034 +int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val,
18035 +                                      int fifo_num)
18036 +{
18037 +       int retval = 0;
18038 +
18039 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
18040 +               DWC_WARN("Wrong value for dev_tx_fifo_size\n");
18041 +               DWC_WARN("dev_tx_fifo_size must be 4-768\n");
18042 +               return -DWC_E_INVALID;
18043 +       }
18044 +
18045 +       if (val > (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]))) {
18046 +               if(dwc_otg_param_initialized(core_if->core_params->dev_tx_fifo_size[fifo_num])) {
18047 +                       DWC_ERROR("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
18048 +                    val, fifo_num);
18049 +               }
18050 +               val = (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]));
18051 +               retval = -DWC_E_INVALID;
18052 +       }
18053 +
18054 +       core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
18055 +       return retval;
18056 +}
18057 +
18058 +int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
18059 +                                          int fifo_num)
18060 +{
18061 +       return core_if->core_params->dev_tx_fifo_size[fifo_num];
18062 +}
18063 +
18064 +int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val)
18065 +{
18066 +       int retval = 0;
18067 +
18068 +       if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
18069 +               DWC_WARN("Wrong value for thr_ctl\n");
18070 +               DWC_WARN("thr_ctl must be 0-7\n");
18071 +               return -DWC_E_INVALID;
18072 +       }
18073 +
18074 +       if ((val != 0) &&
18075 +           (!dwc_otg_get_param_dma_enable(core_if) ||
18076 +            !core_if->hwcfg4.b.ded_fifo_en)) {
18077 +               if(dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
18078 +                       DWC_ERROR("%d invalid for parameter thr_ctl. Check HW configuration.\n",
18079 +                    val);
18080 +               }
18081 +               val = 0;
18082 +               retval = -DWC_E_INVALID;
18083 +       }
18084 +
18085 +       core_if->core_params->thr_ctl = val;
18086 +       return retval;
18087 +}
18088 +
18089 +int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if)
18090 +{
18091 +       return core_if->core_params->thr_ctl;
18092 +}
18093 +
18094 +int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val)
18095 +{
18096 +       int retval = 0;
18097 +
18098 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
18099 +               DWC_WARN("Wrong value for lpm_enable\n");
18100 +               DWC_WARN("lpm_enable must be 0 or 1\n");
18101 +               return -DWC_E_INVALID;
18102 +       }
18103 +
18104 +       if (val && !core_if->hwcfg3.b.otg_lpm_en) {
18105 +               if(dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
18106 +                       DWC_ERROR("%d invalid for parameter lpm_enable. Check HW configuration.\n",
18107 +                    val);
18108 +               }
18109 +               val = 0;
18110 +               retval = -DWC_E_INVALID;
18111 +       }
18112 +
18113 +       core_if->core_params->lpm_enable = val;
18114 +       return retval;
18115 +}
18116 +
18117 +int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if)
18118 +{
18119 +       return core_if->core_params->lpm_enable;
18120 +}
18121 +
18122 +int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
18123 +{
18124 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
18125 +               DWC_WARN("Wrong valaue for tx_thr_length\n");
18126 +               DWC_WARN("tx_thr_length must be 8 - 128\n");
18127 +               return -DWC_E_INVALID;
18128 +       }
18129 +
18130 +       core_if->core_params->tx_thr_length = val;
18131 +       return 0;
18132 +}
18133 +
18134 +int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if)
18135 +{
18136 +       return core_if->core_params->tx_thr_length;
18137 +}
18138 +
18139 +int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
18140 +{
18141 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
18142 +               DWC_WARN("Wrong valaue for rx_thr_length\n");
18143 +               DWC_WARN("rx_thr_length must be 8 - 128\n");
18144 +               return -DWC_E_INVALID;
18145 +       }
18146 +
18147 +       core_if->core_params->rx_thr_length = val;
18148 +       return 0;
18149 +}
18150 +
18151 +int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if)
18152 +{
18153 +       return core_if->core_params->rx_thr_length;
18154 +}
18155 +
18156 +int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val)
18157 +{
18158 +       if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
18159 +           DWC_OTG_PARAM_TEST(val, 4, 4) &&
18160 +           DWC_OTG_PARAM_TEST(val, 8, 8) &&
18161 +           DWC_OTG_PARAM_TEST(val, 16, 16) &&
18162 +           DWC_OTG_PARAM_TEST(val, 32, 32) &&
18163 +           DWC_OTG_PARAM_TEST(val, 64, 64) &&
18164 +           DWC_OTG_PARAM_TEST(val, 128, 128) &&
18165 +           DWC_OTG_PARAM_TEST(val, 256, 256)) {
18166 +               DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val);
18167 +               return -DWC_E_INVALID;
18168 +       }
18169 +       core_if->core_params->dma_burst_size = val;
18170 +       return 0;
18171 +}
18172 +
18173 +int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if)
18174 +{
18175 +       return core_if->core_params->dma_burst_size;
18176 +}
18177 +
18178 +int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val)
18179 +{
18180 +       int retval = 0;
18181 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
18182 +               DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val);
18183 +               return -DWC_E_INVALID;
18184 +       }
18185 +       if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
18186 +               if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
18187 +                       DWC_ERROR("%d invalid for parameter pti_enable. Check HW configuration.\n",
18188 +                            val);
18189 +               }
18190 +               retval = -DWC_E_INVALID;
18191 +               val = 0;
18192 +       }
18193 +       core_if->core_params->pti_enable = val;
18194 +       return retval;
18195 +}
18196 +
18197 +int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if)
18198 +{
18199 +       return core_if->core_params->pti_enable;
18200 +}
18201 +
18202 +int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val)
18203 +{
18204 +       int retval = 0;
18205 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
18206 +               DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val);
18207 +               return -DWC_E_INVALID;
18208 +       }
18209 +       if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
18210 +               if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
18211 +                       DWC_ERROR("%d invalid for parameter mpi_enable. Check HW configuration.\n",
18212 +                            val);
18213 +               }
18214 +               retval = -DWC_E_INVALID;
18215 +               val = 0;
18216 +       }
18217 +       core_if->core_params->mpi_enable = val;
18218 +       return retval;
18219 +}
18220 +
18221 +int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if)
18222 +{
18223 +       return core_if->core_params->mpi_enable;
18224 +}
18225 +
18226 +int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,
18227 +                                       int32_t val)
18228 +{
18229 +       int retval = 0;
18230 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
18231 +               DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val);
18232 +               DWC_WARN("ic_usb_cap must be 0 or 1\n");
18233 +               return -DWC_E_INVALID;
18234 +       }
18235 +
18236 +       if (val && (core_if->hwcfg3.b.otg_enable_ic_usb == 0)) {
18237 +               if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
18238 +                       DWC_ERROR("%d invalid for parameter ic_usb_cap. Check HW configuration.\n",
18239 +                            val);
18240 +               }
18241 +               retval = -DWC_E_INVALID;
18242 +               val = 0;
18243 +       }
18244 +       core_if->core_params->ic_usb_cap = val;
18245 +       return retval;
18246 +}
18247 +int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if)
18248 +{
18249 +       return core_if->core_params->ic_usb_cap;
18250 +}
18251 +
18252 +int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val)
18253 +{
18254 +       int retval = 0;
18255 +       int valid = 1;
18256 +
18257 +       if(DWC_OTG_PARAM_TEST(val, 0, 3)) {
18258 +               DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val);
18259 +               DWC_WARN("ahb_thr_ratio must be 0 - 3\n");
18260 +               return -DWC_E_INVALID;
18261 +       }
18262 +
18263 +       if(val && (core_if->snpsid < OTG_CORE_REV_2_81a || !dwc_otg_get_param_thr_ctl(core_if))) {
18264 +               valid = 0;
18265 +       } else if(val && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) < 4)) {
18266 +               valid = 0;
18267 +       }
18268 +       if(valid == 0) {
18269 +               if(dwc_otg_param_initialized(core_if->core_params->ahb_thr_ratio)) {
18270 +                       DWC_ERROR("%d invalid for parameter ahb_thr_ratio. Chack HW configuration.\n", val);
18271 +               }
18272 +               retval = -DWC_E_INVALID;
18273 +               val = 0;
18274 +       }
18275 +
18276 +       core_if->core_params->ahb_thr_ratio = val;
18277 +       return retval;
18278 +}
18279 +int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if)
18280 +{
18281 +       return core_if->core_params->ahb_thr_ratio;
18282 +}
18283 +
18284 +
18285 +uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if)
18286 +{
18287 +       gotgctl_data_t otgctl;
18288 +       otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
18289 +       return otgctl.b.hstnegscs;
18290 +}
18291 +
18292 +uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if)
18293 +{
18294 +       gotgctl_data_t otgctl;
18295 +       otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
18296 +       return otgctl.b.sesreqscs;
18297 +}
18298 +
18299 +void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val)
18300 +{
18301 +       gotgctl_data_t otgctl;
18302 +       otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
18303 +       otgctl.b.hnpreq = val;
18304 +       dwc_write_reg32(&core_if->core_global_regs->gotgctl, otgctl.d32);
18305 +}
18306 +
18307 +uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if)
18308 +{
18309 +       return core_if->snpsid;
18310 +}
18311 +
18312 +uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if)
18313 +{
18314 +       gotgctl_data_t otgctl;
18315 +       otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
18316 +       return otgctl.b.currmod;
18317 +}
18318 +
18319 +uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if)
18320 +{
18321 +       gusbcfg_data_t usbcfg;
18322 +       usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
18323 +       return usbcfg.b.hnpcap;
18324 +}
18325 +
18326 +void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
18327 +{
18328 +       gusbcfg_data_t usbcfg;
18329 +       usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
18330 +       usbcfg.b.hnpcap = val;
18331 +       dwc_write_reg32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
18332 +}
18333 +
18334 +uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if)
18335 +{
18336 +       gusbcfg_data_t usbcfg;
18337 +       usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
18338 +       return usbcfg.b.srpcap;
18339 +}
18340 +
18341 +void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
18342 +{
18343 +       gusbcfg_data_t usbcfg;
18344 +       usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
18345 +       usbcfg.b.srpcap = val;
18346 +       dwc_write_reg32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
18347 +}
18348 +
18349 +uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if)
18350 +{
18351 +       dcfg_data_t dcfg;
18352 +        dcfg.d32 = -1; //GRAYG
18353 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if);
18354 +        if (NULL == core_if)
18355 +                DWC_ERROR("reg request with NULL core_if\n");
18356 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__,
18357 +                    core_if, core_if->dev_if);
18358 +        if (NULL == core_if->dev_if)
18359 +                DWC_ERROR("reg request with NULL dev_if\n");
18360 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->"
18361 +                    "dev_global_regs(%p)\n", __func__,
18362 +                    core_if, core_if->dev_if,
18363 +                    core_if->dev_if->dev_global_regs);
18364 +        if (NULL == core_if->dev_if->dev_global_regs)
18365 +                DWC_ERROR("reg request with NULL dev_global_regs\n");
18366 +        else {
18367 +                DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->"
18368 +                            "dev_global_regs(%p)->dcfg = %p\n", __func__,
18369 +                            core_if, core_if->dev_if,
18370 +                            core_if->dev_if->dev_global_regs,
18371 +                            &core_if->dev_if->dev_global_regs->dcfg);
18372 +               dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg);
18373 +        }
18374 +       return dcfg.b.devspd;
18375 +}
18376 +
18377 +void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val)
18378 +{
18379 +       dcfg_data_t dcfg;
18380 +       dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg);
18381 +       dcfg.b.devspd = val;
18382 +       dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
18383 +}
18384 +
18385 +uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if)
18386 +{
18387 +       hprt0_data_t hprt0;
18388 +       hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
18389 +       return hprt0.b.prtconnsts;
18390 +}
18391 +
18392 +uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if)
18393 +{
18394 +       dsts_data_t dsts;
18395 +       dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
18396 +       return dsts.b.enumspd;
18397 +}
18398 +
18399 +uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if)
18400 +{
18401 +       hprt0_data_t hprt0;
18402 +       hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
18403 +       return hprt0.b.prtpwr;
18404 +
18405 +}
18406 +
18407 +void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val)
18408 +{
18409 +       hprt0_data_t hprt0;
18410 +       hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
18411 +       hprt0.b.prtpwr = val;
18412 +       dwc_write_reg32(core_if->host_if->hprt0, val);
18413 +}
18414 +
18415 +uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if)
18416 +{
18417 +       hprt0_data_t hprt0;
18418 +       hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
18419 +       return hprt0.b.prtsusp;
18420 +
18421 +}
18422 +
18423 +void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val)
18424 +{
18425 +       hprt0_data_t hprt0;
18426 +       hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
18427 +       hprt0.b.prtsusp = val;
18428 +       dwc_write_reg32(core_if->host_if->hprt0, val);
18429 +}
18430 +
18431 +void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val)
18432 +{
18433 +       hprt0_data_t hprt0;
18434 +       hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
18435 +       hprt0.b.prtres = val;
18436 +       dwc_write_reg32(core_if->host_if->hprt0, val);
18437 +}
18438 +
18439 +uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if)
18440 +{
18441 +       dctl_data_t dctl;
18442 +       dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl);
18443 +       return dctl.b.rmtwkupsig;
18444 +}
18445 +
18446 +uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if)
18447 +{
18448 +       glpmcfg_data_t lpmcfg;
18449 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
18450 +
18451 +       DWC_ASSERT(!
18452 +                  ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts),
18453 +                  "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n",
18454 +                  core_if->lx_state, lpmcfg.b.prt_sleep_sts);
18455 +
18456 +       return lpmcfg.b.prt_sleep_sts;
18457 +}
18458 +
18459 +uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if)
18460 +{
18461 +       glpmcfg_data_t lpmcfg;
18462 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
18463 +       return lpmcfg.b.rem_wkup_en;
18464 +}
18465 +
18466 +uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if)
18467 +{
18468 +       glpmcfg_data_t lpmcfg;
18469 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
18470 +       return lpmcfg.b.appl_resp;
18471 +}
18472 +
18473 +void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val)
18474 +{
18475 +       glpmcfg_data_t lpmcfg;
18476 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
18477 +       lpmcfg.b.appl_resp = val;
18478 +       dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
18479 +}
18480 +
18481 +uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if)
18482 +{
18483 +       glpmcfg_data_t lpmcfg;
18484 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
18485 +       return lpmcfg.b.hsic_connect;
18486 +}
18487 +
18488 +void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val)
18489 +{
18490 +       glpmcfg_data_t lpmcfg;
18491 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
18492 +       lpmcfg.b.hsic_connect = val;
18493 +       dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
18494 +}
18495 +
18496 +uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if)
18497 +{
18498 +       glpmcfg_data_t lpmcfg;
18499 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
18500 +       return lpmcfg.b.inv_sel_hsic;
18501 +
18502 +}
18503 +
18504 +void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val)
18505 +{
18506 +       glpmcfg_data_t lpmcfg;
18507 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
18508 +       lpmcfg.b.inv_sel_hsic = val;
18509 +       dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
18510 +}
18511 +
18512 +uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if)
18513 +{
18514 +       return dwc_read_reg32(&core_if->core_global_regs->gotgctl);
18515 +}
18516 +
18517 +void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val)
18518 +{
18519 +       dwc_write_reg32(&core_if->core_global_regs->gotgctl, val);
18520 +}
18521 +
18522 +uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if)
18523 +{
18524 +       return dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
18525 +}
18526 +
18527 +void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val)
18528 +{
18529 +       dwc_write_reg32(&core_if->core_global_regs->gusbcfg, val);
18530 +}
18531 +
18532 +uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if)
18533 +{
18534 +       return dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
18535 +}
18536 +
18537 +void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
18538 +{
18539 +       dwc_write_reg32(&core_if->core_global_regs->grxfsiz, val);
18540 +}
18541 +
18542 +uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if)
18543 +{
18544 +       return dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz);
18545 +}
18546 +
18547 +void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
18548 +{
18549 +       dwc_write_reg32(&core_if->core_global_regs->gnptxfsiz, val);
18550 +}
18551 +
18552 +uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if)
18553 +{
18554 +       return dwc_read_reg32(&core_if->core_global_regs->gpvndctl);
18555 +}
18556 +
18557 +void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val)
18558 +{
18559 +       dwc_write_reg32(&core_if->core_global_regs->gpvndctl, val);
18560 +}
18561 +
18562 +uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if)
18563 +{
18564 +       return dwc_read_reg32(&core_if->core_global_regs->ggpio);
18565 +}
18566 +
18567 +void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val)
18568 +{
18569 +       dwc_write_reg32(&core_if->core_global_regs->ggpio, val);
18570 +}
18571 +
18572 +uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if)
18573 +{
18574 +       return dwc_read_reg32(core_if->host_if->hprt0);
18575 +
18576 +}
18577 +
18578 +void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val)
18579 +{
18580 +       dwc_write_reg32(core_if->host_if->hprt0, val);
18581 +}
18582 +
18583 +uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if)
18584 +{
18585 +       return dwc_read_reg32(&core_if->core_global_regs->guid);
18586 +}
18587 +
18588 +void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val)
18589 +{
18590 +       dwc_write_reg32(&core_if->core_global_regs->guid, val);
18591 +}
18592 +
18593 +uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if)
18594 +{
18595 +       return dwc_read_reg32(&core_if->core_global_regs->hptxfsiz);
18596 +}
18597 --- /dev/null
18598 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h
18599 @@ -0,0 +1,1143 @@
18600 +/* ==========================================================================
18601 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
18602 + * $Revision: #99 $
18603 + * $Date: 2009/04/21 $
18604 + * $Change: 1237466 $
18605 + *
18606 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18607 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18608 + * otherwise expressly agreed to in writing between Synopsys and you.
18609 + * 
18610 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18611 + * any End User Software License Agreement or Agreement for Licensed Product
18612 + * with Synopsys or any supplement thereto. You are permitted to use and
18613 + * redistribute this Software in source and binary forms, with or without
18614 + * modification, provided that redistributions of source code must retain this
18615 + * notice. You may not view, use, disclose, copy or distribute this file or
18616 + * any information contained herein except pursuant to this license grant from
18617 + * Synopsys. If you do not agree with this notice, including the disclaimer
18618 + * below, then you are not authorized to use the Software.
18619 + * 
18620 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18621 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18622 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18623 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18624 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18625 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18626 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18627 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18628 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18629 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18630 + * DAMAGE.
18631 + * ========================================================================== */
18632 +
18633 +#if !defined(__DWC_CIL_H__)
18634 +#define __DWC_CIL_H__
18635 +
18636 +//#define HW2937_WORKAROUND
18637 +#define DBG_HW2937 0x400
18638 +
18639 +#include "dwc_os.h"
18640 +#include "dwc_list.h"
18641 +#include "dwc_otg_dbg.h"
18642 +#include "dwc_otg_regs.h"
18643 +
18644 +#include "dwc_otg_core_if.h"
18645 +
18646 +/**
18647 + * @file
18648 + * This file contains the interface to the Core Interface Layer.
18649 + */
18650 +
18651 +#ifdef DWC_UTE_CFI
18652 +
18653 +#define MAX_DMA_DESCS_PER_EP   256
18654 +
18655 +/**
18656 + * Enumeration for the data buffer mode
18657 + */
18658 +typedef enum _data_buffer_mode {
18659 +       BM_STANDARD = 0,        /* data buffer is in normal mode */
18660 +       BM_SG = 1,              /* data buffer uses the scatter/gather mode */
18661 +       BM_CONCAT = 2,          /* data buffer uses the concatenation mode */
18662 +       BM_CIRCULAR = 3,        /* data buffer uses the circular DMA mode */
18663 +       BM_ALIGN = 4            /* data buffer is in buffer alignment mode */
18664 +} data_buffer_mode_e;
18665 +#endif                         //DWC_UTE_CFI
18666 +
18667 +/** Macros defined for DWC OTG HW Release verison */
18668 +
18669 +#define OTG_CORE_REV_2_60a     0x4F54260A
18670 +#define OTG_CORE_REV_2_71a     0x4F54271A
18671 +#define OTG_CORE_REV_2_72a     0x4F54272A
18672 +#define OTG_CORE_REV_2_80a     0x4F54280A
18673 +#define OTG_CORE_REV_2_81a     0x4F54281A
18674 +#define OTG_CORE_REV_2_90a     0x4F54290A              
18675 +
18676 +/**
18677 + * Information for each ISOC packet.
18678 + */
18679 +typedef struct iso_pkt_info {
18680 +       uint32_t offset;
18681 +       uint32_t length;
18682 +       int32_t status;
18683 +} iso_pkt_info_t;
18684 +
18685 +/**
18686 + * The <code>dwc_ep</code> structure represents the state of a single
18687 + * endpoint when acting in device mode. It contains the data items
18688 + * needed for an endpoint to be activated and transfer packets.
18689 + */
18690 +typedef struct dwc_ep {
18691 +       /** EP number used for register address lookup */
18692 +       uint8_t num;
18693 +       /** EP direction 0 = OUT */
18694 +       unsigned is_in:1;
18695 +       /** EP active. */
18696 +       unsigned active:1;
18697 +
18698 +       /** Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic Tx FIFO 
18699 +               If dedicated Tx FIFOs are enabled for all IN Eps - Tx FIFO # FOR IN EPs*/
18700 +       unsigned tx_fifo_num:4;
18701 +       /** EP type: 0 - Control, 1 - ISOC,      2 - BULK,      3 - INTR */
18702 +       unsigned type:2;
18703 +#define DWC_OTG_EP_TYPE_CONTROL           0
18704 +#define DWC_OTG_EP_TYPE_ISOC      1
18705 +#define DWC_OTG_EP_TYPE_BULK      2
18706 +#define DWC_OTG_EP_TYPE_INTR      3
18707 +
18708 +       /** DATA start PID for INTR and BULK EP */
18709 +       unsigned data_pid_start:1;
18710 +       /** Frame (even/odd) for ISOC EP */
18711 +       unsigned even_odd_frame:1;
18712 +       /** Max Packet bytes */
18713 +       unsigned maxpacket:11;
18714 +
18715 +       /** Max Transfer size */
18716 +       uint32_t maxxfer;
18717 +
18718 +       /** @name Transfer state */
18719 +       /** @{ */
18720 +
18721 +       /**
18722 +        * Pointer to the beginning of the transfer buffer -- do not modify
18723 +        * during transfer.
18724 +        */
18725 +
18726 +       dwc_dma_t dma_addr;
18727 +
18728 +       dwc_dma_t dma_desc_addr;
18729 +       dwc_otg_dev_dma_desc_t *desc_addr;
18730 +
18731 +       uint8_t *start_xfer_buff;
18732 +       /** pointer to the transfer buffer */
18733 +       uint8_t *xfer_buff;
18734 +       /** Number of bytes to transfer */
18735 +       unsigned xfer_len:19;
18736 +       /** Number of bytes transferred. */
18737 +       unsigned xfer_count:19;
18738 +       /** Sent ZLP */
18739 +       unsigned sent_zlp:1;
18740 +       /** Total len for control transfer */
18741 +       unsigned total_len:19;
18742 +
18743 +       /** stall clear flag */
18744 +       unsigned stall_clear_flag:1;
18745 +
18746 +#ifdef DWC_UTE_CFI
18747 +       /* The buffer mode */
18748 +       data_buffer_mode_e buff_mode;
18749 +
18750 +       /* The chain of DMA descriptors.
18751 +        * MAX_DMA_DESCS_PER_EP will be allocated for each active EP.
18752 +        */
18753 +       dwc_otg_dma_desc_t *descs;
18754 +
18755 +       /* The DMA address of the descriptors chain start */
18756 +       dma_addr_t descs_dma_addr;
18757 +       /** This variable stores the length of the last enqueued request */
18758 +       uint32_t cfi_req_len;
18759 +#endif                         //DWC_UTE_CFI
18760 +
18761 +       /** Allocated DMA Desc count */
18762 +       uint32_t desc_cnt;
18763 +
18764 +#ifdef DWC_EN_ISOC
18765 +       /**
18766 +        * Variables specific for ISOC EPs
18767 +        *
18768 +        */
18769 +       /** DMA addresses of ISOC buffers */
18770 +       dwc_dma_t dma_addr0;
18771 +       dwc_dma_t dma_addr1;
18772 +
18773 +       dwc_dma_t iso_dma_desc_addr;
18774 +       dwc_otg_dev_dma_desc_t *iso_desc_addr;
18775 +
18776 +       /** pointer to the transfer buffers */
18777 +       uint8_t *xfer_buff0;
18778 +       uint8_t *xfer_buff1;
18779 +
18780 +       /** number of ISOC Buffer is processing */
18781 +       uint32_t proc_buf_num;
18782 +       /** Interval of ISOC Buffer processing */
18783 +       uint32_t buf_proc_intrvl;
18784 +       /** Data size for regular frame */
18785 +       uint32_t data_per_frame;
18786 +
18787 +       /* todo - pattern data support is to be implemented in the future */
18788 +       /** Data size for pattern frame */
18789 +       uint32_t data_pattern_frame;
18790 +       /** Frame number of pattern data */
18791 +       uint32_t sync_frame;
18792 +
18793 +       /** bInterval */
18794 +       uint32_t bInterval;
18795 +       /** ISO Packet number per frame */
18796 +       uint32_t pkt_per_frm;
18797 +       /** Next frame num for which will be setup DMA Desc */
18798 +       uint32_t next_frame;
18799 +       /** Number of packets per buffer processing */
18800 +       uint32_t pkt_cnt;
18801 +       /** Info for all isoc packets */
18802 +       iso_pkt_info_t *pkt_info;
18803 +       /** current pkt number */
18804 +       uint32_t cur_pkt;
18805 +       /** current pkt number */
18806 +       uint8_t *cur_pkt_addr;
18807 +       /** current pkt number */
18808 +       uint32_t cur_pkt_dma_addr;
18809 +#endif                         /* DWC_EN_ISOC */
18810 +
18811 +/** @} */
18812 +} dwc_ep_t;
18813 +
18814 +/*
18815 + * Reasons for halting a host channel.
18816 + */
18817 +typedef enum dwc_otg_halt_status {
18818 +       DWC_OTG_HC_XFER_NO_HALT_STATUS,
18819 +       DWC_OTG_HC_XFER_COMPLETE,
18820 +       DWC_OTG_HC_XFER_URB_COMPLETE,
18821 +       DWC_OTG_HC_XFER_ACK,
18822 +       DWC_OTG_HC_XFER_NAK,
18823 +       DWC_OTG_HC_XFER_NYET,
18824 +       DWC_OTG_HC_XFER_STALL,
18825 +       DWC_OTG_HC_XFER_XACT_ERR,
18826 +       DWC_OTG_HC_XFER_FRAME_OVERRUN,
18827 +       DWC_OTG_HC_XFER_BABBLE_ERR,
18828 +       DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,
18829 +       DWC_OTG_HC_XFER_AHB_ERR,
18830 +       DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
18831 +       DWC_OTG_HC_XFER_URB_DEQUEUE
18832 +#ifdef HW2937_WORKAROUND
18833 +       , DWC_OTG_HC_XFER_PAUSE_IN
18834 +#endif
18835 +} dwc_otg_halt_status_e;
18836 +
18837 +/**
18838 + * Host channel descriptor. This structure represents the state of a single
18839 + * host channel when acting in host mode. It contains the data items needed to
18840 + * transfer packets to an endpoint via a host channel.
18841 + */
18842 +typedef struct dwc_hc {
18843 +       /** Host channel number used for register address lookup */
18844 +       uint8_t hc_num;
18845 +
18846 +       /** Device to access */
18847 +       unsigned dev_addr:7;
18848 +
18849 +       /** EP to access */
18850 +       unsigned ep_num:4;
18851 +
18852 +       /** EP direction. 0: OUT, 1: IN */
18853 +       unsigned ep_is_in:1;
18854 +
18855 +       /**
18856 +        * EP speed.
18857 +        * One of the following values:
18858 +        *      - DWC_OTG_EP_SPEED_LOW
18859 +        *      - DWC_OTG_EP_SPEED_FULL
18860 +        *      - DWC_OTG_EP_SPEED_HIGH
18861 +        */
18862 +       unsigned speed:2;
18863 +#define DWC_OTG_EP_SPEED_LOW   0
18864 +#define DWC_OTG_EP_SPEED_FULL  1
18865 +#define DWC_OTG_EP_SPEED_HIGH  2
18866 +
18867 +       /**
18868 +        * Endpoint type.
18869 +        * One of the following values:
18870 +        *      - DWC_OTG_EP_TYPE_CONTROL: 0
18871 +        *      - DWC_OTG_EP_TYPE_ISOC: 1
18872 +        *      - DWC_OTG_EP_TYPE_BULK: 2
18873 +        *      - DWC_OTG_EP_TYPE_INTR: 3
18874 +        */
18875 +       unsigned ep_type:2;
18876 +
18877 +       /** Max packet size in bytes */
18878 +       unsigned max_packet:11;
18879 +
18880 +       /**
18881 +        * PID for initial transaction.
18882 +        * 0: DATA0,<br>
18883 +        * 1: DATA2,<br>
18884 +        * 2: DATA1,<br>
18885 +        * 3: MDATA (non-Control EP),
18886 +        *        SETUP (Control EP)
18887 +        */
18888 +       unsigned data_pid_start:2;
18889 +#define DWC_OTG_HC_PID_DATA0 0
18890 +#define DWC_OTG_HC_PID_DATA2 1
18891 +#define DWC_OTG_HC_PID_DATA1 2
18892 +#define DWC_OTG_HC_PID_MDATA 3
18893 +#define DWC_OTG_HC_PID_SETUP 3
18894 +
18895 +       /** Number of periodic transactions per (micro)frame */
18896 +       unsigned multi_count:2;
18897 +
18898 +       /** @name Transfer State */
18899 +       /** @{ */
18900 +
18901 +       /** Pointer to the current transfer buffer position. */
18902 +       uint8_t *xfer_buff;
18903 +       /**      
18904 +        * In Buffer DMA mode this buffer will be used
18905 +        * if xfer_buff is not DWORD aligned.
18906 +        */
18907 +       dwc_dma_t align_buff;
18908 +       /** Total number of bytes to transfer. */
18909 +       uint32_t xfer_len;
18910 +       /** Number of bytes transferred so far. */
18911 +       uint32_t xfer_count;
18912 +       /** Packet count at start of transfer.*/
18913 +       uint16_t start_pkt_count;
18914 +
18915 +       /**
18916 +        * Flag to indicate whether the transfer has been started. Set to 1 if
18917 +        * it has been started, 0 otherwise.
18918 +        */
18919 +       uint8_t xfer_started;
18920 +
18921 +       /**
18922 +        * Set to 1 to indicate that a PING request should be issued on this
18923 +        * channel. If 0, process normally.
18924 +        */
18925 +       uint8_t do_ping;
18926 +
18927 +       /**
18928 +        * Set to 1 to indicate that the error count for this transaction is
18929 +        * non-zero. Set to 0 if the error count is 0.
18930 +        */
18931 +       uint8_t error_state;
18932 +
18933 +       /**
18934 +        * Set to 1 to indicate that this channel should be halted the next
18935 +        * time a request is queued for the channel. This is necessary in
18936 +        * slave mode if no request queue space is available when an attempt
18937 +        * is made to halt the channel.
18938 +        */
18939 +       uint8_t halt_on_queue;
18940 +
18941 +       /**
18942 +        * Set to 1 if the host channel has been halted, but the core is not
18943 +        * finished flushing queued requests. Otherwise 0.
18944 +        */
18945 +       uint8_t halt_pending;
18946 +
18947 +       /**
18948 +        * Reason for halting the host channel.
18949 +        */
18950 +       dwc_otg_halt_status_e halt_status;
18951 +
18952 +       /*
18953 +        * Split settings for the host channel
18954 +        */
18955 +       uint8_t do_split;                  /**< Enable split for the channel */
18956 +       uint8_t complete_split;    /**< Enable complete split */
18957 +       uint8_t hub_addr;                  /**< Address of high speed hub */
18958 +
18959 +       uint8_t port_addr;                 /**< Port of the low/full speed device */
18960 +       /** Split transaction position 
18961 +        * One of the following values:
18962 +        *        - DWC_HCSPLIT_XACTPOS_MID 
18963 +        *        - DWC_HCSPLIT_XACTPOS_BEGIN
18964 +        *        - DWC_HCSPLIT_XACTPOS_END
18965 +        *        - DWC_HCSPLIT_XACTPOS_ALL */
18966 +       uint8_t xact_pos;
18967 +
18968 +       /** Set when the host channel does a short read. */
18969 +       uint8_t short_read;
18970 +
18971 +       /**
18972 +        * Number of requests issued for this channel since it was assigned to
18973 +        * the current transfer (not counting PINGs).
18974 +        */
18975 +       uint8_t requests;
18976 +
18977 +       /**
18978 +        * Queue Head for the transfer being processed by this channel.
18979 +        */
18980 +       struct dwc_otg_qh *qh;
18981 +
18982 +       /** @} */
18983 +
18984 +       /** Entry in list of host channels. */
18985 +        DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry;
18986 +       
18987 +       /** @name Descriptor DMA support */
18988 +       /** @{ */
18989 +                       
18990 +       /** Number of Transfer Descriptors */
18991 +       uint16_t ntd;
18992 +       
18993 +       /** Descriptor List DMA address */
18994 +       dwc_dma_t desc_list_addr;
18995 +       
18996 +       /** Scheduling micro-frame bitmap. */
18997 +       uint8_t schinfo;
18998 +       
18999 +       /** @} */
19000 +} dwc_hc_t;
19001 +
19002 +/**
19003 + * The following parameters may be specified when starting the module. These
19004 + * parameters define how the DWC_otg controller should be configured.
19005 + */
19006 +typedef struct dwc_otg_core_params {
19007 +       int32_t opt;
19008 +
19009 +       /**
19010 +        * Specifies the OTG capabilities. The driver will automatically
19011 +        * detect the value for this parameter if none is specified.
19012 +        * 0 - HNP and SRP capable (default)
19013 +        * 1 - SRP Only capable
19014 +        * 2 - No HNP/SRP capable
19015 +        */
19016 +       int32_t otg_cap;
19017 +
19018 +       /**
19019 +        * Specifies whether to use slave or DMA mode for accessing the data
19020 +        * FIFOs. The driver will automatically detect the value for this
19021 +        * parameter if none is specified.
19022 +        * 0 - Slave
19023 +        * 1 - DMA (default, if available)
19024 +        */
19025 +       int32_t dma_enable;
19026 +
19027 +       /**
19028 +        * When DMA mode is enabled specifies whether to use address DMA or DMA Descritor mode for accessing the data
19029 +        * FIFOs in device mode. The driver will automatically detect the value for this
19030 +        * parameter if none is specified.
19031 +        * 0 - address DMA
19032 +        * 1 - DMA Descriptor(default, if available)
19033 +        */
19034 +       int32_t dma_desc_enable;
19035 +       /** The DMA Burst size (applicable only for External DMA
19036 +        * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
19037 +        */
19038 +       int32_t dma_burst_size; /* Translate this to GAHBCFG values */
19039 +
19040 +       /**
19041 +        * Specifies the maximum speed of operation in host and device mode.
19042 +        * The actual speed depends on the speed of the attached device and
19043 +        * the value of phy_type. The actual speed depends on the speed of the
19044 +        * attached device.
19045 +        * 0 - High Speed (default)
19046 +        * 1 - Full Speed
19047 +        */
19048 +       int32_t speed;
19049 +       /** Specifies whether low power mode is supported when attached 
19050 +        *      to a Full Speed or Low Speed device in host mode.
19051 +        * 0 - Don't support low power mode (default)
19052 +        * 1 - Support low power mode
19053 +        */
19054 +       int32_t host_support_fs_ls_low_power;
19055 +
19056 +       /** Specifies the PHY clock rate in low power mode when connected to a
19057 +        * Low Speed device in host mode. This parameter is applicable only if
19058 +        * HOST_SUPPORT_FS_LS_LOW_POWER is enabled.      If PHY_TYPE is set to FS
19059 +        * then defaults to 6 MHZ otherwise 48 MHZ.
19060 +        *
19061 +        * 0 - 48 MHz
19062 +        * 1 - 6 MHz
19063 +        */
19064 +       int32_t host_ls_low_power_phy_clk;
19065 +
19066 +       /**
19067 +        * 0 - Use cC FIFO size parameters
19068 +        * 1 - Allow dynamic FIFO sizing (default)
19069 +        */
19070 +       int32_t enable_dynamic_fifo;
19071 +
19072 +       /** Total number of 4-byte words in the data FIFO memory. This 
19073 +        * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic 
19074 +        * Tx FIFOs.
19075 +        * 32 to 32768 (default 8192)
19076 +        * Note: The total FIFO memory depth in the FPGA configuration is 8192.
19077 +        */
19078 +       int32_t data_fifo_size;
19079 +
19080 +       /** Number of 4-byte words in the Rx FIFO in device mode when dynamic 
19081 +        * FIFO sizing is enabled.
19082 +        * 16 to 32768 (default 1064)
19083 +        */
19084 +       int32_t dev_rx_fifo_size;
19085 +
19086 +       /** Number of 4-byte words in the non-periodic Tx FIFO in device mode 
19087 +        * when dynamic FIFO sizing is enabled.
19088 +        * 16 to 32768 (default 1024)
19089 +        */
19090 +       int32_t dev_nperio_tx_fifo_size;
19091 +
19092 +       /** Number of 4-byte words in each of the periodic Tx FIFOs in device
19093 +        * mode when dynamic FIFO sizing is enabled.
19094 +        * 4 to 768 (default 256)
19095 +        */
19096 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
19097 +
19098 +       /** Number of 4-byte words in the Rx FIFO in host mode when dynamic 
19099 +        * FIFO sizing is enabled.
19100 +        * 16 to 32768 (default 1024)  
19101 +        */
19102 +       int32_t host_rx_fifo_size;
19103 +
19104 +               /** Number of 4-byte words in the non-periodic Tx FIFO in host mode 
19105 +        * when Dynamic FIFO sizing is enabled in the core. 
19106 +        * 16 to 32768 (default 1024)
19107 +        */
19108 +       int32_t host_nperio_tx_fifo_size;
19109 +
19110 +       /** Number of 4-byte words in the host periodic Tx FIFO when dynamic 
19111 +        * FIFO sizing is enabled. 
19112 +        * 16 to 32768 (default 1024)
19113 +        */
19114 +       int32_t host_perio_tx_fifo_size;
19115 +
19116 +       /** The maximum transfer size supported in bytes.  
19117 +        * 2047 to 65,535  (default 65,535)
19118 +        */
19119 +       int32_t max_transfer_size;
19120 +
19121 +       /** The maximum number of packets in a transfer.  
19122 +        * 15 to 511  (default 511)
19123 +        */
19124 +       int32_t max_packet_count;
19125 +
19126 +       /** The number of host channel registers to use.  
19127 +        * 1 to 16 (default 12) 
19128 +        * Note: The FPGA configuration supports a maximum of 12 host channels.
19129 +        */
19130 +       int32_t host_channels;
19131 +
19132 +       /** The number of endpoints in addition to EP0 available for device 
19133 +        * mode operations. 
19134 +        * 1 to 15 (default 6 IN and OUT) 
19135 +        * Note: The FPGA configuration supports a maximum of 6 IN and OUT 
19136 +        * endpoints in addition to EP0.
19137 +        */
19138 +       int32_t dev_endpoints;
19139 +
19140 +               /** 
19141 +                * Specifies the type of PHY interface to use. By default, the driver
19142 +                * will automatically detect the phy_type.
19143 +                * 
19144 +                * 0 - Full Speed PHY
19145 +                * 1 - UTMI+ (default)
19146 +                * 2 - ULPI
19147 +                */
19148 +       int32_t phy_type;
19149 +
19150 +       /**
19151 +        * Specifies the UTMI+ Data Width.      This parameter is
19152 +        * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
19153 +        * PHY_TYPE, this parameter indicates the data width between
19154 +        * the MAC and the ULPI Wrapper.) Also, this parameter is
19155 +        * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
19156 +        * to "8 and 16 bits", meaning that the core has been
19157 +        * configured to work at either data path width. 
19158 +        *
19159 +        * 8 or 16 bits (default 16)
19160 +        */
19161 +       int32_t phy_utmi_width;
19162 +
19163 +       /**
19164 +        * Specifies whether the ULPI operates at double or single
19165 +        * data rate. This parameter is only applicable if PHY_TYPE is
19166 +        * ULPI.
19167 +        * 
19168 +        * 0 - single data rate ULPI interface with 8 bit wide data
19169 +        * bus (default)
19170 +        * 1 - double data rate ULPI interface with 4 bit wide data
19171 +        * bus
19172 +        */
19173 +       int32_t phy_ulpi_ddr;
19174 +
19175 +       /**
19176 +        * Specifies whether to use the internal or external supply to 
19177 +        * drive the vbus with a ULPI phy.
19178 +        */
19179 +       int32_t phy_ulpi_ext_vbus;
19180 +
19181 +       /**
19182 +        * Specifies whether to use the I2Cinterface for full speed PHY. This
19183 +        * parameter is only applicable if PHY_TYPE is FS.
19184 +        * 0 - No (default)
19185 +        * 1 - Yes
19186 +        */
19187 +       int32_t i2c_enable;
19188 +
19189 +       int32_t ulpi_fs_ls;
19190 +
19191 +       int32_t ts_dline;
19192 +
19193 +       /**
19194 +        * Specifies whether dedicated transmit FIFOs are 
19195 +        * enabled for non periodic IN endpoints in device mode
19196 +        * 0 - No 
19197 +        * 1 - Yes
19198 +        */
19199 +       int32_t en_multiple_tx_fifo;
19200 +
19201 +       /** Number of 4-byte words in each of the Tx FIFOs in device
19202 +        * mode when dynamic FIFO sizing is enabled.
19203 +        * 4 to 768 (default 256)
19204 +        */
19205 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
19206 +
19207 +       /** Thresholding enable flag- 
19208 +        * bit 0 - enable non-ISO Tx thresholding
19209 +        * bit 1 - enable ISO Tx thresholding
19210 +        * bit 2 - enable Rx thresholding
19211 +        */
19212 +       uint32_t thr_ctl;
19213 +
19214 +       /** Thresholding length for Tx 
19215 +        *      FIFOs in 32 bit DWORDs
19216 +        */
19217 +       uint32_t tx_thr_length;
19218 +
19219 +       /** Thresholding length for Rx 
19220 +        *      FIFOs in 32 bit DWORDs
19221 +        */
19222 +       uint32_t rx_thr_length;
19223 +
19224 +       /**
19225 +        * Specifies whether LPM (Link Power Management) support is enabled
19226 +        */
19227 +       int32_t lpm_enable;
19228 +
19229 +       /** Per Transfer Interrupt 
19230 +        *      mode enable flag
19231 +        * 1 - Enabled
19232 +        * 0 - Disabled
19233 +        */
19234 +       int32_t pti_enable;
19235 +
19236 +       /** Multi Processor Interrupt 
19237 +        *      mode enable flag
19238 +        * 1 - Enabled
19239 +        * 0 - Disabled
19240 +        */
19241 +       int32_t mpi_enable;
19242 +
19243 +       /** IS_USB Capability
19244 +        * 1 - Enabled
19245 +        * 0 - Disabled
19246 +        */
19247 +       int32_t ic_usb_cap;
19248 +
19249 +       /** AHB Threshold Ratio
19250 +        * 2'b00 AHB Threshold =        MAC Threshold
19251 +        * 2'b01 AHB Threshold = 1/2    MAC Threshold
19252 +        * 2'b10 AHB Threshold = 1/4    MAC Threshold
19253 +        * 2'b11 AHB Threshold = 1/8    MAC Threshold
19254 +        */
19255 +       int32_t ahb_thr_ratio;
19256 +
19257 +} dwc_otg_core_params_t;
19258 +
19259 +#ifdef DEBUG
19260 +struct dwc_otg_core_if;
19261 +typedef struct hc_xfer_info {
19262 +       struct dwc_otg_core_if *core_if;
19263 +       dwc_hc_t *hc;
19264 +} hc_xfer_info_t;
19265 +#endif
19266 +/*
19267 + * Device States
19268 + */
19269 +typedef enum dwc_otg_lx_state {
19270 +       /** On state */
19271 +       DWC_OTG_L0,
19272 +       /** LPM sleep state*/
19273 +       DWC_OTG_L1,
19274 +       /** USB suspend state*/
19275 +       DWC_OTG_L2,
19276 +       /** Off state*/
19277 +       DWC_OTG_L3
19278 +} dwc_otg_lx_state_e;
19279 +
19280 +/**
19281 + * The <code>dwc_otg_core_if</code> structure contains information needed to manage
19282 + * the DWC_otg controller acting in either host or device mode. It
19283 + * represents the programming view of the controller as a whole.
19284 + */
19285 +struct dwc_otg_core_if {
19286 +       /** Parameters that define how the core should be configured.*/
19287 +       dwc_otg_core_params_t *core_params;
19288 +
19289 +       /** Core Global registers starting at offset 000h. */
19290 +       dwc_otg_core_global_regs_t *core_global_regs;
19291 +
19292 +       /** Device-specific information */
19293 +       dwc_otg_dev_if_t *dev_if;
19294 +       /** Host-specific information */
19295 +       dwc_otg_host_if_t *host_if;
19296 +
19297 +       /** Value from SNPSID register */
19298 +       uint32_t snpsid;
19299 +
19300 +       /*
19301 +        * Set to 1 if the core PHY interface bits in USBCFG have been
19302 +        * initialized.
19303 +        */
19304 +       uint8_t phy_init_done;
19305 +
19306 +       /*
19307 +        * SRP Success flag, set by srp success interrupt in FS I2C mode
19308 +        */
19309 +       uint8_t srp_success;
19310 +       uint8_t srp_timer_started;
19311 +
19312 +       /* Common configuration information */
19313 +       /** Power and Clock Gating Control Register */
19314 +       volatile uint32_t *pcgcctl;
19315 +#define DWC_OTG_PCGCCTL_OFFSET 0xE00
19316 +
19317 +       /** Push/pop addresses for endpoints or host channels.*/
19318 +       uint32_t *data_fifo[MAX_EPS_CHANNELS];
19319 +#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
19320 +#define DWC_OTG_DATA_FIFO_SIZE 0x1000
19321 +
19322 +       /** Total RAM for FIFOs (Bytes) */
19323 +       uint16_t total_fifo_size;
19324 +       /** Size of Rx FIFO (Bytes) */
19325 +       uint16_t rx_fifo_size;
19326 +       /** Size of Non-periodic Tx FIFO (Bytes) */
19327 +       uint16_t nperio_tx_fifo_size;
19328 +
19329 +       /** 1 if DMA is enabled, 0 otherwise. */
19330 +       uint8_t dma_enable;
19331 +
19332 +       /** 1 if DMA descriptor is enabled, 0 otherwise. */
19333 +       uint8_t dma_desc_enable;
19334 +
19335 +       /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
19336 +       uint8_t pti_enh_enable;
19337 +
19338 +       /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
19339 +       uint8_t multiproc_int_enable;
19340 +
19341 +       /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
19342 +       uint8_t en_multiple_tx_fifo;
19343 +
19344 +       /** Set to 1 if multiple packets of a high-bandwidth transfer is in
19345 +        * process of being queued */
19346 +       uint8_t queuing_high_bandwidth;
19347 +
19348 +       /** Hardware Configuration -- stored here for convenience.*/
19349 +       hwcfg1_data_t hwcfg1;
19350 +       hwcfg2_data_t hwcfg2;
19351 +       hwcfg3_data_t hwcfg3;
19352 +       hwcfg4_data_t hwcfg4;
19353 +
19354 +       /** Host and Device Configuration -- stored here for convenience.*/
19355 +       hcfg_data_t hcfg;
19356 +       dcfg_data_t dcfg;
19357 +
19358 +       /** The operational State, during transations
19359 +        * (a_host>>a_peripherial and b_device=>b_host) this may not
19360 +        * match the core but allows the software to determine
19361 +        * transitions.
19362 +        */
19363 +       uint8_t op_state;
19364 +
19365 +       /**
19366 +        * Set to 1 if the HCD needs to be restarted on a session request
19367 +        * interrupt. This is required if no connector ID status change has
19368 +        * occurred since the HCD was last disconnected.
19369 +        */
19370 +       uint8_t restart_hcd_on_session_req;
19371 +
19372 +       /** HCD callbacks */
19373 +       /** A-Device is a_host */
19374 +#define A_HOST         (1)
19375 +       /** A-Device is a_suspend */
19376 +#define A_SUSPEND      (2)
19377 +       /** A-Device is a_peripherial */
19378 +#define A_PERIPHERAL   (3)
19379 +       /** B-Device is operating as a Peripheral. */
19380 +#define B_PERIPHERAL   (4)
19381 +       /** B-Device is operating as a Host. */
19382 +#define B_HOST         (5)
19383 +
19384 +       /** HCD callbacks */
19385 +       struct dwc_otg_cil_callbacks *hcd_cb;
19386 +       /** PCD callbacks */
19387 +       struct dwc_otg_cil_callbacks *pcd_cb;
19388 +
19389 +       /** Device mode Periodic Tx FIFO Mask */
19390 +       uint32_t p_tx_msk;
19391 +       /** Device mode Periodic Tx FIFO Mask */
19392 +       uint32_t tx_msk;
19393 +
19394 +       /** Workqueue object used for handling several interrupts */
19395 +       dwc_workq_t *wq_otg;
19396 +
19397 +       /** Timer object used for handling "Wakeup Detected" Interrupt */
19398 +       dwc_timer_t *wkp_timer;
19399 +
19400 +#ifdef DEBUG
19401 +       uint32_t start_hcchar_val[MAX_EPS_CHANNELS];
19402 +
19403 +       hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS];
19404 +       dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS];
19405 +
19406 +       uint32_t hfnum_7_samples;
19407 +       uint64_t hfnum_7_frrem_accum;
19408 +       uint32_t hfnum_0_samples;
19409 +       uint64_t hfnum_0_frrem_accum;
19410 +       uint32_t hfnum_other_samples;
19411 +       uint64_t hfnum_other_frrem_accum;
19412 +#endif
19413 +
19414 +#ifdef DWC_UTE_CFI
19415 +       uint16_t pwron_rxfsiz;
19416 +       uint16_t pwron_gnptxfsiz;
19417 +       uint16_t pwron_txfsiz[15];
19418 +
19419 +       uint16_t init_rxfsiz;
19420 +       uint16_t init_gnptxfsiz;
19421 +       uint16_t init_txfsiz[15];
19422 +#endif
19423 +
19424 +       /** Lx state of device */
19425 +       dwc_otg_lx_state_e lx_state;
19426 +
19427 +};
19428 +
19429 +#ifdef DEBUG
19430 +/*
19431 + * This function is called when transfer is timed out.
19432 + */
19433 +extern void hc_xfer_timeout(void *ptr);
19434 +#endif
19435 +
19436 +/*
19437 + * The following functions are functions for works 
19438 + * using during handling some interrupts
19439 + */
19440 +extern void w_conn_id_status_change(void *p);
19441 +
19442 +extern void w_wakeup_detected(void *p);
19443 +
19444 +/*
19445 + * The following functions support initialization of the CIL driver component
19446 + * and the DWC_otg controller.
19447 + */
19448 +extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if);
19449 +extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);
19450 +
19451 +/** @name Device CIL Functions
19452 + * The following functions support managing the DWC_otg controller in device
19453 + * mode.
19454 + */
19455 +/**@{*/
19456 +extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if);
19457 +extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,
19458 +                                     uint32_t * _dest);
19459 +extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if);
19460 +extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
19461 +extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
19462 +extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
19463 +extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,
19464 +                                     dwc_ep_t * _ep);
19465 +extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,
19466 +                                        dwc_ep_t * _ep);
19467 +extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,
19468 +                                      dwc_ep_t * _ep);
19469 +extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,
19470 +                                         dwc_ep_t * _ep);
19471 +extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,
19472 +                                   dwc_ep_t * _ep, int _dma);
19473 +extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
19474 +extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,
19475 +                                  dwc_ep_t * _ep);
19476 +extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);
19477 +
19478 +#ifdef DWC_EN_ISOC
19479 +extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
19480 +                                             dwc_ep_t * ep);
19481 +extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
19482 +                                             dwc_ep_t * ep);
19483 +#endif                         /* DWC_EN_ISOC */
19484 +/**@}*/
19485 +
19486 +/** @name Host CIL Functions
19487 + * The following functions support managing the DWC_otg controller in host
19488 + * mode.
19489 + */
19490 +/**@{*/
19491 +extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
19492 +extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if,
19493 +                           dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status);
19494 +extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
19495 +extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if,
19496 +                                     dwc_hc_t * _hc);
19497 +extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if,
19498 +                                       dwc_hc_t * _hc);
19499 +extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
19500 +extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if,
19501 +                                   dwc_hc_t * _hc);
19502 +extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if);
19503 +extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if);
19504 +
19505 +extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc);
19506 +
19507 +/* Macro used to clear one channel interrupt */
19508 +#define clear_hc_int(_hc_regs_, _intr_) \
19509 +do { \
19510 +       hcint_data_t hcint_clear = {.d32 = 0}; \
19511 +       hcint_clear.b._intr_ = 1; \
19512 +       dwc_write_reg32(&(_hc_regs_)->hcint, hcint_clear.d32); \
19513 +} while (0)
19514 +
19515 +/*
19516 + * Macro used to disable one channel interrupt. Channel interrupts are
19517 + * disabled when the channel is halted or released by the interrupt handler.
19518 + * There is no need to handle further interrupts of that type until the
19519 + * channel is re-assigned. In fact, subsequent handling may cause crashes
19520 + * because the channel structures are cleaned up when the channel is released.
19521 + */
19522 +#define disable_hc_int(_hc_regs_, _intr_) \
19523 +do { \
19524 +       hcintmsk_data_t hcintmsk = {.d32 = 0}; \
19525 +       hcintmsk.b._intr_ = 1; \
19526 +       dwc_modify_reg32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \
19527 +} while (0)
19528 +               
19529 +/**
19530 + * This function Reads HPRT0 in preparation to modify. It keeps the
19531 + * WC bits 0 so that if they are read as 1, they won't clear when you
19532 + * write it back 
19533 + */
19534 +static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if)
19535 +{
19536 +       hprt0_data_t hprt0;
19537 +       hprt0.d32 = dwc_read_reg32(_core_if->host_if->hprt0);
19538 +       hprt0.b.prtena = 0;
19539 +       hprt0.b.prtconndet = 0;
19540 +       hprt0.b.prtenchng = 0;
19541 +       hprt0.b.prtovrcurrchng = 0;
19542 +       return hprt0.d32;
19543 +}
19544 +
19545 +/**@}*/
19546 +
19547 +/** @name Common CIL Functions
19548 + * The following functions support managing the DWC_otg controller in either
19549 + * device or host mode.
19550 + */
19551 +/**@{*/
19552 +
19553 +extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
19554 +                               uint8_t * dest, uint16_t bytes);
19555 +
19556 +extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);
19557 +extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);
19558 +extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);
19559 +
19560 +/**
19561 + * This function returns the Core Interrupt register.
19562 + */
19563 +static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
19564 +{
19565 +       return (dwc_read_reg32(&core_if->core_global_regs->gintsts) &
19566 +               dwc_read_reg32(&core_if->core_global_regs->gintmsk));
19567 +}
19568 +
19569 +/**
19570 + * This function returns the OTG Interrupt register.
19571 + */
19572 +static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if)
19573 +{
19574 +       return (dwc_read_reg32(&core_if->core_global_regs->gotgint));
19575 +}
19576 +
19577 +/**
19578 + * This function reads the Device All Endpoints Interrupt register and
19579 + * returns the IN endpoint interrupt bits.
19580 + */
19581 +static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
19582 +                                                      core_if)
19583 +{
19584 +
19585 +       uint32_t v;
19586 +
19587 +       if (core_if->multiproc_int_enable) {
19588 +               v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->
19589 +                                  deachint) & dwc_read_reg32(&core_if->dev_if->
19590 +                                                             dev_global_regs->
19591 +                                                             deachintmsk);
19592 +       } else {
19593 +               v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) &
19594 +                   dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk);
19595 +       }
19596 +       return (v & 0xffff);
19597 +}
19598 +
19599 +/**
19600 + * This function reads the Device All Endpoints Interrupt register and
19601 + * returns the OUT endpoint interrupt bits.
19602 + */
19603 +static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
19604 +                                                       core_if)
19605 +{
19606 +       uint32_t v;
19607 +
19608 +       if (core_if->multiproc_int_enable) {
19609 +               v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->
19610 +                                  deachint) & dwc_read_reg32(&core_if->dev_if->
19611 +                                                             dev_global_regs->
19612 +                                                             deachintmsk);
19613 +       } else {
19614 +               v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) &
19615 +                   dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk);
19616 +       }
19617 +
19618 +       return ((v & 0xffff0000) >> 16);
19619 +}
19620 +
19621 +/**
19622 + * This function returns the Device IN EP Interrupt register
19623 + */
19624 +static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
19625 +                                                  dwc_ep_t * ep)
19626 +{
19627 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
19628 +       uint32_t v, msk, emp;
19629 +
19630 +       if (core_if->multiproc_int_enable) {
19631 +               msk =
19632 +                   dwc_read_reg32(&dev_if->dev_global_regs->
19633 +                                  diepeachintmsk[ep->num]);
19634 +               emp =
19635 +                   dwc_read_reg32(&dev_if->dev_global_regs->
19636 +                                  dtknqr4_fifoemptymsk);
19637 +               msk |= ((emp >> ep->num) & 0x1) << 7;
19638 +               v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
19639 +       } else {
19640 +               msk = dwc_read_reg32(&dev_if->dev_global_regs->diepmsk);
19641 +               emp =
19642 +                   dwc_read_reg32(&dev_if->dev_global_regs->
19643 +                                  dtknqr4_fifoemptymsk);
19644 +               msk |= ((emp >> ep->num) & 0x1) << 7;
19645 +               v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
19646 +       }
19647 +
19648 +       return v;
19649 +}
19650 +
19651 +/**
19652 + * This function returns the Device OUT EP Interrupt register
19653 + */
19654 +static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *
19655 +                                                   _core_if, dwc_ep_t * _ep)
19656 +{
19657 +       dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
19658 +       uint32_t v;
19659 +       doepmsk_data_t msk = {.d32 = 0 };
19660 +
19661 +       if (_core_if->multiproc_int_enable) {
19662 +               msk.d32 =
19663 +                   dwc_read_reg32(&dev_if->dev_global_regs->
19664 +                                  doepeachintmsk[_ep->num]);
19665 +               if (_core_if->pti_enh_enable) {
19666 +                       msk.b.pktdrpsts = 1;
19667 +               }
19668 +               v = dwc_read_reg32(&dev_if->out_ep_regs[_ep->num]->
19669 +                                  doepint) & msk.d32;
19670 +       } else {
19671 +               msk.d32 = dwc_read_reg32(&dev_if->dev_global_regs->doepmsk);
19672 +               if (_core_if->pti_enh_enable) {
19673 +                       msk.b.pktdrpsts = 1;
19674 +               }
19675 +               v = dwc_read_reg32(&dev_if->out_ep_regs[_ep->num]->
19676 +                                  doepint) & msk.d32;
19677 +       }
19678 +       return v;
19679 +}
19680 +
19681 +/**
19682 + * This function returns the Host All Channel Interrupt register
19683 + */
19684 +static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t *
19685 +                                                          _core_if)
19686 +{
19687 +       return (dwc_read_reg32(&_core_if->host_if->host_global_regs->haint));
19688 +}
19689 +
19690 +static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t *
19691 +                                                     _core_if, dwc_hc_t * _hc)
19692 +{
19693 +       return (dwc_read_reg32
19694 +               (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint));
19695 +}
19696 +
19697 +/**
19698 + * This function returns the mode of the operation, host or device.
19699 + *
19700 + * @return 0 - Device Mode, 1 - Host Mode 
19701 + */
19702 +static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)
19703 +{
19704 +       return (dwc_read_reg32(&_core_if->core_global_regs->gintsts) & 0x1);
19705 +}
19706 +
19707 +/**@}*/
19708 +
19709 +/**
19710 + * DWC_otg CIL callback structure.     This structure allows the HCD and
19711 + * PCD to register functions used for starting and stopping the PCD
19712 + * and HCD for role change on for a DRD.
19713 + */
19714 +typedef struct dwc_otg_cil_callbacks {
19715 +       /** Start function for role change */
19716 +       int (*start) (void *_p);
19717 +       /** Stop Function for role change */
19718 +       int (*stop) (void *_p);
19719 +       /** Disconnect Function for role change */
19720 +       int (*disconnect) (void *_p);
19721 +       /** Resume/Remote wakeup Function */
19722 +       int (*resume_wakeup) (void *_p);
19723 +       /** Suspend function */
19724 +       int (*suspend) (void *_p);
19725 +       /** Session Start (SRP) */
19726 +       int (*session_start) (void *_p);
19727 +#ifdef CONFIG_USB_DWC_OTG_LPM
19728 +       /** Sleep (switch to L0 state) */
19729 +       int (*sleep) (void *_p);
19730 +#endif
19731 +       /** Pointer passed to start() and stop() */
19732 +       void *p;
19733 +} dwc_otg_cil_callbacks_t;
19734 +
19735 +extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if,
19736 +                                              dwc_otg_cil_callbacks_t * _cb,
19737 +                                              void *_p);
19738 +extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if,
19739 +                                              dwc_otg_cil_callbacks_t * _cb,
19740 +                                              void *_p);
19741 +
19742 +#endif
19743 --- /dev/null
19744 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
19745 @@ -0,0 +1,846 @@
19746 +/* ==========================================================================
19747 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
19748 + * $Revision: #15 $
19749 + * $Date: 2009/04/15 $
19750 + * $Change: 1234129 $
19751 + *
19752 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
19753 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
19754 + * otherwise expressly agreed to in writing between Synopsys and you.
19755 + *
19756 + * The Software IS NOT an item of Licensed Software or Licensed Product under
19757 + * any End User Software License Agreement or Agreement for Licensed Product
19758 + * with Synopsys or any supplement thereto. You are permitted to use and
19759 + * redistribute this Software in source and binary forms, with or without
19760 + * modification, provided that redistributions of source code must retain this
19761 + * notice. You may not view, use, disclose, copy or distribute this file or
19762 + * any information contained herein except pursuant to this license grant from
19763 + * Synopsys. If you do not agree with this notice, including the disclaimer
19764 + * below, then you are not authorized to use the Software.
19765 + *
19766 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
19767 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19768 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19769 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
19770 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19771 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19772 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19773 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19774 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19775 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
19776 + * DAMAGE.
19777 + * ========================================================================== */
19778 +
19779 +/** @file
19780 + *
19781 + * The Core Interface Layer provides basic services for accessing and
19782 + * managing the DWC_otg hardware. These services are used by both the
19783 + * Host Controller Driver and the Peripheral Controller Driver.
19784 + *
19785 + * This file contains the Common Interrupt handlers.
19786 + */
19787 +#include "dwc_os.h"
19788 +#include "dwc_otg_regs.h"
19789 +#include "dwc_otg_cil.h"
19790 +
19791 +#ifdef DEBUG
19792 +inline const char *op_state_str(dwc_otg_core_if_t * core_if)
19793 +{
19794 +       return (core_if->op_state == A_HOST ? "a_host" :
19795 +               (core_if->op_state == A_SUSPEND ? "a_suspend" :
19796 +                (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
19797 +                 (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
19798 +                  (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
19799 +}
19800 +#endif
19801 +
19802 +/** This function will log a debug message
19803 + *
19804 + * @param core_if Programming view of DWC_otg controller.
19805 + */
19806 +int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)
19807 +{
19808 +       gintsts_data_t gintsts;
19809 +       DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
19810 +                dwc_otg_mode(core_if) ? "Host" : "Device");
19811 +
19812 +       /* Clear interrupt */
19813 +       gintsts.d32 = 0;
19814 +       gintsts.b.modemismatch = 1;
19815 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
19816 +       return 1;
19817 +}
19818 +
19819 +/** Start the HCD.  Helper function for using the HCD callbacks.
19820 + *
19821 + * @param core_if Programming view of DWC_otg controller.
19822 + */
19823 +static inline void hcd_start(dwc_otg_core_if_t * core_if)
19824 +{
19825 +       if (core_if->hcd_cb && core_if->hcd_cb->start) {
19826 +               core_if->hcd_cb->start(core_if->hcd_cb->p);
19827 +       }
19828 +}
19829 +
19830 +/** Stop the HCD.  Helper function for using the HCD callbacks.
19831 + *
19832 + * @param core_if Programming view of DWC_otg controller.
19833 + */
19834 +static inline void hcd_stop(dwc_otg_core_if_t * core_if)
19835 +{
19836 +       if (core_if->hcd_cb && core_if->hcd_cb->stop) {
19837 +               core_if->hcd_cb->stop(core_if->hcd_cb->p);
19838 +       }
19839 +}
19840 +
19841 +/** Disconnect the HCD.  Helper function for using the HCD callbacks.
19842 + *
19843 + * @param core_if Programming view of DWC_otg controller.
19844 + */
19845 +static inline void hcd_disconnect(dwc_otg_core_if_t * core_if)
19846 +{
19847 +       if (core_if->hcd_cb && core_if->hcd_cb->disconnect) {
19848 +               core_if->hcd_cb->disconnect(core_if->hcd_cb->p);
19849 +       }
19850 +}
19851 +
19852 +/** Inform the HCD the a New Session has begun.  Helper function for
19853 + * using the HCD callbacks.
19854 + *
19855 + * @param core_if Programming view of DWC_otg controller.
19856 + */
19857 +static inline void hcd_session_start(dwc_otg_core_if_t * core_if)
19858 +{
19859 +       if (core_if->hcd_cb && core_if->hcd_cb->session_start) {
19860 +               core_if->hcd_cb->session_start(core_if->hcd_cb->p);
19861 +       }
19862 +}
19863 +
19864 +#ifdef CONFIG_USB_DWC_OTG_LPM
19865 +/**
19866 + * Inform the HCD about LPM sleep.
19867 + * Helper function for using the HCD callbacks.
19868 + *
19869 + * @param core_if Programming view of DWC_otg controller.
19870 + */
19871 +static inline void hcd_sleep(dwc_otg_core_if_t * core_if)
19872 +{
19873 +       if (core_if->hcd_cb && core_if->hcd_cb->sleep) {
19874 +               core_if->hcd_cb->sleep(core_if->hcd_cb->p);
19875 +       }
19876 +}
19877 +#endif
19878 +
19879 +/** Resume the HCD.  Helper function for using the HCD callbacks. 
19880 + *
19881 + * @param core_if Programming view of DWC_otg controller.
19882 + */
19883 +static inline void hcd_resume(dwc_otg_core_if_t * core_if)
19884 +{
19885 +       if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) {
19886 +               core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p);
19887 +       }
19888 +}
19889 +
19890 +/** Start the PCD.  Helper function for using the PCD callbacks.
19891 + *
19892 + * @param core_if Programming view of DWC_otg controller.
19893 + */
19894 +static inline void pcd_start(dwc_otg_core_if_t * core_if)
19895 +{
19896 +       if (core_if->pcd_cb && core_if->pcd_cb->start) {
19897 +               core_if->pcd_cb->start(core_if->pcd_cb->p);
19898 +       }
19899 +}
19900 +
19901 +/** Stop the PCD.  Helper function for using the PCD callbacks. 
19902 + *
19903 + * @param core_if Programming view of DWC_otg controller.
19904 + */
19905 +static inline void pcd_stop(dwc_otg_core_if_t * core_if)
19906 +{
19907 +       if (core_if->pcd_cb && core_if->pcd_cb->stop) {
19908 +               core_if->pcd_cb->stop(core_if->pcd_cb->p);
19909 +       }
19910 +}
19911 +
19912 +/** Suspend the PCD.  Helper function for using the PCD callbacks. 
19913 + *
19914 + * @param core_if Programming view of DWC_otg controller.
19915 + */
19916 +static inline void pcd_suspend(dwc_otg_core_if_t * core_if)
19917 +{
19918 +       if (core_if->pcd_cb && core_if->pcd_cb->suspend) {
19919 +               core_if->pcd_cb->suspend(core_if->pcd_cb->p);
19920 +       }
19921 +}
19922 +
19923 +/** Resume the PCD.  Helper function for using the PCD callbacks. 
19924 + *
19925 + * @param core_if Programming view of DWC_otg controller.
19926 + */
19927 +static inline void pcd_resume(dwc_otg_core_if_t * core_if)
19928 +{
19929 +       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
19930 +               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
19931 +       }
19932 +}
19933 +
19934 +/**
19935 + * This function handles the OTG Interrupts. It reads the OTG
19936 + * Interrupt Register (GOTGINT) to determine what interrupt has
19937 + * occurred.
19938 + *
19939 + * @param core_if Programming view of DWC_otg controller.
19940 + */
19941 +int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)
19942 +{
19943 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
19944 +       gotgint_data_t gotgint;
19945 +       gotgctl_data_t gotgctl;
19946 +       gintmsk_data_t gintmsk;
19947 +
19948 +       gotgint.d32 = dwc_read_reg32(&global_regs->gotgint);
19949 +       gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl);
19950 +       DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
19951 +                   op_state_str(core_if));
19952 +
19953 +       if (gotgint.b.sesenddet) {
19954 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
19955 +                           "Session End Detected++ (%s)\n",
19956 +                           op_state_str(core_if));
19957 +               gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl);
19958 +
19959 +               if (core_if->op_state == B_HOST) {
19960 +                       pcd_start(core_if);
19961 +                       core_if->op_state = B_PERIPHERAL;
19962 +               } else {
19963 +                       /* If not B_HOST and Device HNP still set. HNP
19964 +                        * Did not succeed!*/
19965 +                       if (gotgctl.b.devhnpen) {
19966 +                               DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
19967 +                               __DWC_ERROR("Device Not Connected/Responding!\n");
19968 +                       }
19969 +
19970 +                       /* If Session End Detected the B-Cable has
19971 +                        * been disconnected. */
19972 +                       /* Reset PCD and Gadget driver to a
19973 +                        * clean state. */
19974 +                       core_if->lx_state = DWC_OTG_L0;
19975 +                       pcd_stop(core_if);
19976 +               }
19977 +               gotgctl.d32 = 0;
19978 +               gotgctl.b.devhnpen = 1;
19979 +               dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0);
19980 +       }
19981 +       if (gotgint.b.sesreqsucstschng) {
19982 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
19983 +                           "Session Reqeust Success Status Change++\n");
19984 +               gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl);
19985 +               if (gotgctl.b.sesreqscs) {
19986 +                       if ((core_if->core_params->phy_type ==
19987 +                            DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {
19988 +                               core_if->srp_success = 1;
19989 +                       } else {
19990 +                               pcd_resume(core_if);
19991 +                               /* Clear Session Request */
19992 +                               gotgctl.d32 = 0;
19993 +                               gotgctl.b.sesreq = 1;
19994 +                               dwc_modify_reg32(&global_regs->gotgctl,
19995 +                                                gotgctl.d32, 0);
19996 +                       }
19997 +               }
19998 +       }
19999 +       if (gotgint.b.hstnegsucstschng) {
20000 +               /* Print statements during the HNP interrupt handling
20001 +                * can cause it to fail.*/
20002 +               gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl);
20003 +               if (gotgctl.b.hstnegscs) {
20004 +                       if (dwc_otg_is_host_mode(core_if)) {
20005 +                               core_if->op_state = B_HOST;
20006 +                               /*
20007 +                                * Need to disable SOF interrupt immediately.
20008 +                                * When switching from device to host, the PCD
20009 +                                * interrupt handler won't handle the
20010 +                                * interrupt if host mode is already set. The
20011 +                                * HCD interrupt handler won't get called if
20012 +                                * the HCD state is HALT. This means that the
20013 +                                * interrupt does not get handled and Linux
20014 +                                * complains loudly.
20015 +                                */
20016 +                               gintmsk.d32 = 0;
20017 +                               gintmsk.b.sofintr = 1;
20018 +                               dwc_modify_reg32(&global_regs->gintmsk,
20019 +                                                gintmsk.d32, 0);
20020 +                               pcd_stop(core_if);
20021 +                               /*
20022 +                                * Initialize the Core for Host mode.
20023 +                                */
20024 +                               hcd_start(core_if);
20025 +                               core_if->op_state = B_HOST;
20026 +                       }
20027 +               } else {
20028 +                       gotgctl.d32 = 0;
20029 +                       gotgctl.b.hnpreq = 1;
20030 +                       gotgctl.b.devhnpen = 1;
20031 +                       dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0);
20032 +                       DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
20033 +                       __DWC_ERROR("Device Not Connected/Responding\n");
20034 +               }
20035 +       }
20036 +       if (gotgint.b.hstnegdet) {
20037 +               /* The disconnect interrupt is set at the same time as
20038 +                * Host Negotiation Detected.  During the mode
20039 +                * switch all interrupts are cleared so the disconnect
20040 +                * interrupt handler will not get executed.
20041 +                */
20042 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
20043 +                           "Host Negotiation Detected++ (%s)\n",
20044 +                           (dwc_otg_is_host_mode(core_if) ? "Host" :
20045 +                            "Device"));
20046 +               if (dwc_otg_is_device_mode(core_if)) {
20047 +                       DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
20048 +                                   core_if->op_state);
20049 +                       hcd_disconnect(core_if);
20050 +                       pcd_start(core_if);
20051 +                       core_if->op_state = A_PERIPHERAL;
20052 +               } else {
20053 +                       /*
20054 +                        * Need to disable SOF interrupt immediately. When
20055 +                        * switching from device to host, the PCD interrupt
20056 +                        * handler won't handle the interrupt if host mode is
20057 +                        * already set. The HCD interrupt handler won't get
20058 +                        * called if the HCD state is HALT. This means that
20059 +                        * the interrupt does not get handled and Linux
20060 +                        * complains loudly.
20061 +                        */
20062 +                       gintmsk.d32 = 0;
20063 +                       gintmsk.b.sofintr = 1;
20064 +                       dwc_modify_reg32(&global_regs->gintmsk, gintmsk.d32, 0);
20065 +                       pcd_stop(core_if);
20066 +                       hcd_start(core_if);
20067 +                       core_if->op_state = A_HOST;
20068 +               }
20069 +       }
20070 +       if (gotgint.b.adevtoutchng) {
20071 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
20072 +                           "A-Device Timeout Change++\n");
20073 +       }
20074 +       if (gotgint.b.debdone) {
20075 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
20076 +       }
20077 +
20078 +       /* Clear GOTGINT */
20079 +       dwc_write_reg32(&core_if->core_global_regs->gotgint, gotgint.d32);
20080 +
20081 +       return 1;
20082 +}
20083 +
20084 +void w_conn_id_status_change(void *p)
20085 +{
20086 +       dwc_otg_core_if_t *core_if = p;
20087 +       uint32_t count = 0;
20088 +       gotgctl_data_t gotgctl = {.d32 = 0 };
20089 +
20090 +       gotgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
20091 +       DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
20092 +       DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
20093 +
20094 +       /* B-Device connector (Device Mode) */
20095 +       if (gotgctl.b.conidsts) {
20096 +               /* Wait for switch to device mode. */
20097 +               while (!dwc_otg_is_device_mode(core_if)) {
20098 +                       DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",
20099 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
20100 +                                   "Peripheral"));
20101 +                       dwc_mdelay(100);
20102 +                       if (++count > 10000)
20103 +                               break;
20104 +               }
20105 +               DWC_ASSERT(++count < 10000,
20106 +                          "Connection id status change timed out");
20107 +               core_if->op_state = B_PERIPHERAL;
20108 +               dwc_otg_core_init(core_if);
20109 +               dwc_otg_enable_global_interrupts(core_if);
20110 +               pcd_start(core_if);
20111 +       } else {
20112 +               /* A-Device connector (Host Mode) */
20113 +               while (!dwc_otg_is_host_mode(core_if)) {
20114 +                       DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",
20115 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
20116 +                                   "Peripheral"));
20117 +                       dwc_mdelay(100);
20118 +                       if (++count > 10000)
20119 +                               break;
20120 +               }
20121 +               DWC_ASSERT(++count < 10000,
20122 +                          "Connection id status change timed out");
20123 +               core_if->op_state = A_HOST;
20124 +               /*
20125 +                * Initialize the Core for Host mode.
20126 +                */
20127 +               dwc_otg_core_init(core_if);
20128 +               dwc_otg_enable_global_interrupts(core_if);
20129 +               hcd_start(core_if);
20130 +       }
20131 +}
20132 +
20133 +/**
20134 + * This function handles the Connector ID Status Change Interrupt.  It
20135 + * reads the OTG Interrupt Register (GOTCTL) to determine whether this
20136 + * is a Device to Host Mode transition or a Host Mode to Device
20137 + * Transition.  
20138 + *
20139 + * This only occurs when the cable is connected/removed from the PHY
20140 + * connector.
20141 + *
20142 + * @param core_if Programming view of DWC_otg controller.
20143 + */
20144 +int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)
20145 +{
20146 +
20147 +       /*
20148 +        * Need to disable SOF interrupt immediately. If switching from device
20149 +        * to host, the PCD interrupt handler won't handle the interrupt if
20150 +        * host mode is already set. The HCD interrupt handler won't get
20151 +        * called if the HCD state is HALT. This means that the interrupt does
20152 +        * not get handled and Linux complains loudly.
20153 +        */
20154 +       gintmsk_data_t gintmsk = {.d32 = 0 };
20155 +       gintsts_data_t gintsts = {.d32 = 0 };
20156 +
20157 +       gintmsk.b.sofintr = 1;
20158 +       dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
20159 +
20160 +       DWC_DEBUGPL(DBG_CIL,
20161 +                   " ++Connector ID Status Change Interrupt++  (%s)\n",
20162 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
20163 +
20164 +       /*
20165 +        * Need to schedule a work, as there are possible DELAY function calls
20166 +        */
20167 +       DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
20168 +                          core_if, "connection id status change");
20169 +
20170 +       /* Set flag and clear interrupt */
20171 +       gintsts.b.conidstschng = 1;
20172 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
20173 +
20174 +       return 1;
20175 +}
20176 +
20177 +/**
20178 + * This interrupt indicates that a device is initiating the Session
20179 + * Request Protocol to request the host to turn on bus power so a new
20180 + * session can begin. The handler responds by turning on bus power. If
20181 + * the DWC_otg controller is in low power mode, the handler brings the
20182 + * controller out of low power mode before turning on bus power.
20183 + *
20184 + * @param core_if Programming view of DWC_otg controller.
20185 + */
20186 +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
20187 +{
20188 +       hprt0_data_t hprt0;
20189 +       gintsts_data_t gintsts;
20190 +
20191 +#ifndef DWC_HOST_ONLY
20192 +       DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
20193 +
20194 +       if (dwc_otg_is_device_mode(core_if)) {
20195 +               DWC_PRINTF("SRP: Device mode\n");
20196 +       } else {
20197 +               DWC_PRINTF("SRP: Host mode\n");
20198 +
20199 +               /* Turn on the port power bit. */
20200 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
20201 +               hprt0.b.prtpwr = 1;
20202 +               dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
20203 +
20204 +               /* Start the Connection timer. So a message can be displayed
20205 +                * if connect does not occur within 10 seconds. */
20206 +               hcd_session_start(core_if);
20207 +       }
20208 +#endif
20209 +
20210 +       /* Clear interrupt */
20211 +       gintsts.d32 = 0;
20212 +       gintsts.b.sessreqintr = 1;
20213 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
20214 +
20215 +       return 1;
20216 +}
20217 +
20218 +void w_wakeup_detected(void *p)
20219 +{
20220 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;
20221 +       /*
20222 +        * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
20223 +        * so that OPT tests pass with all PHYs).
20224 +        */
20225 +       hprt0_data_t hprt0 = {.d32 = 0 };
20226 +#if 0
20227 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
20228 +       /* Restart the Phy Clock */
20229 +       pcgcctl.b.stoppclk = 1;
20230 +       dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0);
20231 +       dwc_udelay(10);
20232 +#endif                         //0
20233 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
20234 +       DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
20235 +//      dwc_mdelay(70);
20236 +       hprt0.b.prtres = 0;     /* Resume */
20237 +       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
20238 +       DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
20239 +                   dwc_read_reg32(core_if->host_if->hprt0));
20240 +
20241 +       hcd_resume(core_if);
20242 +
20243 +       /** Change to L0 state*/
20244 +       core_if->lx_state = DWC_OTG_L0;
20245 +
20246 +}
20247 +
20248 +/**
20249 + * This interrupt indicates that the DWC_otg controller has detected a
20250 + * resume or remote wakeup sequence. If the DWC_otg controller is in
20251 + * low power mode, the handler must brings the controller out of low
20252 + * power mode. The controller automatically begins resume
20253 + * signaling. The handler schedules a time to stop resume signaling.
20254 + */
20255 +int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
20256 +{
20257 +       gintsts_data_t gintsts;
20258 +
20259 +       DWC_DEBUGPL(DBG_ANY,
20260 +                   "++Resume and Remote Wakeup Detected Interrupt++\n");
20261 +
20262 +       DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
20263 +
20264 +       if (dwc_otg_is_device_mode(core_if)) {
20265 +               dctl_data_t dctl = {.d32 = 0 };
20266 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
20267 +                           dwc_read_reg32(&core_if->dev_if->dev_global_regs->
20268 +                                          dsts));
20269 +               if (core_if->lx_state == DWC_OTG_L2) {
20270 +#ifdef PARTIAL_POWER_DOWN
20271 +                       if (core_if->hwcfg4.b.power_optimiz) {
20272 +                               pcgcctl_data_t power = {.d32 = 0 };
20273 +
20274 +                               power.d32 = dwc_read_reg32(core_if->pcgcctl);
20275 +                               DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
20276 +                                           power.d32);
20277 +
20278 +                               power.b.stoppclk = 0;
20279 +                               dwc_write_reg32(core_if->pcgcctl, power.d32);
20280 +
20281 +                               power.b.pwrclmp = 0;
20282 +                               dwc_write_reg32(core_if->pcgcctl, power.d32);
20283 +
20284 +                               power.b.rstpdwnmodule = 0;
20285 +                               dwc_write_reg32(core_if->pcgcctl, power.d32);
20286 +                       }
20287 +#endif
20288 +                       /* Clear the Remote Wakeup Signalling */
20289 +                       dctl.b.rmtwkupsig = 1;
20290 +                       dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
20291 +                                        dctl, dctl.d32, 0);
20292 +
20293 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
20294 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->
20295 +                                                              p);
20296 +                       }
20297 +               } else {
20298 +                       glpmcfg_data_t lpmcfg;
20299 +                       lpmcfg.d32 =
20300 +                           dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
20301 +                       lpmcfg.b.hird_thres &= (~(1 << 4));
20302 +                       dwc_write_reg32(&core_if->core_global_regs->glpmcfg,
20303 +                                       lpmcfg.d32);
20304 +               }
20305 +               /** Change to L0 state*/
20306 +               core_if->lx_state = DWC_OTG_L0;
20307 +       } else {
20308 +               if (core_if->lx_state != DWC_OTG_L1) {
20309 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
20310 +
20311 +                       /* Restart the Phy Clock */
20312 +                       pcgcctl.b.stoppclk = 1;
20313 +                       dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0);
20314 +
20315 +                       DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);
20316 +               } else {
20317 +                       /** Change to L0 state*/
20318 +                       core_if->lx_state = DWC_OTG_L0;
20319 +               }
20320 +       }
20321 +
20322 +       /* Clear interrupt */
20323 +       gintsts.d32 = 0;
20324 +       gintsts.b.wkupintr = 1;
20325 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
20326 +
20327 +       return 1;
20328 +}
20329 +
20330 +/** 
20331 + * This interrupt indicates that a device has been disconnected from
20332 + * the root port. 
20333 + */
20334 +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)
20335 +{
20336 +       gintsts_data_t gintsts;
20337 +
20338 +       DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
20339 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
20340 +                   op_state_str(core_if));
20341 +
20342 +/** @todo Consolidate this if statement. */
20343 +#ifndef DWC_HOST_ONLY
20344 +       if (core_if->op_state == B_HOST) {
20345 +               /* If in device mode Disconnect and stop the HCD, then
20346 +                * start the PCD. */
20347 +               hcd_disconnect(core_if);
20348 +               pcd_start(core_if);
20349 +               core_if->op_state = B_PERIPHERAL;
20350 +       } else if (dwc_otg_is_device_mode(core_if)) {
20351 +               gotgctl_data_t gotgctl = {.d32 = 0 };
20352 +               gotgctl.d32 =
20353 +                   dwc_read_reg32(&core_if->core_global_regs->gotgctl);
20354 +               if (gotgctl.b.hstsethnpen == 1) {
20355 +                       /* Do nothing, if HNP in process the OTG
20356 +                        * interrupt "Host Negotiation Detected"
20357 +                        * interrupt will do the mode switch.
20358 +                        */
20359 +               } else if (gotgctl.b.devhnpen == 0) {
20360 +                       /* If in device mode Disconnect and stop the HCD, then
20361 +                        * start the PCD. */
20362 +                       hcd_disconnect(core_if);
20363 +                       pcd_start(core_if);
20364 +                       core_if->op_state = B_PERIPHERAL;
20365 +               } else {
20366 +                       DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
20367 +               }
20368 +       } else {
20369 +               if (core_if->op_state == A_HOST) {
20370 +                       /* A-Cable still connected but device disconnected. */
20371 +                       hcd_disconnect(core_if);
20372 +               }
20373 +       }
20374 +#endif
20375 +       /* Change to L3(OFF) state */
20376 +       core_if->lx_state = DWC_OTG_L3;
20377 +
20378 +       gintsts.d32 = 0;
20379 +       gintsts.b.disconnect = 1;
20380 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
20381 +       return 1;
20382 +}
20383 +
20384 +/**
20385 + * This interrupt indicates that SUSPEND state has been detected on
20386 + * the USB.
20387 + * 
20388 + * For HNP the USB Suspend interrupt signals the change from
20389 + * "a_peripheral" to "a_host".
20390 + *
20391 + * When power management is enabled the core will be put in low power
20392 + * mode.
20393 + */
20394 +int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
20395 +{
20396 +       dsts_data_t dsts;
20397 +       gintsts_data_t gintsts;
20398 +
20399 +       DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
20400 +
20401 +       if (dwc_otg_is_device_mode(core_if)) {
20402 +               /* Check the Device status register to determine if the Suspend
20403 +                * state is active. */
20404 +               dsts.d32 =
20405 +                   dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
20406 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
20407 +               DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
20408 +                           "HWCFG4.power Optimize=%d\n",
20409 +                           dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
20410 +
20411 +#ifdef PARTIAL_POWER_DOWN
20412 +/** @todo Add a module parameter for power management. */
20413 +
20414 +               if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
20415 +                       pcgcctl_data_t power = {.d32 = 0 };
20416 +                       DWC_DEBUGPL(DBG_CIL, "suspend\n");
20417 +
20418 +                       power.b.pwrclmp = 1;
20419 +                       dwc_write_reg32(core_if->pcgcctl, power.d32);
20420 +
20421 +                       power.b.rstpdwnmodule = 1;
20422 +                       dwc_modify_reg32(core_if->pcgcctl, 0, power.d32);
20423 +
20424 +                       power.b.stoppclk = 1;
20425 +                       dwc_modify_reg32(core_if->pcgcctl, 0, power.d32);
20426 +
20427 +               } else {
20428 +                       DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
20429 +               }
20430 +#endif
20431 +               /* PCD callback for suspend. */
20432 +               pcd_suspend(core_if);
20433 +       } else {
20434 +               if (core_if->op_state == A_PERIPHERAL) {
20435 +                       DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
20436 +                       /* Clear the a_peripheral flag, back to a_host. */
20437 +                       pcd_stop(core_if);
20438 +                       hcd_start(core_if);
20439 +                       core_if->op_state = A_HOST;
20440 +               }
20441 +       }
20442 +
20443 +       /* Change to L2(suspend) state */
20444 +       core_if->lx_state = DWC_OTG_L2;
20445 +
20446 +       /* Clear interrupt */
20447 +       gintsts.d32 = 0;
20448 +       gintsts.b.usbsuspend = 1;
20449 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
20450 +
20451 +       return 1;
20452 +}
20453 +
20454 +#ifdef CONFIG_USB_DWC_OTG_LPM
20455 +/**
20456 + * This function hadles LPM transaction received interrupt.
20457 + */
20458 +static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
20459 +{
20460 +       glpmcfg_data_t lpmcfg;
20461 +       gintsts_data_t gintsts;
20462 +
20463 +       if (!core_if->core_params->lpm_enable) {
20464 +               DWC_PRINTF("Unexpected LPM interrupt\n");
20465 +       }
20466 +
20467 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
20468 +       DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
20469 +
20470 +       if (dwc_otg_is_host_mode(core_if)) {
20471 +               hcd_sleep(core_if);
20472 +       } else {
20473 +               lpmcfg.b.hird_thres |= (1 << 4);
20474 +               dwc_write_reg32(&core_if->core_global_regs->glpmcfg,
20475 +                               lpmcfg.d32);
20476 +       }
20477 +
20478 +       /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */      
20479 +       dwc_udelay(10);
20480 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
20481 +       if (lpmcfg.b.prt_sleep_sts) {
20482 +               /* Save the current state */
20483 +               core_if->lx_state = DWC_OTG_L1;
20484 +       }
20485 +
20486 +       /* Clear interrupt  */
20487 +       gintsts.d32 = 0;
20488 +       gintsts.b.lpmtranrcvd = 1;
20489 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
20490 +       return 1;
20491 +}
20492 +#endif                         /* CONFIG_USB_DWC_OTG_LPM */
20493 +
20494 +/**
20495 + * This function returns the Core Interrupt register.
20496 + */
20497 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
20498 +{
20499 +       gintsts_data_t gintsts;
20500 +       gintmsk_data_t gintmsk;
20501 +       gintmsk_data_t gintmsk_common = {.d32 = 0 };
20502 +       gintmsk_common.b.wkupintr = 1;
20503 +       gintmsk_common.b.sessreqintr = 1;
20504 +       gintmsk_common.b.conidstschng = 1;
20505 +       gintmsk_common.b.otgintr = 1;
20506 +       gintmsk_common.b.modemismatch = 1;
20507 +       gintmsk_common.b.disconnect = 1;
20508 +       gintmsk_common.b.usbsuspend = 1;
20509 +#ifdef CONFIG_USB_DWC_OTG_LPM
20510 +       gintmsk_common.b.lpmtranrcvd = 1;
20511 +#endif
20512 +       /** @todo: The port interrupt occurs while in device 
20513 +         * mode. Added code to CIL to clear the interrupt for now! 
20514 +         */
20515 +       gintmsk_common.b.portintr = 1;
20516 +
20517 +       gintsts.d32 = dwc_read_reg32(&core_if->core_global_regs->gintsts);
20518 +       gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk);
20519 +#ifdef DEBUG
20520 +       /* if any common interrupts set */
20521 +       if (gintsts.d32 & gintmsk_common.d32) {
20522 +               DWC_DEBUGPL(DBG_ANY, "gintsts=%08x  gintmsk=%08x\n",
20523 +                           gintsts.d32, gintmsk.d32);
20524 +       }
20525 +#endif
20526 +
20527 +       return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
20528 +
20529 +}
20530 +
20531 +/**
20532 + * Common interrupt handler.
20533 + *
20534 + * The common interrupts are those that occur in both Host and Device mode. 
20535 + * This handler handles the following interrupts:
20536 + * - Mode Mismatch Interrupt
20537 + * - Disconnect Interrupt
20538 + * - OTG Interrupt
20539 + * - Connector ID Status Change Interrupt
20540 + * - Session Request Interrupt.
20541 + * - Resume / Remote Wakeup Detected Interrupt.
20542 + * - LPM Transaction Received Interrutp
20543 + * 
20544 + */
20545 +int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t * core_if)
20546 +{
20547 +       int retval = 0;
20548 +       gintsts_data_t gintsts;
20549 +
20550 +       gintsts.d32 = dwc_otg_read_common_intr(core_if);
20551 +
20552 +       if (gintsts.b.modemismatch) {
20553 +               retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
20554 +       }
20555 +       if (gintsts.b.otgintr) {
20556 +               retval |= dwc_otg_handle_otg_intr(core_if);
20557 +       }
20558 +       if (gintsts.b.conidstschng) {
20559 +               retval |= dwc_otg_handle_conn_id_status_change_intr(core_if);
20560 +       }
20561 +       if (gintsts.b.disconnect) {
20562 +               retval |= dwc_otg_handle_disconnect_intr(core_if);
20563 +       }
20564 +       if (gintsts.b.sessreqintr) {
20565 +               retval |= dwc_otg_handle_session_req_intr(core_if);
20566 +       }
20567 +       if (gintsts.b.wkupintr) {
20568 +               retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
20569 +       }
20570 +       if (gintsts.b.usbsuspend) {
20571 +               retval |= dwc_otg_handle_usb_suspend_intr(core_if);
20572 +       }
20573 +#ifdef CONFIG_USB_DWC_OTG_LPM
20574 +       if (gintsts.b.lpmtranrcvd) {
20575 +               retval |= dwc_otg_handle_lpm_intr(core_if);
20576 +       }
20577 +#endif
20578 +
20579 +       if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
20580 +               /* The port interrupt occurs while in device mode with HPRT0
20581 +                * Port Enable/Disable.
20582 +                */
20583 +               gintsts.d32 = 0;
20584 +               gintsts.b.portintr = 1;
20585 +               dwc_write_reg32(&core_if->core_global_regs->gintsts,
20586 +                               gintsts.d32);
20587 +               retval |= 1;
20588 +
20589 +       }
20590 +       return retval;
20591 +}
20592 --- /dev/null
20593 +++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
20594 @@ -0,0 +1,641 @@
20595 +/* ==========================================================================
20596 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
20597 + * $Revision: #4 $
20598 + * $Date: 2008/12/18 $
20599 + * $Change: 1155299 $
20600 + *
20601 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
20602 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
20603 + * otherwise expressly agreed to in writing between Synopsys and you.
20604 + *
20605 + * The Software IS NOT an item of Licensed Software or Licensed Product under
20606 + * any End User Software License Agreement or Agreement for Licensed Product
20607 + * with Synopsys or any supplement thereto. You are permitted to use and
20608 + * redistribute this Software in source and binary forms, with or without
20609 + * modification, provided that redistributions of source code must retain this
20610 + * notice. You may not view, use, disclose, copy or distribute this file or
20611 + * any information contained herein except pursuant to this license grant from
20612 + * Synopsys. If you do not agree with this notice, including the disclaimer
20613 + * below, then you are not authorized to use the Software.
20614 + *
20615 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
20616 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20617 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20618 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
20619 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20620 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20621 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20622 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20623 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20624 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20625 + * DAMAGE.
20626 + * ========================================================================== */
20627 +#if !defined(__DWC_CORE_IF_H__)
20628 +#define __DWC_CORE_IF_H__
20629 +
20630 +#include "dwc_os.h"
20631 +
20632 +/** @file
20633 + * This file defines DWC_OTG Core API
20634 + */
20635 +
20636 +struct dwc_otg_core_if;
20637 +typedef struct dwc_otg_core_if dwc_otg_core_if_t;
20638 +
20639 +/** Maximum number of Periodic FIFOs */
20640 +#define MAX_PERIO_FIFOS 15
20641 +/** Maximum number of Periodic FIFOs */
20642 +#define MAX_TX_FIFOS 15
20643 +
20644 +/** Maximum number of Endpoints/HostChannels */
20645 +#define MAX_EPS_CHANNELS 16
20646 +
20647 +extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);
20648 +extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);
20649 +extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if);
20650 +
20651 +extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if);
20652 +extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if);
20653 +
20654 +extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if);
20655 +extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if);
20656 +
20657 +extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);
20658 +
20659 +/** This function should be called on every hardware interrupt. */
20660 +extern int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t * _core_if);
20661 +
20662 +/** @name OTG Core Parameters */
20663 +/** @{ */
20664 +
20665 +/**
20666 + * Specifies the OTG capabilities. The driver will automatically
20667 + * detect the value for this parameter if none is specified.
20668 + * 0 - HNP and SRP capable (default)
20669 + * 1 - SRP Only capable
20670 + * 2 - No HNP/SRP capable
20671 + */
20672 +extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val);
20673 +extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if);
20674 +#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
20675 +#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
20676 +#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
20677 +#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
20678 +
20679 +extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val);
20680 +extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if);
20681 +#define dwc_param_opt_default 1
20682 +
20683 +/**
20684 + * Specifies whether to use slave or DMA mode for accessing the data
20685 + * FIFOs. The driver will automatically detect the value for this
20686 + * parameter if none is specified.
20687 + * 0 - Slave
20688 + * 1 - DMA (default, if available)
20689 + */
20690 +extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if,
20691 +                                       int32_t val);
20692 +extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if);
20693 +#define dwc_param_dma_enable_default 1
20694 +
20695 +/**
20696 + * When DMA mode is enabled specifies whether to use
20697 + * address DMA or DMA Descritor mode for accessing the data
20698 + * FIFOs in device mode. The driver will automatically detect
20699 + * the value for this parameter if none is specified.
20700 + * 0 - address DMA
20701 + * 1 - DMA Descriptor(default, if available)
20702 + */
20703 +extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,
20704 +                                            int32_t val);
20705 +extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);
20706 +//#define dwc_param_dma_desc_enable_default 1
20707 +#define dwc_param_dma_desc_enable_default 0 // Broadcom BCM2708
20708 +
20709 +/** The DMA Burst size (applicable only for External DMA
20710 + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
20711 + */
20712 +extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if,
20713 +                                           int32_t val);
20714 +extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if);
20715 +#define dwc_param_dma_burst_size_default 32
20716 +
20717 +/**
20718 + * Specifies the maximum speed of operation in host and device mode.
20719 + * The actual speed depends on the speed of the attached device and
20720 + * the value of phy_type. The actual speed depends on the speed of the
20721 + * attached device.
20722 + * 0 - High Speed (default)
20723 + * 1 - Full Speed
20724 + */
20725 +extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val);
20726 +extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if);
20727 +#define dwc_param_speed_default 0
20728 +#define DWC_SPEED_PARAM_HIGH 0
20729 +#define DWC_SPEED_PARAM_FULL 1
20730 +
20731 +/** Specifies whether low power mode is supported when attached
20732 + *     to a Full Speed or Low Speed device in host mode.
20733 + * 0 - Don't support low power mode (default)
20734 + * 1 - Support low power mode
20735 + */
20736 +extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
20737 +                                                         core_if, int32_t val);
20738 +extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
20739 +                                                             * core_if);
20740 +#define dwc_param_host_support_fs_ls_low_power_default 0
20741 +
20742 +/** Specifies the PHY clock rate in low power mode when connected to a
20743 + * Low Speed device in host mode. This parameter is applicable only if
20744 + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
20745 + * then defaults to 6 MHZ otherwise 48 MHZ.
20746 + *
20747 + * 0 - 48 MHz
20748 + * 1 - 6 MHz
20749 + */
20750 +extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
20751 +                                                      core_if, int32_t val);
20752 +extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
20753 +                                                          core_if);
20754 +#define dwc_param_host_ls_low_power_phy_clk_default 0
20755 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
20756 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
20757 +
20758 +/**
20759 + * 0 - Use cC FIFO size parameters
20760 + * 1 - Allow dynamic FIFO sizing (default)
20761 + */
20762 +extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
20763 +                                                int32_t val);
20764 +extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
20765 +                                                    core_if);
20766 +#define dwc_param_enable_dynamic_fifo_default 1
20767 +
20768 +/** Total number of 4-byte words in the data FIFO memory. This
20769 + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
20770 + * Tx FIFOs.
20771 + * 32 to 32768 (default 8192)
20772 + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
20773 + */
20774 +extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if,
20775 +                                           int32_t val);
20776 +extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if);
20777 +//#define dwc_param_data_fifo_size_default 8192
20778 +#define dwc_param_data_fifo_size_default 0xFF0 // Broadcom BCM2708
20779 +
20780 +/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
20781 + * FIFO sizing is enabled.
20782 + * 16 to 32768 (default 1064)
20783 + */
20784 +extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if,
20785 +                                             int32_t val);
20786 +extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if);
20787 +#define dwc_param_dev_rx_fifo_size_default 1064
20788 +
20789 +/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
20790 + * when dynamic FIFO sizing is enabled.
20791 + * 16 to 32768 (default 1024)
20792 + */
20793 +extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
20794 +                                                    core_if, int32_t val);
20795 +extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
20796 +                                                        core_if);
20797 +#define dwc_param_dev_nperio_tx_fifo_size_default 1024
20798 +
20799 +/** Number of 4-byte words in each of the periodic Tx FIFOs in device
20800 + * mode when dynamic FIFO sizing is enabled.
20801 + * 4 to 768 (default 256)
20802 + */
20803 +extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
20804 +                                                   int32_t val, int fifo_num);
20805 +extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
20806 +                                                       core_if, int fifo_num);
20807 +#define dwc_param_dev_perio_tx_fifo_size_default 256
20808 +
20809 +/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
20810 + * FIFO sizing is enabled.
20811 + * 16 to 32768 (default 1024)
20812 + */
20813 +extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
20814 +                                              int32_t val);
20815 +extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);
20816 +//#define dwc_param_host_rx_fifo_size_default 1024
20817 +#define dwc_param_host_rx_fifo_size_default 774 // Broadcom BCM2708
20818 +
20819 +/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
20820 + * when Dynamic FIFO sizing is enabled in the core.
20821 + * 16 to 32768 (default 1024)
20822 + */
20823 +extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
20824 +                                                     core_if, int32_t val);
20825 +extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
20826 +                                                         core_if);
20827 +//#define dwc_param_host_nperio_tx_fifo_size_default 1024
20828 +#define dwc_param_host_nperio_tx_fifo_size_default 0x100 // Broadcom BCM2708
20829 +
20830 +/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
20831 + * FIFO sizing is enabled.
20832 + * 16 to 32768 (default 1024)
20833 + */
20834 +extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
20835 +                                                    core_if, int32_t val);
20836 +extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
20837 +                                                        core_if);
20838 +//#define dwc_param_host_perio_tx_fifo_size_default 1024
20839 +#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708
20840 +
20841 +/** The maximum transfer size supported in bytes.
20842 + * 2047 to 65,535  (default 65,535)
20843 + */
20844 +extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
20845 +                                              int32_t val);
20846 +extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if);
20847 +#define dwc_param_max_transfer_size_default 65535
20848 +
20849 +/** The maximum number of packets in a transfer.
20850 + * 15 to 511  (default 511)
20851 + */
20852 +extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if,
20853 +                                             int32_t val);
20854 +extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if);
20855 +#define dwc_param_max_packet_count_default 511
20856 +
20857 +/** The number of host channel registers to use.
20858 + * 1 to 16 (default 12)
20859 + * Note: The FPGA configuration supports a maximum of 12 host channels.
20860 + */
20861 +extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,
20862 +                                          int32_t val);
20863 +extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);
20864 +#define dwc_param_host_channels_default 12
20865 +
20866 +/** The number of endpoints in addition to EP0 available for device
20867 + * mode operations.
20868 + * 1 to 15 (default 6 IN and OUT)
20869 + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
20870 + * endpoints in addition to EP0.
20871 + */
20872 +extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,
20873 +                                          int32_t val);
20874 +extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);
20875 +#define dwc_param_dev_endpoints_default 6
20876 +
20877 +/**
20878 + * Specifies the type of PHY interface to use. By default, the driver
20879 + * will automatically detect the phy_type.
20880 + *
20881 + * 0 - Full Speed PHY
20882 + * 1 - UTMI+ (default)
20883 + * 2 - ULPI
20884 + */
20885 +extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val);
20886 +extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if);
20887 +#define DWC_PHY_TYPE_PARAM_FS 0
20888 +#define DWC_PHY_TYPE_PARAM_UTMI 1
20889 +#define DWC_PHY_TYPE_PARAM_ULPI 2
20890 +#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
20891 +
20892 +/**
20893 + * Specifies the UTMI+ Data Width.     This parameter is
20894 + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
20895 + * PHY_TYPE, this parameter indicates the data width between
20896 + * the MAC and the ULPI Wrapper.) Also, this parameter is
20897 + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
20898 + * to "8 and 16 bits", meaning that the core has been
20899 + * configured to work at either data path width.
20900 + *
20901 + * 8 or 16 bits (default 16)
20902 + */
20903 +extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if,
20904 +                                           int32_t val);
20905 +extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if);
20906 +//#define dwc_param_phy_utmi_width_default 16
20907 +#define dwc_param_phy_utmi_width_default 8 // Broadcom BCM2708 
20908 +
20909 +/**
20910 + * Specifies whether the ULPI operates at double or single
20911 + * data rate. This parameter is only applicable if PHY_TYPE is
20912 + * ULPI.
20913 + *
20914 + * 0 - single data rate ULPI interface with 8 bit wide data
20915 + * bus (default)
20916 + * 1 - double data rate ULPI interface with 4 bit wide data
20917 + * bus
20918 + */
20919 +extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if,
20920 +                                         int32_t val);
20921 +extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if);
20922 +#define dwc_param_phy_ulpi_ddr_default 0
20923 +
20924 +/**
20925 + * Specifies whether to use the internal or external supply to
20926 + * drive the vbus with a ULPI phy.
20927 + */
20928 +extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
20929 +                                              int32_t val);
20930 +extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if);
20931 +#define DWC_PHY_ULPI_INTERNAL_VBUS 0
20932 +#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
20933 +#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
20934 +
20935 +/**
20936 + * Specifies whether to use the I2Cinterface for full speed PHY. This
20937 + * parameter is only applicable if PHY_TYPE is FS.
20938 + * 0 - No (default)
20939 + * 1 - Yes
20940 + */
20941 +extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if,
20942 +                                       int32_t val);
20943 +extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if);
20944 +#define dwc_param_i2c_enable_default 0
20945 +
20946 +extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if,
20947 +                                       int32_t val);
20948 +extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if);
20949 +#define dwc_param_ulpi_fs_ls_default 0
20950 +
20951 +extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val);
20952 +extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if);
20953 +#define dwc_param_ts_dline_default 0
20954 +
20955 +/**
20956 + * Specifies whether dedicated transmit FIFOs are
20957 + * enabled for non periodic IN endpoints in device mode
20958 + * 0 - No
20959 + * 1 - Yes
20960 + */
20961 +extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
20962 +                                                int32_t val);
20963 +extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
20964 +                                                    core_if);
20965 +#define dwc_param_en_multiple_tx_fifo_default 1
20966 +
20967 +/** Number of 4-byte words in each of the Tx FIFOs in device
20968 + * mode when dynamic FIFO sizing is enabled.
20969 + * 4 to 768 (default 256)
20970 + */
20971 +extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
20972 +                                             int fifo_num, int32_t val);
20973 +extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
20974 +                                                 int fifo_num);
20975 +#define dwc_param_dev_tx_fifo_size_default 256
20976 +
20977 +/** Thresholding enable flag-
20978 + * bit 0 - enable non-ISO Tx thresholding
20979 + * bit 1 - enable ISO Tx thresholding
20980 + * bit 2 - enable Rx thresholding
20981 + */
20982 +extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val);
20983 +extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num);
20984 +#define dwc_param_thr_ctl_default 0
20985 +
20986 +/** Thresholding length for Tx
20987 + * FIFOs in 32 bit DWORDs
20988 + */
20989 +extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if,
20990 +                                          int32_t val);
20991 +extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if);
20992 +#define dwc_param_tx_thr_length_default 64
20993 +
20994 +/** Thresholding length for Rx
20995 + *     FIFOs in 32 bit DWORDs
20996 + */
20997 +extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if,
20998 +                                          int32_t val);
20999 +extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if);
21000 +#define dwc_param_rx_thr_length_default 64
21001 +
21002 +/**
21003 + * Specifies whether LPM (Link Power Management) support is enabled
21004 + */
21005 +extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if,
21006 +                                       int32_t val);
21007 +extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if);
21008 +#define dwc_param_lpm_enable_default 1
21009 +
21010 +/**
21011 + * Specifies whether PTI enhancement is enabled
21012 + */
21013 +extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if,
21014 +                                       int32_t val);
21015 +extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if);
21016 +#define dwc_param_pti_enable_default 0
21017 +
21018 +/**
21019 + * Specifies whether MPI enhancement is enabled
21020 + */
21021 +extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if,
21022 +                                       int32_t val);
21023 +extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if);
21024 +#define dwc_param_mpi_enable_default 0
21025 +
21026 +/**
21027 + * Specifies whether IC_USB capability is enabled
21028 + */
21029 +extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,
21030 +                                       int32_t val);
21031 +extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if);
21032 +#define dwc_param_ic_usb_cap_default 0
21033 +
21034 +extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val);
21035 +extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if);
21036 +#define dwc_param_ahb_thr_ratio_default 0
21037 +
21038 +/** @} */
21039 +
21040 +/** @name Access to registers and bit-fields */
21041 +
21042 +/**
21043 + * Dump core registers and SPRAM
21044 + */
21045 +extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if);
21046 +extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if);
21047 +extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if);
21048 +extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if);
21049 +
21050 +/**
21051 + * Get host negotiation status.
21052 + */
21053 +extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if);
21054 +
21055 +/**
21056 + * Get srp status
21057 + */
21058 +extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if);
21059 +
21060 +/**
21061 + * Set hnpreq bit in the GOTGCTL register.
21062 + */
21063 +extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val);
21064 +
21065 +/**
21066 + * Get Content of SNPSID register.
21067 + */
21068 +extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if);
21069 +
21070 +/**
21071 + * Get current mode.
21072 + * Returns 0 if in device mode, and 1 if in host mode.
21073 + */
21074 +extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if);
21075 +
21076 +/**
21077 + * Get value of hnpcapable field in the GUSBCFG register
21078 + */
21079 +extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if);
21080 +/**
21081 + * Set value of hnpcapable field in the GUSBCFG register
21082 + */
21083 +extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
21084 +
21085 +/**
21086 + * Get value of srpcapable field in the GUSBCFG register
21087 + */
21088 +extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if);
21089 +/**
21090 + * Set value of srpcapable field in the GUSBCFG register
21091 + */
21092 +extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
21093 +
21094 +/**
21095 + * Get value of devspeed field in the DCFG register
21096 + */
21097 +extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if);
21098 +/**
21099 + * Set value of devspeed field in the DCFG register
21100 + */
21101 +extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val);
21102 +
21103 +/**
21104 + * Get the value of busconnected field from the HPRT0 register
21105 + */
21106 +extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if);
21107 +
21108 +/**
21109 + * Gets the device enumeration Speed.
21110 + */
21111 +extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if);
21112 +
21113 +/**
21114 + * Get value of prtpwr field from the HPRT0 register
21115 + */
21116 +extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if);
21117 +/**
21118 + * Set value of prtpwr field from the HPRT0 register
21119 + */
21120 +extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val);
21121 +
21122 +/**
21123 + * Get value of prtsusp field from the HPRT0 regsiter
21124 + */
21125 +extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if);
21126 +/**
21127 + * Set value of prtpwr field from the HPRT0 register
21128 + */
21129 +extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val);
21130 +
21131 +/**
21132 + * Set value of prtres field from the HPRT0 register
21133 + *FIXME Remove?
21134 + */
21135 +extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val);
21136 +
21137 +/**
21138 + * Get value of rmtwkupsig bit in DCTL register
21139 + */
21140 +extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if);
21141 +
21142 +/**
21143 + * Get value of prt_sleep_sts field from the GLPMCFG register
21144 + */
21145 +extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if);
21146 +
21147 +/**
21148 + * Get value of rem_wkup_en field from the GLPMCFG register
21149 + */
21150 +extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if);
21151 +
21152 +/**
21153 + * Get value of appl_resp field from the GLPMCFG register
21154 + */
21155 +extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if);
21156 +/**
21157 + * Set value of appl_resp field from the GLPMCFG register
21158 + */
21159 +extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val);
21160 +
21161 +/**
21162 + * Get value of hsic_connect field from the GLPMCFG register
21163 + */
21164 +extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if);
21165 +/**
21166 + * Set value of hsic_connect field from the GLPMCFG register
21167 + */
21168 +extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val);
21169 +
21170 +/**
21171 + * Get value of inv_sel_hsic field from the GLPMCFG register.
21172 + */
21173 +extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if);
21174 +/**
21175 + * Set value of inv_sel_hsic field from the GLPMFG register.
21176 + */
21177 +extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val);
21178 +
21179 +/*
21180 + * Some functions for accessing registers
21181 + */
21182 +
21183 +/**
21184 + *  GOTGCTL register
21185 + */
21186 +extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if);
21187 +extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val);
21188 +
21189 +/**
21190 + * GUSBCFG register
21191 + */
21192 +extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if);
21193 +extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val);
21194 +
21195 +/**
21196 + * GRXFSIZ register
21197 + */
21198 +extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if);
21199 +extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
21200 +
21201 +/**
21202 + * GNPTXFSIZ register
21203 + */
21204 +extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if);
21205 +extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
21206 +
21207 +extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if);
21208 +extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val);
21209 +
21210 +/**
21211 + * GGPIO register
21212 + */
21213 +extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if);
21214 +extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val);
21215 +
21216 +/**
21217 + * GUID register
21218 + */
21219 +extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if);
21220 +extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val);
21221 +
21222 +/**
21223 + * HPRT0 register
21224 + */
21225 +extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if);
21226 +extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val);
21227 +
21228 +/**
21229 + * GHPTXFSIZE
21230 + */
21231 +extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if);
21232 +
21233 +/** @} */
21234 +
21235 +#endif                         /* __DWC_CORE_IF_H__ */
21236 --- /dev/null
21237 +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
21238 @@ -0,0 +1,113 @@
21239 +/* ==========================================================================
21240 + *
21241 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
21242 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
21243 + * otherwise expressly agreed to in writing between Synopsys and you.
21244 + * 
21245 + * The Software IS NOT an item of Licensed Software or Licensed Product under
21246 + * any End User Software License Agreement or Agreement for Licensed Product
21247 + * with Synopsys or any supplement thereto. You are permitted to use and
21248 + * redistribute this Software in source and binary forms, with or without
21249 + * modification, provided that redistributions of source code must retain this
21250 + * notice. You may not view, use, disclose, copy or distribute this file or
21251 + * any information contained herein except pursuant to this license grant from
21252 + * Synopsys. If you do not agree with this notice, including the disclaimer
21253 + * below, then you are not authorized to use the Software.
21254 + * 
21255 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
21256 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21257 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21258 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
21259 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21260 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21261 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21262 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21263 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21264 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
21265 + * DAMAGE.
21266 + * ========================================================================== */
21267 +
21268 +#ifndef __DWC_OTG_DBG_H__
21269 +#define __DWC_OTG_DBG_H__
21270 +
21271 +/** @file
21272 + * This file defines debug levels.
21273 + * Debugging support vanishes in non-debug builds.  
21274 + */
21275 +
21276 +/**
21277 + * The Debug Level bit-mask variable.
21278 + */
21279 +extern uint32_t g_dbg_lvl;
21280 +/**
21281 + * Set the Debug Level variable.
21282 + */
21283 +static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
21284 +{
21285 +       uint32_t old = g_dbg_lvl;
21286 +       g_dbg_lvl = new;
21287 +       return old;
21288 +}
21289 +
21290 +/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
21291 +#define DBG_CIL                (0x2)
21292 +/** When debug level has the DBG_CILV bit set, display CIL Verbose debug
21293 + * messages */
21294 +#define DBG_CILV       (0x20)
21295 +/**  When debug level has the DBG_PCD bit set, display PCD (Device) debug
21296 + *  messages */
21297 +#define DBG_PCD                (0x4)
21298 +/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug
21299 + * messages */
21300 +#define DBG_PCDV       (0x40)
21301 +/** When debug level has the DBG_HCD bit set, display Host debug messages */
21302 +#define DBG_HCD                (0x8)
21303 +/** When debug level has the DBG_HCDV bit set, display Verbose Host debug
21304 + * messages */
21305 +#define DBG_HCDV       (0x80)
21306 +/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host
21307 + *  mode. */
21308 +#define DBG_HCD_URB    (0x800)
21309 +
21310 +/** When debug level has any bit set, display debug messages */
21311 +#define DBG_ANY                (0xFF)
21312 +
21313 +/** All debug messages off */
21314 +#define DBG_OFF                0
21315 +
21316 +/** Prefix string for DWC_DEBUG print macros. */
21317 +#define USB_DWC "DWC_otg: "
21318 +
21319 +/** 
21320 + * Print a debug message when the Global debug level variable contains
21321 + * the bit defined in <code>lvl</code>.
21322 + *
21323 + * @param[in] lvl - Debug level, use one of the DBG_ constants above.
21324 + * @param[in] x - like printf
21325 + *
21326 + *    Example:<p>
21327 + * <code>
21328 + *      DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr);
21329 + * </code>
21330 + * <br>
21331 + * results in:<br> 
21332 + * <code>
21333 + * usb-DWC_otg: dwc_otg_cil_init(ca867000)
21334 + * </code>
21335 + */
21336 +#ifdef DEBUG
21337 +
21338 +# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0)
21339 +# define DWC_DEBUGP(x...)      DWC_DEBUGPL(DBG_ANY, x )
21340 +
21341 +# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl)
21342 +
21343 +#else
21344 +
21345 +# define DWC_DEBUGPL(lvl, x...) do{}while(0)
21346 +# define DWC_DEBUGP(x...)
21347 +
21348 +# define CHK_DEBUG_LEVEL(level) (0)
21349 +
21350 +#endif /*DEBUG*/
21351 +#endif
21352 --- /dev/null
21353 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
21354 @@ -0,0 +1,1577 @@
21355 +/* ==========================================================================
21356 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
21357 + * $Revision: #76 $
21358 + * $Date: 2009/05/03 $
21359 + * $Change: 1245589 $
21360 + *
21361 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
21362 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
21363 + * otherwise expressly agreed to in writing between Synopsys and you.
21364 + *
21365 + * The Software IS NOT an item of Licensed Software or Licensed Product under
21366 + * any End User Software License Agreement or Agreement for Licensed Product
21367 + * with Synopsys or any supplement thereto. You are permitted to use and
21368 + * redistribute this Software in source and binary forms, with or without
21369 + * modification, provided that redistributions of source code must retain this
21370 + * notice. You may not view, use, disclose, copy or distribute this file or
21371 + * any information contained herein except pursuant to this license grant from
21372 + * Synopsys. If you do not agree with this notice, including the disclaimer
21373 + * below, then you are not authorized to use the Software.
21374 + *
21375 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
21376 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21377 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21378 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
21379 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21380 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21381 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21382 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21383 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21384 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
21385 + * DAMAGE.
21386 + * ========================================================================== */
21387 +
21388 +/** @file
21389 + * The dwc_otg_driver module provides the initialization and cleanup entry
21390 + * points for the DWC_otg driver. This module will be dynamically installed
21391 + * after Linux is booted using the insmod command. When the module is
21392 + * installed, the dwc_otg_driver_init function is called. When the module is
21393 + * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
21394 + *
21395 + * This module also defines a data structure for the dwc_otg_driver, which is
21396 + * used in conjunction with the standard ARM lm_device structure. These
21397 + * structures allow the OTG driver to comply with the standard Linux driver
21398 + * model in which devices and drivers are registered with a bus driver. This
21399 + * has the benefit that Linux can expose attributes of the driver and device
21400 + * in its special sysfs file system. Users can then read or write files in
21401 + * this file system to perform diagnostics on the driver components or the
21402 + * device.
21403 + */
21404 +
21405 +#include <linux/kernel.h>
21406 +#include <linux/module.h>
21407 +#include <linux/moduleparam.h>
21408 +#include <linux/init.h>
21409 +#include <linux/device.h>
21410 +#include <linux/errno.h>
21411 +#include <linux/types.h>
21412 +#include <linux/stat.h>                /* permission constants */
21413 +#include <linux/version.h>
21414 +#include <linux/interrupt.h>
21415 +
21416 +#ifdef LM_INTERFACE
21417 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
21418 +#include <asm/arch/lm.h>
21419 +#include <asm/arch/hardware.h>
21420 +#else
21421 +/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -
21422 +   here we use definitions stolen from arm-integrator headers
21423 +*/
21424 +#include <mach/lm.h>
21425 +#include <mach/hardware.h>
21426 +#endif
21427 +#include <asm/sizes.h>
21428 +#include <asm/mach/map.h>
21429 +
21430 +#elif defined(PLATFORM_INTERFACE)
21431 +
21432 +#include <linux/platform_device.h>
21433 +#include <asm/mach/map.h>
21434 +
21435 +#endif
21436 +
21437 +# include <linux/irq.h>
21438 +
21439 +#include <asm/io.h>
21440 +
21441 +
21442 +#include "dwc_os.h"
21443 +#include "dwc_otg_dbg.h"
21444 +#include "dwc_otg_driver.h"
21445 +#include "dwc_otg_attr.h"
21446 +#include "dwc_otg_core_if.h"
21447 +#include "dwc_otg_pcd_if.h"
21448 +#include "dwc_otg_hcd_if.h"
21449 +
21450 +#define DWC_DRIVER_VERSION     "2.90b 6-MAY-2010"
21451 +#define DWC_DRIVER_DESC                "HS OTG USB Controller driver"
21452 +
21453 +static const char dwc_driver_name[] = "dwc_otg";
21454 +
21455 +extern int pcd_init(
21456 +#ifdef LM_INTERFACE
21457 +       struct lm_device *_dev
21458 +#elif  defined(PCI_INTERFACE)
21459 +       struct pci_dev *_dev
21460 +#elif  defined(PLATFORM_INTERFACE)
21461 +       struct platform_device *dev
21462 +#endif
21463 +        );
21464 +extern int hcd_init(
21465 +#ifdef LM_INTERFACE
21466 +       struct lm_device *_dev
21467 +#elif  defined(PCI_INTERFACE)
21468 +       struct pci_dev *_dev
21469 +#elif  defined(PLATFORM_INTERFACE)
21470 +       struct platform_device *dev
21471 +#endif
21472 +        );
21473 +
21474 +extern int pcd_remove(
21475 +#ifdef LM_INTERFACE
21476 +       struct lm_device *_dev
21477 +#elif  defined(PCI_INTERFACE)
21478 +       struct pci_dev *_dev
21479 +#elif  defined(PLATFORM_INTERFACE)
21480 +       struct platform_device *_dev
21481 +#endif
21482 +        );
21483 +
21484 +extern void hcd_remove(
21485 +#ifdef LM_INTERFACE
21486 +       struct lm_device *_dev
21487 +#elif  defined(PCI_INTERFACE)
21488 +       struct pci_dev *_dev
21489 +#elif  defined(PLATFORM_INTERFACE)
21490 +       struct platform_device *_dev
21491 +#endif
21492 +        );
21493 +
21494 +/*-------------------------------------------------------------------------*/
21495 +/* Encapsulate the module parameter settings */
21496 +
21497 +struct dwc_otg_driver_module_params {
21498 +       int32_t opt;
21499 +       int32_t otg_cap;
21500 +       int32_t dma_enable;
21501 +       int32_t dma_desc_enable;
21502 +       int32_t dma_burst_size;
21503 +       int32_t speed;
21504 +       int32_t host_support_fs_ls_low_power;
21505 +       int32_t host_ls_low_power_phy_clk;
21506 +       int32_t enable_dynamic_fifo;
21507 +       int32_t data_fifo_size;
21508 +       int32_t dev_rx_fifo_size;
21509 +       int32_t dev_nperio_tx_fifo_size;
21510 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
21511 +       int32_t host_rx_fifo_size;
21512 +       int32_t host_nperio_tx_fifo_size;
21513 +       int32_t host_perio_tx_fifo_size;
21514 +       int32_t max_transfer_size;
21515 +       int32_t max_packet_count;
21516 +       int32_t host_channels;
21517 +       int32_t dev_endpoints;
21518 +       int32_t phy_type;
21519 +       int32_t phy_utmi_width;
21520 +       int32_t phy_ulpi_ddr;
21521 +       int32_t phy_ulpi_ext_vbus;
21522 +       int32_t i2c_enable;
21523 +       int32_t ulpi_fs_ls;
21524 +       int32_t ts_dline;
21525 +       int32_t en_multiple_tx_fifo;
21526 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
21527 +       uint32_t thr_ctl;
21528 +       uint32_t tx_thr_length;
21529 +       uint32_t rx_thr_length;
21530 +       int32_t pti_enable;
21531 +       int32_t mpi_enable;
21532 +       int32_t lpm_enable;
21533 +       int32_t ic_usb_cap;
21534 +       int32_t ahb_thr_ratio;
21535 +};
21536 +
21537 +static struct dwc_otg_driver_module_params dwc_otg_module_params = {
21538 +       .opt = -1,
21539 +       .otg_cap = -1,
21540 +       .dma_enable = -1,
21541 +       .dma_desc_enable = -1,
21542 +       .dma_burst_size = -1,
21543 +       .speed = -1,
21544 +       .host_support_fs_ls_low_power = -1,
21545 +       .host_ls_low_power_phy_clk = -1,
21546 +       .enable_dynamic_fifo = -1,
21547 +       .data_fifo_size = -1,
21548 +       .dev_rx_fifo_size = -1,
21549 +       .dev_nperio_tx_fifo_size = -1,
21550 +       .dev_perio_tx_fifo_size = {
21551 +                                  /* dev_perio_tx_fifo_size_1 */
21552 +                                  -1,
21553 +                                  -1,
21554 +                                  -1,
21555 +                                  -1,
21556 +                                  -1,
21557 +                                  -1,
21558 +                                  -1,
21559 +                                  -1,
21560 +                                  -1,
21561 +                                  -1,
21562 +                                  -1,
21563 +                                  -1,
21564 +                                  -1,
21565 +                                  -1,
21566 +                                  -1
21567 +                                  /* 15 */
21568 +                                  },
21569 +       .host_rx_fifo_size = -1,
21570 +       .host_nperio_tx_fifo_size = -1,
21571 +       .host_perio_tx_fifo_size = -1,
21572 +       .max_transfer_size = -1,
21573 +       .max_packet_count = -1,
21574 +       .host_channels = -1,
21575 +       .dev_endpoints = -1,
21576 +       .phy_type = -1,
21577 +       .phy_utmi_width = -1,
21578 +       .phy_ulpi_ddr = -1,
21579 +       .phy_ulpi_ext_vbus = -1,
21580 +       .i2c_enable = -1,
21581 +       .ulpi_fs_ls = -1,
21582 +       .ts_dline = -1,
21583 +       .en_multiple_tx_fifo = -1,
21584 +       .dev_tx_fifo_size = {
21585 +                            /* dev_tx_fifo_size */
21586 +                            -1,
21587 +                            -1,
21588 +                            -1,
21589 +                            -1,
21590 +                            -1,
21591 +                            -1,
21592 +                            -1,
21593 +                            -1,
21594 +                            -1,
21595 +                            -1,
21596 +                            -1,
21597 +                            -1,
21598 +                            -1,
21599 +                            -1,
21600 +                            -1
21601 +                            /* 15 */
21602 +                            },
21603 +       .thr_ctl = -1,
21604 +       .tx_thr_length = -1,
21605 +       .rx_thr_length = -1,
21606 +       .pti_enable = -1,
21607 +       .mpi_enable = -1,
21608 +       .lpm_enable = -1,
21609 +       .ic_usb_cap = -1,
21610 +       .ahb_thr_ratio = -1,
21611 +};
21612 +
21613 +/**
21614 + * This function shows the Driver Version.
21615 + */
21616 +static ssize_t version_show(struct device_driver *dev, char *buf)
21617 +{
21618 +       return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n",
21619 +                       DWC_DRIVER_VERSION);
21620 +}
21621 +
21622 +static DRIVER_ATTR(version, S_IRUGO, version_show, NULL);
21623 +
21624 +/**
21625 + * Global Debug Level Mask.
21626 + */
21627 +uint32_t g_dbg_lvl = 0;                /* OFF */
21628 +
21629 +/**
21630 + * This function shows the driver Debug Level.
21631 + */
21632 +static ssize_t dbg_level_show(struct device_driver *drv, char *buf)
21633 +{
21634 +       return sprintf(buf, "0x%0x\n", g_dbg_lvl);
21635 +}
21636 +
21637 +/**
21638 + * This function stores the driver Debug Level.
21639 + */
21640 +static ssize_t dbg_level_store(struct device_driver *drv, const char *buf,
21641 +                              size_t count)
21642 +{
21643 +       g_dbg_lvl = simple_strtoul(buf, NULL, 16);
21644 +       return count;
21645 +}
21646 +
21647 +static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,
21648 +                  dbg_level_store);
21649 +
21650 +/**
21651 + * This function is called during module intialization
21652 + * to pass module parameters to the DWC_OTG CORE.
21653 + */
21654 +static int set_parameters(dwc_otg_core_if_t * core_if)
21655 +{
21656 +       int retval = 0;
21657 +       int i;
21658 +
21659 +       if (dwc_otg_module_params.otg_cap != -1) {
21660 +               retval +=
21661 +                   dwc_otg_set_param_otg_cap(core_if,
21662 +                                             dwc_otg_module_params.otg_cap);
21663 +       }
21664 +       if (dwc_otg_module_params.dma_enable != -1) {
21665 +               retval +=
21666 +                   dwc_otg_set_param_dma_enable(core_if,
21667 +                                                dwc_otg_module_params.
21668 +                                                dma_enable);
21669 +       }
21670 +       if (dwc_otg_module_params.dma_desc_enable != -1) {
21671 +               retval +=
21672 +                   dwc_otg_set_param_dma_desc_enable(core_if,
21673 +                                                     dwc_otg_module_params.
21674 +                                                     dma_desc_enable);
21675 +       }
21676 +       if (dwc_otg_module_params.opt != -1) {
21677 +               retval +=
21678 +                   dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt);
21679 +       }
21680 +       if (dwc_otg_module_params.dma_burst_size != -1) {
21681 +               retval +=
21682 +                   dwc_otg_set_param_dma_burst_size(core_if,
21683 +                                                    dwc_otg_module_params.
21684 +                                                    dma_burst_size);
21685 +       }
21686 +       if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) {
21687 +               retval +=
21688 +                   dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
21689 +                                                                  dwc_otg_module_params.
21690 +                                                                  host_support_fs_ls_low_power);
21691 +       }
21692 +       if (dwc_otg_module_params.enable_dynamic_fifo != -1) {
21693 +               retval +=
21694 +                   dwc_otg_set_param_enable_dynamic_fifo(core_if,
21695 +                                                         dwc_otg_module_params.
21696 +                                                         enable_dynamic_fifo);
21697 +       }
21698 +       if (dwc_otg_module_params.data_fifo_size != -1) {
21699 +               retval +=
21700 +                   dwc_otg_set_param_data_fifo_size(core_if,
21701 +                                                    dwc_otg_module_params.
21702 +                                                    data_fifo_size);
21703 +       }
21704 +       if (dwc_otg_module_params.dev_rx_fifo_size != -1) {
21705 +               retval +=
21706 +                   dwc_otg_set_param_dev_rx_fifo_size(core_if,
21707 +                                                      dwc_otg_module_params.
21708 +                                                      dev_rx_fifo_size);
21709 +       }
21710 +       if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) {
21711 +               retval +=
21712 +                   dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
21713 +                                                             dwc_otg_module_params.
21714 +                                                             dev_nperio_tx_fifo_size);
21715 +       }
21716 +       if (dwc_otg_module_params.host_rx_fifo_size != -1) {
21717 +               retval +=
21718 +                   dwc_otg_set_param_host_rx_fifo_size(core_if,
21719 +                                                       dwc_otg_module_params.host_rx_fifo_size);
21720 +       }
21721 +       if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) {
21722 +               retval +=
21723 +                   dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
21724 +                                                              dwc_otg_module_params.
21725 +                                                              host_nperio_tx_fifo_size);
21726 +       }
21727 +       if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) {
21728 +               retval +=
21729 +                   dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
21730 +                                                             dwc_otg_module_params.
21731 +                                                             host_perio_tx_fifo_size);
21732 +       }
21733 +       if (dwc_otg_module_params.max_transfer_size != -1) {
21734 +               retval +=
21735 +                   dwc_otg_set_param_max_transfer_size(core_if,
21736 +                                                       dwc_otg_module_params.
21737 +                                                       max_transfer_size);
21738 +       }
21739 +       if (dwc_otg_module_params.max_packet_count != -1) {
21740 +               retval +=
21741 +                   dwc_otg_set_param_max_packet_count(core_if,
21742 +                                                      dwc_otg_module_params.
21743 +                                                      max_packet_count);
21744 +       }
21745 +       if (dwc_otg_module_params.host_channels != -1) {
21746 +               retval +=
21747 +                   dwc_otg_set_param_host_channels(core_if,
21748 +                                                   dwc_otg_module_params.
21749 +                                                   host_channels);
21750 +       }
21751 +       if (dwc_otg_module_params.dev_endpoints != -1) {
21752 +               retval +=
21753 +                   dwc_otg_set_param_dev_endpoints(core_if,
21754 +                                                   dwc_otg_module_params.
21755 +                                                   dev_endpoints);
21756 +       }
21757 +       if (dwc_otg_module_params.phy_type != -1) {
21758 +               retval +=
21759 +                   dwc_otg_set_param_phy_type(core_if,
21760 +                                              dwc_otg_module_params.phy_type);
21761 +       }
21762 +       if (dwc_otg_module_params.speed != -1) {
21763 +               retval +=
21764 +                   dwc_otg_set_param_speed(core_if,
21765 +                                           dwc_otg_module_params.speed);
21766 +       }
21767 +       if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) {
21768 +               retval +=
21769 +                   dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
21770 +                                                               dwc_otg_module_params.
21771 +                                                               host_ls_low_power_phy_clk);
21772 +       }
21773 +       if (dwc_otg_module_params.phy_ulpi_ddr != -1) {
21774 +               retval +=
21775 +                   dwc_otg_set_param_phy_ulpi_ddr(core_if,
21776 +                                                  dwc_otg_module_params.
21777 +                                                  phy_ulpi_ddr);
21778 +       }
21779 +       if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) {
21780 +               retval +=
21781 +                   dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
21782 +                                                       dwc_otg_module_params.
21783 +                                                       phy_ulpi_ext_vbus);
21784 +       }
21785 +       if (dwc_otg_module_params.phy_utmi_width != -1) {
21786 +               retval +=
21787 +                   dwc_otg_set_param_phy_utmi_width(core_if,
21788 +                                                    dwc_otg_module_params.
21789 +                                                    phy_utmi_width);
21790 +       }
21791 +       if (dwc_otg_module_params.ulpi_fs_ls != -1) {
21792 +               retval +=
21793 +                   dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_otg_module_params.ulpi_fs_ls);
21794 +       }
21795 +       if (dwc_otg_module_params.ts_dline != -1) {
21796 +               retval +=
21797 +                   dwc_otg_set_param_ts_dline(core_if,
21798 +                                              dwc_otg_module_params.ts_dline);
21799 +       }
21800 +       if (dwc_otg_module_params.i2c_enable != -1) {
21801 +               retval +=
21802 +                   dwc_otg_set_param_i2c_enable(core_if,
21803 +                                                dwc_otg_module_params.
21804 +                                                i2c_enable);
21805 +       }
21806 +       if (dwc_otg_module_params.en_multiple_tx_fifo != -1) {
21807 +               retval +=
21808 +                   dwc_otg_set_param_en_multiple_tx_fifo(core_if,
21809 +                                                         dwc_otg_module_params.
21810 +                                                         en_multiple_tx_fifo);
21811 +       }
21812 +       for (i = 0; i < 15; i++) {
21813 +               if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {
21814 +                       retval +=
21815 +                           dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
21816 +                                                                    dwc_otg_module_params.
21817 +                                                                    dev_perio_tx_fifo_size
21818 +                                                                    [i], i);
21819 +               }
21820 +       }
21821 +
21822 +       for (i = 0; i < 15; i++) {
21823 +               if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {
21824 +                       retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
21825 +                                                                    dwc_otg_module_params.
21826 +                                                                    dev_tx_fifo_size
21827 +                                                                    [i], i);
21828 +               }
21829 +       }
21830 +       if (dwc_otg_module_params.thr_ctl != -1) {
21831 +               retval +=
21832 +                   dwc_otg_set_param_thr_ctl(core_if,
21833 +                                             dwc_otg_module_params.thr_ctl);
21834 +       }
21835 +       if (dwc_otg_module_params.mpi_enable != -1) {
21836 +               retval +=
21837 +                   dwc_otg_set_param_mpi_enable(core_if,
21838 +                                                dwc_otg_module_params.
21839 +                                                mpi_enable);
21840 +       }
21841 +       if (dwc_otg_module_params.pti_enable != -1) {
21842 +               retval +=
21843 +                   dwc_otg_set_param_pti_enable(core_if,
21844 +                                                dwc_otg_module_params.
21845 +                                                pti_enable);
21846 +       }
21847 +       if (dwc_otg_module_params.lpm_enable != -1) {
21848 +               retval +=
21849 +                   dwc_otg_set_param_lpm_enable(core_if,
21850 +                                                dwc_otg_module_params.
21851 +                                                lpm_enable);
21852 +       }
21853 +       if (dwc_otg_module_params.ic_usb_cap != -1) {
21854 +               retval +=
21855 +                   dwc_otg_set_param_ic_usb_cap(core_if,
21856 +                                                dwc_otg_module_params.
21857 +                                                ic_usb_cap);
21858 +       }
21859 +       if (dwc_otg_module_params.tx_thr_length != -1) {
21860 +               retval +=
21861 +                   dwc_otg_set_param_tx_thr_length(core_if,
21862 +                                                   dwc_otg_module_params.tx_thr_length);
21863 +       }
21864 +       if (dwc_otg_module_params.rx_thr_length != -1) {
21865 +               retval +=
21866 +                   dwc_otg_set_param_rx_thr_length(core_if,
21867 +                                                   dwc_otg_module_params.
21868 +                                                   rx_thr_length);
21869 +       }
21870 +       if(dwc_otg_module_params.ahb_thr_ratio != -1) {
21871 +               retval +=
21872 +                   dwc_otg_set_param_ahb_thr_ratio(core_if, dwc_otg_module_params.ahb_thr_ratio);
21873 +       }
21874 +       return retval;
21875 +}
21876 +
21877 +/**
21878 + * This function is the top level interrupt handler for the Common
21879 + * (Device and host modes) interrupts.
21880 + */
21881 +static irqreturn_t dwc_otg_common_irq(int irq, void *dev)
21882 +{
21883 +       dwc_otg_device_t *otg_dev = dev;
21884 +       int32_t retval = IRQ_NONE;
21885 +
21886 +       retval = dwc_otg_handle_common_intr(otg_dev->core_if);
21887 +       if (retval != 0) {
21888 +               S3C2410X_CLEAR_EINTPEND();
21889 +       }
21890 +       return IRQ_RETVAL(retval);
21891 +}
21892 +
21893 +/**
21894 + * This function is called when a lm_device is unregistered with the
21895 + * dwc_otg_driver. This happens, for example, when the rmmod command is
21896 + * executed. The device may or may not be electrically present. If it is
21897 + * present, the driver stops device processing. Any resources used on behalf
21898 + * of this device are freed.
21899 + *
21900 + * @param _dev
21901 + */
21902 +#ifdef LM_INTERFACE
21903 +static void dwc_otg_driver_remove(
21904 +     struct lm_device *_dev
21905 +#elif  defined(PCI_INTERFACE)
21906 +static void dwc_otg_driver_remove(
21907 +     struct pci_dev *_dev
21908 +#elif  defined(PLATFORM_INTERFACE)
21909 +static int dwc_otg_driver_remove(
21910 +     struct platform_device *_dev
21911 +#endif
21912 +)
21913 +
21914 +{
21915 +#ifdef LM_INTERFACE
21916 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
21917 +#elif  defined(PCI_INTERFACE)
21918 +       dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
21919 +#elif  defined(PLATFORM_INTERFACE)
21920 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
21921 +#endif
21922 +
21923 +
21924 +       DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
21925 +
21926 +       if (!otg_dev) {
21927 +               /* Memory allocation for the dwc_otg_device failed. */
21928 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
21929 +#ifdef PLATFORM_INTERFACE
21930 +                return -ENOMEM;
21931 +#else
21932 +               return;
21933 +#endif
21934 +       }
21935 +#ifndef DWC_DEVICE_ONLY
21936 +       if (otg_dev->hcd) {
21937 +               hcd_remove(_dev);
21938 +       } else {
21939 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
21940 +#ifdef PLATFORM_INTERFACE
21941 +                return -EINVAL;
21942 +#else
21943 +               return;
21944 +#endif
21945 +       }
21946 +#endif
21947 +
21948 +#ifndef DWC_HOST_ONLY
21949 +       if (otg_dev->pcd) {
21950 +               pcd_remove(_dev);
21951 +       }
21952 +#endif
21953 +       /*
21954 +        * Free the IRQ
21955 +        */
21956 +       if (otg_dev->common_irq_installed) {
21957 +#ifdef PLATFORM_INTERFACE
21958 +               free_irq(platform_get_irq(_dev, 0), otg_dev);
21959 +#else
21960 +               free_irq(_dev->irq, otg_dev);
21961 +#endif
21962 +       }
21963 +
21964 +       if (otg_dev->core_if) {
21965 +               dwc_otg_cil_remove(otg_dev->core_if);
21966 +       }
21967 +
21968 +       /*
21969 +        * Remove the device attributes
21970 +        */
21971 +       dwc_otg_attr_remove(_dev);
21972 +
21973 +       /*
21974 +        * Return the memory.
21975 +        */
21976 +       if (otg_dev->base) {
21977 +               iounmap(otg_dev->base);
21978 +       }
21979 +       dwc_free(otg_dev);
21980 +
21981 +       /*
21982 +        * Clear the drvdata pointer.
21983 +        */
21984 +#ifdef LM_INTERFACE
21985 +       lm_set_drvdata(_dev, 0);
21986 +#elif  defined(PCI_INTERFACE)
21987 +        release_mem_region(otg_dev->rsrc_start, otg_dev->rsrc_len);
21988 +        pci_set_drvdata(_dev, 0);
21989 +#elif  defined(PLATFORM_INTERFACE)
21990 +        platform_set_drvdata(_dev, 0);
21991 +        return 0;
21992 +#endif
21993 +}
21994 +
21995 +/**
21996 + * This function is called when an lm_device is bound to a
21997 + * dwc_otg_driver. It creates the driver components required to
21998 + * control the device (CIL, HCD, and PCD) and it initializes the
21999 + * device. The driver components are stored in a dwc_otg_device
22000 + * structure. A reference to the dwc_otg_device is saved in the
22001 + * lm_device. This allows the driver to access the dwc_otg_device
22002 + * structure on subsequent calls to driver methods for this device.
22003 + *
22004 + * @param _dev Bus device
22005 + */
22006 +static int dwc_otg_driver_probe(
22007 +#ifdef LM_INTERFACE
22008 +struct lm_device *_dev
22009 +#elif  defined(PCI_INTERFACE)
22010 +struct pci_dev *_dev,  const struct pci_device_id *id
22011 +#elif  defined(PLATFORM_INTERFACE)
22012 +struct platform_device *_dev
22013 +#endif
22014 +)
22015 +{
22016 +       int retval = 0;
22017 +       dwc_otg_device_t *dwc_otg_device;
22018 +        int devirq;
22019 +
22020 +       dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev);
22021 +#ifdef LM_INTERFACE
22022 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start);
22023 +#elif  defined(PCI_INTERFACE)
22024 +       if (!id) {
22025 +                DWC_ERROR("Invalid pci_device_id %p", id);
22026 +               return -EINVAL;
22027 +       }
22028 +
22029 +       if (!_dev || (pci_enable_device(_dev) < 0)) {
22030 +               DWC_ERROR("Invalid pci_device %p", _dev);
22031 +               return -ENODEV;
22032 +       }
22033 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));
22034 +       /* other stuff needed as well? */
22035 +        
22036 +#elif  defined(PLATFORM_INTERFACE)
22037 +       dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n",
22038 +                (unsigned)_dev->resource->start,
22039 +                (unsigned)(_dev->resource->end - _dev->resource->start));
22040 +#endif
22041 +
22042 +
22043 +       dwc_otg_device = dwc_alloc(sizeof(dwc_otg_device_t));
22044 +
22045 +       if (!dwc_otg_device) {
22046 +               dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");
22047 +               retval = -ENOMEM;
22048 +               goto fail;
22049 +       }
22050 +
22051 +       memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
22052 +       dwc_otg_device->reg_offset = 0xFFFFFFFF;
22053 +
22054 +       /*
22055 +        * Map the DWC_otg Core memory into virtual address space.
22056 +        */
22057 +#ifdef LM_INTERFACE
22058 +#if 1
22059 +       dwc_otg_device->base = ioremap(_dev->resource.start, SZ_256K);
22060 +#else
22061 +       struct map_desc desc = {
22062 +           .virtual = IO_ADDRESS((unsigned)_dev->resource.start),
22063 +           .pfn     = __phys_to_pfn((unsigned)_dev->resource.start),
22064 +           .length  = SZ_128K,
22065 +           .type    = MT_DEVICE
22066 +       };
22067 +       iotable_init(&desc, 1);
22068 +       dwc_otg_device->base = (void *)desc.virtual;
22069 +#endif
22070 +
22071 +       if (!dwc_otg_device->base) {
22072 +               dev_err(&_dev->dev, "ioremap() failed\n");
22073 +               retval = -ENOMEM;
22074 +               goto fail;
22075 +       }
22076 +       dev_dbg(&_dev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base);
22077 +#elif  defined(PCI_INTERFACE)
22078 +       _dev->current_state = PCI_D0;
22079 +       _dev->dev.power.power_state = PMSG_ON;
22080 +       
22081 +       if (!_dev->irq) {
22082 +                DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!", pci_name(_dev));
22083 +                retval = -ENODEV;
22084 +                goto fail;
22085 +        }
22086 +
22087 +        dwc_otg_device->rsrc_start = pci_resource_start(_dev,0);
22088 +        dwc_otg_device->rsrc_len = pci_resource_len(_dev,0);
22089 +        DWC_DEBUGPL(DBG_ANY,"PCI resource: start=%08x, len=%08x\n",
22090 +                    dwc_otg_device->rsrc_start,
22091 +                    dwc_otg_device->rsrc_len);
22092 +        if (!request_mem_region(dwc_otg_device->rsrc_start, dwc_otg_device->rsrc_len, "dwc_otg")) {
22093 +          dev_dbg(&_dev->dev, "error mapping memory\n");
22094 +          retval = -EFAULT;
22095 +          goto fail;
22096 +        }
22097 +
22098 +        dwc_otg_device->base = ioremap_nocache(dwc_otg_device->rsrc_start, dwc_otg_device->rsrc_len);
22099 +        if (dwc_otg_device->base == NULL) {
22100 +                dev_dbg(&_dev->dev, "error mapping memory\n");
22101 +                retval = -EFAULT;
22102 +                goto fail;
22103 +        }
22104 +        dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n", dwc_otg_device->base);
22105 +        dwc_otg_device->base = (char *)dwc_otg_device->base;
22106 +        dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n", dwc_otg_device->base);
22107 +        dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__,
22108 +                (unsigned)dwc_otg_device->rsrc_start, dwc_otg_device->base);
22109 +        //
22110 +        pci_set_drvdata(_dev, dwc_otg_device); 
22111 +        pci_set_master(_dev);
22112 +#elif defined(PLATFORM_INTERFACE)
22113 +        DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n",
22114 +                    _dev->resource->start,
22115 +                    _dev->resource->end - _dev->resource->start + 1);
22116 +#if 1
22117 +        if (!request_mem_region(_dev->resource->start,
22118 +                                _dev->resource->end - _dev->resource->start + 1,
22119 +                                "dwc_otg")) {
22120 +          dev_dbg(&_dev->dev, "error reserving mapped memory\n");
22121 +          retval = -EFAULT;
22122 +          goto fail;
22123 +        }
22124 +
22125 +       dwc_otg_device->base = ioremap_nocache(_dev->resource->start,
22126 +                                               _dev->resource->end -
22127 +                                               _dev->resource->start + 1);
22128 +#else
22129 +        {
22130 +                struct map_desc desc = {
22131 +                    .virtual = IO_ADDRESS((unsigned)_dev->resource->start),
22132 +                    .pfn     = __phys_to_pfn((unsigned)_dev->resource->start),
22133 +                    .length  = SZ_128K,
22134 +                    .type    = MT_DEVICE
22135 +                };
22136 +                iotable_init(&desc, 1);
22137 +                dwc_otg_device->base = (void *)desc.virtual;
22138 +        }
22139 +#endif
22140 +       if (!dwc_otg_device->base) {
22141 +               dev_err(&_dev->dev, "ioremap() failed\n");
22142 +               retval = -ENOMEM;
22143 +               goto fail;
22144 +       }
22145 +       dev_dbg(&_dev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base);
22146 +#endif
22147 +
22148 +       /*
22149 +        * Initialize driver data to point to the global DWC_otg
22150 +        * Device structure.
22151 +        */
22152 +#ifdef LM_INTERFACE
22153 +       lm_set_drvdata(_dev, dwc_otg_device);
22154 +#elif defined(PLATFORM_INTERFACE)
22155 +       platform_set_drvdata(_dev, dwc_otg_device);
22156 +#endif
22157 +       dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
22158 +
22159 +       dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->base);
22160 +        DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n",
22161 +                    dwc_otg_device, dwc_otg_device->core_if);//GRAYG
22162 +        
22163 +       if (!dwc_otg_device->core_if) {
22164 +               dev_err(&_dev->dev, "CIL initialization failed!\n");
22165 +               retval = -ENOMEM;
22166 +               goto fail;
22167 +       }
22168 +
22169 +       dev_dbg(&_dev->dev, "Calling get_gsnpsid\n");
22170 +       /*
22171 +        * Attempt to ensure this device is really a DWC_otg Controller.
22172 +        * Read and verify the SNPSID register contents. The value should be
22173 +        * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX".
22174 +        */
22175 +
22176 +       if ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=
22177 +           0x4F542000) {
22178 +               dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
22179 +                       dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
22180 +               dwc_otg_cil_remove(dwc_otg_device->core_if);
22181 +               dwc_free(dwc_otg_device);
22182 +               retval = -EINVAL;
22183 +               goto fail;
22184 +       }
22185 +
22186 +       /*
22187 +        * Validate parameter values.
22188 +        */
22189 +       dev_dbg(&_dev->dev, "Calling set_parameters\n");
22190 +       if (set_parameters(dwc_otg_device->core_if)) {
22191 +               dwc_otg_cil_remove(dwc_otg_device->core_if);
22192 +               retval = -EINVAL;
22193 +               goto fail;
22194 +       }
22195 +
22196 +       /*
22197 +        * Create Device Attributes in sysfs
22198 +        */
22199 +       dev_dbg(&_dev->dev, "Calling attr_create\n");
22200 +       dwc_otg_attr_create(_dev);
22201 +
22202 +       /*
22203 +        * Disable the global interrupt until all the interrupt
22204 +        * handlers are installed.
22205 +        */
22206 +       dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n");
22207 +       dwc_otg_disable_global_interrupts(dwc_otg_device->core_if);
22208 +
22209 +       /*
22210 +        * Install the interrupt handler for the common interrupts before
22211 +        * enabling common interrupts in core_init below.
22212 +        */
22213 +#if defined(PLATFORM_INTERFACE)
22214 +        devirq = platform_get_irq(_dev, 0);
22215 +#else
22216 +        devirq = _dev->irq;
22217 +#endif
22218 +       DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
22219 +                   devirq);
22220 +       dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);
22221 +       retval = request_irq(devirq, dwc_otg_common_irq,
22222 +                             IRQF_SHARED,
22223 +                             "dwc_otg", dwc_otg_device);
22224 +       if (retval) {
22225 +               DWC_ERROR("request of irq%d failed\n", devirq);
22226 +               retval = -EBUSY;
22227 +               goto fail;
22228 +       } else {
22229 +               dwc_otg_device->common_irq_installed = 1;
22230 +       }
22231 +
22232 +#ifndef IRQF_TRIGGER_LOW
22233 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
22234 +       dev_dbg(&_dev->dev, "Calling set_irq_type\n");
22235 +       set_irq_type(devirq,
22236 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
22237 +                     IRQT_LOW
22238 +#else
22239 +                     IRQ_TYPE_LEVEL_LOW
22240 +#endif
22241 +                    );
22242 +#endif
22243 +#endif /*IRQF_TRIGGER_LOW*/
22244 +
22245 +       /*
22246 +        * Initialize the DWC_otg core.
22247 +        */
22248 +       dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n");
22249 +       dwc_otg_core_init(dwc_otg_device->core_if);
22250 +
22251 +#ifndef DWC_HOST_ONLY
22252 +       /*
22253 +        * Initialize the PCD
22254 +        */
22255 +       dev_dbg(&_dev->dev, "Calling pcd_init\n");
22256 +       retval = pcd_init(_dev);
22257 +       if (retval != 0) {
22258 +               DWC_ERROR("pcd_init failed\n");
22259 +               dwc_otg_device->pcd = NULL;
22260 +               goto fail;
22261 +       }
22262 +#endif
22263 +#ifndef DWC_DEVICE_ONLY
22264 +       /*
22265 +        * Initialize the HCD
22266 +        */
22267 +       dev_dbg(&_dev->dev, "Calling hcd_init\n");
22268 +       retval = hcd_init(_dev);
22269 +       if (retval != 0) {
22270 +               DWC_ERROR("hcd_init failed\n");
22271 +               dwc_otg_device->hcd = NULL;
22272 +               goto fail;
22273 +       }
22274 +#endif
22275 +        /* Recover from drvdata having been overwritten by hcd_init() */
22276 +#ifdef LM_INTERFACE
22277 +       lm_set_drvdata(_dev, dwc_otg_device);
22278 +#elif defined(PLATFORM_INTERFACE)
22279 +       platform_set_drvdata(_dev, dwc_otg_device);
22280 +#elif defined(PCI_INTERFACE)
22281 +       pci_set_drvdata(_dev, dwc_otg_device);
22282 +#endif
22283 +
22284 +       /*
22285 +        * Enable the global interrupt after all the interrupt
22286 +        * handlers are installed.
22287 +        */
22288 +       dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n");
22289 +       dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
22290 +       dev_dbg(&_dev->dev, "Done\n");
22291 +
22292 +       return 0;
22293 +
22294 +      fail:
22295 +       dwc_otg_driver_remove(_dev);
22296 +       return retval;
22297 +}
22298 +
22299 +/**
22300 + * This structure defines the methods to be called by a bus driver
22301 + * during the lifecycle of a device on that bus. Both drivers and
22302 + * devices are registered with a bus driver. The bus driver matches
22303 + * devices to drivers based on information in the device and driver
22304 + * structures.
22305 + *
22306 + * The probe function is called when the bus driver matches a device
22307 + * to this driver. The remove function is called when a device is
22308 + * unregistered with the bus driver.
22309 + */
22310 +#ifdef LM_INTERFACE
22311 +static struct lm_driver dwc_otg_driver = {
22312 +       .drv = {
22313 +               .name = (char *)dwc_driver_name,
22314 +               },
22315 +       .probe = dwc_otg_driver_probe,
22316 +       .remove = dwc_otg_driver_remove,
22317 +        // 'suspend' and 'resume' absent
22318 +};
22319 +#elif defined(PCI_INTERFACE)
22320 +static const struct pci_device_id pci_ids[] = { {
22321 +        PCI_DEVICE(0x16c3, 0xabcd),
22322 +        .driver_data = (unsigned long) 0xdeadbeef,
22323 +        }, { /* end: all zeroes */ }
22324 +};
22325 +MODULE_DEVICE_TABLE(pci, pci_ids);
22326 +
22327 +/* pci driver glue; this is a "new style" PCI driver module */
22328 +static struct pci_driver dwc_otg_driver = {
22329 +        .name =         "dwc_otg",
22330 +        .id_table =     pci_ids,
22331 +
22332 +        .probe =        dwc_otg_driver_probe,
22333 +        .remove =       dwc_otg_driver_remove,
22334 +
22335 +        .driver = {
22336 +                .name   = (char*)dwc_driver_name,
22337 +        },
22338 +};
22339 +#elif defined(PLATFORM_INTERFACE)
22340 +static struct platform_device_id platform_ids[] = {
22341 +        {
22342 +              .name = "bcm2708_usb",
22343 +              .driver_data = (kernel_ulong_t) 0xdeadbeef,
22344 +        },
22345 +        { /* end: all zeroes */ }
22346 +};
22347 +MODULE_DEVICE_TABLE(platform, platform_ids);
22348 +
22349 +static struct platform_driver dwc_otg_driver = {
22350 +       .driver = {
22351 +               .name = (char *)dwc_driver_name,
22352 +               },
22353 +        .id_table = platform_ids,
22354 +                        
22355 +       .probe = dwc_otg_driver_probe,
22356 +       .remove = dwc_otg_driver_remove,
22357 +        // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early' 
22358 +};
22359 +#endif
22360 +
22361 +
22362 +/**
22363 + * This function is called when the dwc_otg_driver is installed with the
22364 + * insmod command. It registers the dwc_otg_driver structure with the
22365 + * appropriate bus driver. This will cause the dwc_otg_driver_probe function
22366 + * to be called. In addition, the bus driver will automatically expose
22367 + * attributes defined for the device and driver in the special sysfs file
22368 + * system.
22369 + *
22370 + * @return
22371 + */
22372 +static int __init dwc_otg_driver_init(void)
22373 +{
22374 +       int retval = 0;
22375 +       int error;
22376 +       printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
22377 +              DWC_DRIVER_VERSION,
22378 +#ifdef LM_INTERFACE
22379 +               "logicmodule");
22380 +       retval = lm_driver_register(&dwc_otg_driver);
22381 +#elif defined(PCI_INTERFACE)
22382 +               "pci");
22383 +       retval = pci_register_driver(&dwc_otg_driver);
22384 +#elif defined(PLATFORM_INTERFACE)
22385 +               "platform");
22386 +       retval = platform_driver_register(&dwc_otg_driver);
22387 +#endif
22388 +       if (retval < 0) {
22389 +               printk(KERN_ERR "%s retval=%d\n", __func__, retval);
22390 +               return retval;
22391 +       }
22392 +#ifdef LM_INTERFACE
22393 +       error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_version);
22394 +       error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);
22395 +#elif defined(PCI_INTERFACE)
22396 +       error = driver_create_file(&dwc_otg_driver.driver,
22397 +                                   &driver_attr_version);
22398 +       error = driver_create_file(&dwc_otg_driver.driver,
22399 +                                   &driver_attr_debuglevel);
22400 +#elif defined(PLATFORM_INTERFACE)
22401 +       error = driver_create_file(&dwc_otg_driver.driver,
22402 +                                   &driver_attr_version);
22403 +       error = driver_create_file(&dwc_otg_driver.driver,
22404 +                                   &driver_attr_debuglevel);
22405 +#endif
22406 +       return retval;
22407 +}
22408 +
22409 +module_init(dwc_otg_driver_init);
22410 +
22411 +/**
22412 + * This function is called when the driver is removed from the kernel
22413 + * with the rmmod command. The driver unregisters itself with its bus
22414 + * driver.
22415 + *
22416 + */
22417 +static void __exit dwc_otg_driver_cleanup(void)
22418 +{
22419 +       printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");
22420 +
22421 +#ifdef LM_INTERFACE
22422 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);
22423 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version);
22424 +       lm_driver_unregister(&dwc_otg_driver);
22425 +#elif defined(PCI_INTERFACE)
22426 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
22427 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
22428 +       pci_unregister_driver(&dwc_otg_driver);
22429 +#elif defined(PLATFORM_INTERFACE)
22430 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
22431 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
22432 +       platform_driver_unregister(&dwc_otg_driver);
22433 +#endif
22434 +
22435 +       printk(KERN_INFO "%s module removed\n", dwc_driver_name);
22436 +}
22437 +module_exit(dwc_otg_driver_cleanup);
22438 +
22439 +MODULE_DESCRIPTION(DWC_DRIVER_DESC);
22440 +MODULE_AUTHOR("Synopsys Inc.");
22441 +MODULE_LICENSE("GPL");
22442 +
22443 +module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);
22444 +MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");
22445 +module_param_named(opt, dwc_otg_module_params.opt, int, 0444);
22446 +MODULE_PARM_DESC(opt, "OPT Mode");
22447 +module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);
22448 +MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");
22449 +
22450 +module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int,
22451 +                  0444);
22452 +MODULE_PARM_DESC(dma_desc_enable,
22453 +                "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");
22454 +
22455 +module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int,
22456 +                  0444);
22457 +MODULE_PARM_DESC(dma_burst_size,
22458 +                "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");
22459 +module_param_named(speed, dwc_otg_module_params.speed, int, 0444);
22460 +MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");
22461 +module_param_named(host_support_fs_ls_low_power,
22462 +                  dwc_otg_module_params.host_support_fs_ls_low_power, int,
22463 +                  0444);
22464 +MODULE_PARM_DESC(host_support_fs_ls_low_power,
22465 +                "Support Low Power w/FS or LS 0=Support 1=Don't Support");
22466 +module_param_named(host_ls_low_power_phy_clk,
22467 +                  dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);
22468 +MODULE_PARM_DESC(host_ls_low_power_phy_clk,
22469 +                "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");
22470 +module_param_named(enable_dynamic_fifo,
22471 +                  dwc_otg_module_params.enable_dynamic_fifo, int, 0444);
22472 +MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");
22473 +module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int,
22474 +                  0444);
22475 +MODULE_PARM_DESC(data_fifo_size,
22476 +                "Total number of words in the data FIFO memory 32-32768");
22477 +module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size,
22478 +                  int, 0444);
22479 +MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
22480 +module_param_named(dev_nperio_tx_fifo_size,
22481 +                  dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);
22482 +MODULE_PARM_DESC(dev_nperio_tx_fifo_size,
22483 +                "Number of words in the non-periodic Tx FIFO 16-32768");
22484 +module_param_named(dev_perio_tx_fifo_size_1,
22485 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);
22486 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_1,
22487 +                "Number of words in the periodic Tx FIFO 4-768");
22488 +module_param_named(dev_perio_tx_fifo_size_2,
22489 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);
22490 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_2,
22491 +                "Number of words in the periodic Tx FIFO 4-768");
22492 +module_param_named(dev_perio_tx_fifo_size_3,
22493 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);
22494 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_3,
22495 +                "Number of words in the periodic Tx FIFO 4-768");
22496 +module_param_named(dev_perio_tx_fifo_size_4,
22497 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);
22498 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_4,
22499 +                "Number of words in the periodic Tx FIFO 4-768");
22500 +module_param_named(dev_perio_tx_fifo_size_5,
22501 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);
22502 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_5,
22503 +                "Number of words in the periodic Tx FIFO 4-768");
22504 +module_param_named(dev_perio_tx_fifo_size_6,
22505 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);
22506 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_6,
22507 +                "Number of words in the periodic Tx FIFO 4-768");
22508 +module_param_named(dev_perio_tx_fifo_size_7,
22509 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);
22510 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_7,
22511 +                "Number of words in the periodic Tx FIFO 4-768");
22512 +module_param_named(dev_perio_tx_fifo_size_8,
22513 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);
22514 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_8,
22515 +                "Number of words in the periodic Tx FIFO 4-768");
22516 +module_param_named(dev_perio_tx_fifo_size_9,
22517 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);
22518 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_9,
22519 +                "Number of words in the periodic Tx FIFO 4-768");
22520 +module_param_named(dev_perio_tx_fifo_size_10,
22521 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);
22522 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_10,
22523 +                "Number of words in the periodic Tx FIFO 4-768");
22524 +module_param_named(dev_perio_tx_fifo_size_11,
22525 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);
22526 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_11,
22527 +                "Number of words in the periodic Tx FIFO 4-768");
22528 +module_param_named(dev_perio_tx_fifo_size_12,
22529 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444);
22530 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_12,
22531 +                "Number of words in the periodic Tx FIFO 4-768");
22532 +module_param_named(dev_perio_tx_fifo_size_13,
22533 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444);
22534 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_13,
22535 +                "Number of words in the periodic Tx FIFO 4-768");
22536 +module_param_named(dev_perio_tx_fifo_size_14,
22537 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444);
22538 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_14,
22539 +                "Number of words in the periodic Tx FIFO 4-768");
22540 +module_param_named(dev_perio_tx_fifo_size_15,
22541 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444);
22542 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_15,
22543 +                "Number of words in the periodic Tx FIFO 4-768");
22544 +module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size,
22545 +                  int, 0444);
22546 +MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
22547 +module_param_named(host_nperio_tx_fifo_size,
22548 +                  dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444);
22549 +MODULE_PARM_DESC(host_nperio_tx_fifo_size,
22550 +                "Number of words in the non-periodic Tx FIFO 16-32768");
22551 +module_param_named(host_perio_tx_fifo_size,
22552 +                  dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444);
22553 +MODULE_PARM_DESC(host_perio_tx_fifo_size,
22554 +                "Number of words in the host periodic Tx FIFO 16-32768");
22555 +module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size,
22556 +                  int, 0444);
22557 +/** @todo Set the max to 512K, modify checks */
22558 +MODULE_PARM_DESC(max_transfer_size,
22559 +                "The maximum transfer size supported in bytes 2047-65535");
22560 +module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count,
22561 +                  int, 0444);
22562 +MODULE_PARM_DESC(max_packet_count,
22563 +                "The maximum number of packets in a transfer 15-511");
22564 +module_param_named(host_channels, dwc_otg_module_params.host_channels, int,
22565 +                  0444);
22566 +MODULE_PARM_DESC(host_channels,
22567 +                "The number of host channel registers to use 1-16");
22568 +module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int,
22569 +                  0444);
22570 +MODULE_PARM_DESC(dev_endpoints,
22571 +                "The number of endpoints in addition to EP0 available for device mode 1-15");
22572 +module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444);
22573 +MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI");
22574 +module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int,
22575 +                  0444);
22576 +MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");
22577 +module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444);
22578 +MODULE_PARM_DESC(phy_ulpi_ddr,
22579 +                "ULPI at double or single data rate 0=Single 1=Double");
22580 +module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus,
22581 +                  int, 0444);
22582 +MODULE_PARM_DESC(phy_ulpi_ext_vbus,
22583 +                "ULPI PHY using internal or external vbus 0=Internal");
22584 +module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444);
22585 +MODULE_PARM_DESC(i2c_enable, "FS PHY Interface");
22586 +module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444);
22587 +MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only");
22588 +module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444);
22589 +MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs");
22590 +module_param_named(debug, g_dbg_lvl, int, 0444);
22591 +MODULE_PARM_DESC(debug, "");
22592 +
22593 +module_param_named(en_multiple_tx_fifo,
22594 +                  dwc_otg_module_params.en_multiple_tx_fifo, int, 0444);
22595 +MODULE_PARM_DESC(en_multiple_tx_fifo,
22596 +                "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled");
22597 +module_param_named(dev_tx_fifo_size_1,
22598 +                  dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444);
22599 +MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768");
22600 +module_param_named(dev_tx_fifo_size_2,
22601 +                  dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444);
22602 +MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768");
22603 +module_param_named(dev_tx_fifo_size_3,
22604 +                  dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444);
22605 +MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768");
22606 +module_param_named(dev_tx_fifo_size_4,
22607 +                  dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444);
22608 +MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768");
22609 +module_param_named(dev_tx_fifo_size_5,
22610 +                  dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444);
22611 +MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768");
22612 +module_param_named(dev_tx_fifo_size_6,
22613 +                  dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444);
22614 +MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768");
22615 +module_param_named(dev_tx_fifo_size_7,
22616 +                  dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444);
22617 +MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768");
22618 +module_param_named(dev_tx_fifo_size_8,
22619 +                  dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444);
22620 +MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768");
22621 +module_param_named(dev_tx_fifo_size_9,
22622 +                  dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444);
22623 +MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768");
22624 +module_param_named(dev_tx_fifo_size_10,
22625 +                  dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444);
22626 +MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768");
22627 +module_param_named(dev_tx_fifo_size_11,
22628 +                  dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444);
22629 +MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768");
22630 +module_param_named(dev_tx_fifo_size_12,
22631 +                  dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444);
22632 +MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768");
22633 +module_param_named(dev_tx_fifo_size_13,
22634 +                  dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444);
22635 +MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768");
22636 +module_param_named(dev_tx_fifo_size_14,
22637 +                  dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444);
22638 +MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768");
22639 +module_param_named(dev_tx_fifo_size_15,
22640 +                  dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444);
22641 +MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768");
22642 +
22643 +module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444);
22644 +MODULE_PARM_DESC(thr_ctl,
22645 +                "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled");
22646 +module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int,
22647 +                  0444);
22648 +MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs");
22649 +module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int,
22650 +                  0444);
22651 +MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs");
22652 +
22653 +module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444);
22654 +module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444);
22655 +module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444);
22656 +MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled");
22657 +module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444);
22658 +MODULE_PARM_DESC(ic_usb_cap,
22659 +                "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled");
22660 +module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int, 0444);
22661 +MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio");
22662 +
22663 +/** @page "Module Parameters"
22664 + *
22665 + * The following parameters may be specified when starting the module.
22666 + * These parameters define how the DWC_otg controller should be
22667 + * configured. Parameter values are passed to the CIL initialization
22668 + * function dwc_otg_cil_init
22669 + *
22670 + * Example: <code>modprobe dwc_otg speed=1 otg_cap=1</code>
22671 + *
22672 +
22673 + <table>
22674 + <tr><td>Parameter Name</td><td>Meaning</td></tr>
22675 +
22676 + <tr>
22677 + <td>otg_cap</td>
22678 + <td>Specifies the OTG capabilities. The driver will automatically detect the
22679 + value for this parameter if none is specified.
22680 + - 0: HNP and SRP capable (default, if available)
22681 + - 1: SRP Only capable
22682 + - 2: No HNP/SRP capable
22683 + </td></tr>
22684 +
22685 + <tr>
22686 + <td>dma_enable</td>
22687 + <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs.
22688 + The driver will automatically detect the value for this parameter if none is
22689 + specified.
22690 + - 0: Slave
22691 + - 1: DMA (default, if available)
22692 + </td></tr>
22693 +
22694 + <tr>
22695 + <td>dma_burst_size</td>
22696 + <td>The DMA Burst size (applicable only for External DMA Mode).
22697 + - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32)
22698 + </td></tr>
22699 +
22700 + <tr>
22701 + <td>speed</td>
22702 + <td>Specifies the maximum speed of operation in host and device mode. The
22703 + actual speed depends on the speed of the attached device and the value of
22704 + phy_type.
22705 + - 0: High Speed (default)
22706 + - 1: Full Speed
22707 + </td></tr>
22708 +
22709 + <tr>
22710 + <td>host_support_fs_ls_low_power</td>
22711 + <td>Specifies whether low power mode is supported when attached to a Full
22712 + Speed or Low Speed device in host mode.
22713 + - 0: Don't support low power mode (default)
22714 + - 1: Support low power mode
22715 + </td></tr>
22716 +
22717 + <tr>
22718 + <td>host_ls_low_power_phy_clk</td>
22719 + <td>Specifies the PHY clock rate in low power mode when connected to a Low
22720 + Speed device in host mode. This parameter is applicable only if
22721 + HOST_SUPPORT_FS_LS_LOW_POWER is enabled.
22722 + - 0: 48 MHz (default)
22723 + - 1: 6 MHz
22724 + </td></tr>
22725 +
22726 + <tr>
22727 + <td>enable_dynamic_fifo</td>
22728 + <td> Specifies whether FIFOs may be resized by the driver software.
22729 + - 0: Use cC FIFO size parameters
22730 + - 1: Allow dynamic FIFO sizing (default)
22731 + </td></tr>
22732 +
22733 + <tr>
22734 + <td>data_fifo_size</td>
22735 + <td>Total number of 4-byte words in the data FIFO memory. This memory
22736 + includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs.
22737 + - Values: 32 to 32768 (default 8192)
22738 +
22739 + Note: The total FIFO memory depth in the FPGA configuration is 8192.
22740 + </td></tr>
22741 +
22742 + <tr>
22743 + <td>dev_rx_fifo_size</td>
22744 + <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic
22745 + FIFO sizing is enabled.
22746 + - Values: 16 to 32768 (default 1064)
22747 + </td></tr>
22748 +
22749 + <tr>
22750 + <td>dev_nperio_tx_fifo_size</td>
22751 + <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when
22752 + dynamic FIFO sizing is enabled.
22753 + - Values: 16 to 32768 (default 1024)
22754 + </td></tr>
22755 +
22756 + <tr>
22757 + <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td>
22758 + <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode
22759 + when dynamic FIFO sizing is enabled.
22760 + - Values: 4 to 768 (default 256)
22761 + </td></tr>
22762 +
22763 + <tr>
22764 + <td>host_rx_fifo_size</td>
22765 + <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO
22766 + sizing is enabled.
22767 + - Values: 16 to 32768 (default 1024)
22768 + </td></tr>
22769 +
22770 + <tr>
22771 + <td>host_nperio_tx_fifo_size</td>
22772 + <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when
22773 + dynamic FIFO sizing is enabled in the core.
22774 + - Values: 16 to 32768 (default 1024)
22775 + </td></tr>
22776 +
22777 + <tr>
22778 + <td>host_perio_tx_fifo_size</td>
22779 + <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO
22780 + sizing is enabled.
22781 + - Values: 16 to 32768 (default 1024)
22782 + </td></tr>
22783 +
22784 + <tr>
22785 + <td>max_transfer_size</td>
22786 + <td>The maximum transfer size supported in bytes.
22787 + - Values: 2047 to 65,535 (default 65,535)
22788 + </td></tr>
22789 +
22790 + <tr>
22791 + <td>max_packet_count</td>
22792 + <td>The maximum number of packets in a transfer.
22793 + - Values: 15 to 511 (default 511)
22794 + </td></tr>
22795 +
22796 + <tr>
22797 + <td>host_channels</td>
22798 + <td>The number of host channel registers to use.
22799 + - Values: 1 to 16 (default 12)
22800 +
22801 + Note: The FPGA configuration supports a maximum of 12 host channels.
22802 + </td></tr>
22803 +
22804 + <tr>
22805 + <td>dev_endpoints</td>
22806 + <td>The number of endpoints in addition to EP0 available for device mode
22807 + operations.
22808 + - Values: 1 to 15 (default 6 IN and OUT)
22809 +
22810 + Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in
22811 + addition to EP0.
22812 + </td></tr>
22813 +
22814 + <tr>
22815 + <td>phy_type</td>
22816 + <td>Specifies the type of PHY interface to use. By default, the driver will
22817 + automatically detect the phy_type.
22818 + - 0: Full Speed
22819 + - 1: UTMI+ (default, if available)
22820 + - 2: ULPI
22821 + </td></tr>
22822 +
22823 + <tr>
22824 + <td>phy_utmi_width</td>
22825 + <td>Specifies the UTMI+ Data Width. This parameter is applicable for a
22826 + phy_type of UTMI+. Also, this parameter is applicable only if the
22827 + OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the
22828 + core has been configured to work at either data path width.
22829 + - Values: 8 or 16 bits (default 16)
22830 + </td></tr>
22831 +
22832 + <tr>
22833 + <td>phy_ulpi_ddr</td>
22834 + <td>Specifies whether the ULPI operates at double or single data rate. This
22835 + parameter is only applicable if phy_type is ULPI.
22836 + - 0: single data rate ULPI interface with 8 bit wide data bus (default)
22837 + - 1: double data rate ULPI interface with 4 bit wide data bus
22838 + </td></tr>
22839 +
22840 + <tr>
22841 + <td>i2c_enable</td>
22842 + <td>Specifies whether to use the I2C interface for full speed PHY. This
22843 + parameter is only applicable if PHY_TYPE is FS.
22844 + - 0: Disabled (default)
22845 + - 1: Enabled
22846 + </td></tr>
22847 +
22848 + <tr>
22849 + <td>otg_en_multiple_tx_fifo</td>
22850 + <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.
22851 + The driver will automatically detect the value for this parameter if none is
22852 + specified.
22853 + - 0: Disabled
22854 + - 1: Enabled (default, if available)
22855 + </td></tr>
22856 +
22857 + <tr>
22858 + <td>dev_tx_fifo_size_n (n = 1 to 15)</td>
22859 + <td>Number of 4-byte words in each of the Tx FIFOs in device mode
22860 + when dynamic FIFO sizing is enabled.
22861 + - Values: 4 to 768 (default 256)
22862 + </td></tr>
22863 +
22864 + <tr>
22865 + <td>tx_thr_length</td>
22866 + <td>Transmit Threshold length in 32 bit double words
22867 + - Values: 8 to 128 (default 64)
22868 + </td></tr>
22869 +
22870 + <tr>
22871 + <td>rx_thr_length</td>
22872 + <td>Receive Threshold length in 32 bit double words
22873 + - Values: 8 to 128 (default 64)
22874 + </td></tr>
22875 +
22876 +<tr>
22877 + <td>thr_ctl</td>
22878 + <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of this 
22879 + parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and Rx 
22880 + transfers accordingly. 
22881 + The driver will automatically detect the value for this parameter if none is
22882 + specified.
22883 + - Values: 0 to 7 (default 0)
22884 + Bit values indicate:
22885 + - 0: Thresholding disabled
22886 + - 1: Thresholding enabled
22887 + </td></tr>
22888 +
22889 +<tr>
22890 + <td>dma_desc_enable</td>
22891 + <td>Specifies whether to enable Descriptor DMA mode.
22892 + The driver will automatically detect the value for this parameter if none is
22893 + specified.
22894 + - 0: Descriptor DMA disabled
22895 + - 1: Descriptor DMA (default, if available)
22896 + </td></tr>
22897 +
22898 +<tr>
22899 + <td>mpi_enable</td>
22900 + <td>Specifies whether to enable MPI enhancement mode.
22901 + The driver will automatically detect the value for this parameter if none is
22902 + specified.
22903 + - 0: MPI disabled (default)
22904 + - 1: MPI enable 
22905 + </td></tr>
22906 +
22907 +<tr>
22908 + <td>pti_enable</td>
22909 + <td>Specifies whether to enable PTI enhancement support.
22910 + The driver will automatically detect the value for this parameter if none is
22911 + specified.
22912 + - 0: PTI disabled (default)
22913 + - 1: PTI enable 
22914 + </td></tr>
22915 +
22916 +<tr>
22917 + <td>lpm_enable</td>
22918 + <td>Specifies whether to enable LPM support.
22919 + The driver will automatically detect the value for this parameter if none is
22920 + specified.
22921 + - 0: LPM disabled
22922 + - 1: LPM enable (default, if available)
22923 + </td></tr>
22924 +
22925 + <tr>
22926 + <td>ahb_thr_ratio</td>
22927 + <td>Specifies AHB Threshold ratio.
22928 + - Values: 0 to 3 (default 0)
22929 + </td></tr>
22930 +
22931 +*/
22932 --- /dev/null
22933 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h
22934 @@ -0,0 +1,101 @@
22935 +/* ==========================================================================
22936 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
22937 + * $Revision: #16 $
22938 + * $Date: 2009/04/03 $
22939 + * $Change: 1225160 $
22940 + *
22941 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
22942 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
22943 + * otherwise expressly agreed to in writing between Synopsys and you.
22944 + * 
22945 + * The Software IS NOT an item of Licensed Software or Licensed Product under
22946 + * any End User Software License Agreement or Agreement for Licensed Product
22947 + * with Synopsys or any supplement thereto. You are permitted to use and
22948 + * redistribute this Software in source and binary forms, with or without
22949 + * modification, provided that redistributions of source code must retain this
22950 + * notice. You may not view, use, disclose, copy or distribute this file or
22951 + * any information contained herein except pursuant to this license grant from
22952 + * Synopsys. If you do not agree with this notice, including the disclaimer
22953 + * below, then you are not authorized to use the Software.
22954 + * 
22955 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22956 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22957 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22958 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
22959 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22960 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22961 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22962 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22963 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22964 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
22965 + * DAMAGE.
22966 + * ========================================================================== */
22967 +
22968 +#ifndef __DWC_OTG_DRIVER_H__
22969 +#define __DWC_OTG_DRIVER_H__
22970 +
22971 +/** @file
22972 + * This file contains the interface to the Linux driver.
22973 + */
22974 +#include "dwc_otg_core_if.h"
22975 +
22976 +/* Type declarations */
22977 +struct dwc_otg_pcd;
22978 +struct dwc_otg_hcd;
22979 +
22980 +#ifdef  PCI_INTERFACE
22981 +#include <linux/pci.h>
22982 +#endif
22983 +
22984 +
22985 +
22986 +/**
22987 + * This structure is a wrapper that encapsulates the driver components used to
22988 + * manage a single DWC_otg controller.
22989 + */
22990 +typedef struct dwc_otg_device {
22991 +       /** Base address returned from ioremap() */
22992 +       void *base;
22993 +
22994 +#ifdef LM_INTERFACE
22995 +       struct lm_device *lmdev;
22996 +#elif  defined(PCI_INTERFACE)
22997 +       int rsrc_start;
22998 +       int rsrc_len;
22999 +#elif  defined(PLATFORM_INTERFACE)
23000 +       struct platform_device *platformdev;
23001 +#endif
23002 +
23003 +       /** Pointer to the core interface structure. */
23004 +       dwc_otg_core_if_t *core_if;
23005 +
23006 +       /** Register offset for Diagnostic API. */
23007 +       uint32_t reg_offset;
23008 +
23009 +       /** Pointer to the PCD structure. */
23010 +       struct dwc_otg_pcd *pcd;
23011 +
23012 +       /** Pointer to the HCD structure. */
23013 +       struct dwc_otg_hcd *hcd;
23014 +
23015 +       /** Flag to indicate whether the common IRQ handler is installed. */
23016 +       uint8_t common_irq_installed;
23017 +
23018 +} dwc_otg_device_t;
23019 +
23020 +/*We must clear S3C24XX_EINTPEND external interrupt register 
23021 + * because after clearing in this register trigerred IRQ from 
23022 + * H/W core in kernel interrupt can be occured again before OTG
23023 + * handlers clear all IRQ sources of Core registers because of
23024 + * timing latencies and Low Level IRQ Type.
23025 + */
23026 +#ifdef CONFIG_MACH_IPMATE
23027 +#define  S3C2410X_CLEAR_EINTPEND()   \
23028 +do { \
23029 +       __raw_writel(1UL << 11,S3C24XX_EINTPEND); \
23030 +} while (0)
23031 +#else
23032 +#define  S3C2410X_CLEAR_EINTPEND()   do { } while (0)
23033 +#endif
23034 +
23035 +#endif
23036 --- /dev/null
23037 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
23038 @@ -0,0 +1,3330 @@
23039 +
23040 +/* ==========================================================================
23041 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
23042 + * $Revision: #87 $
23043 + * $Date: 2009/04/23 $
23044 + * $Change: 1239143 $
23045 + *
23046 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
23047 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
23048 + * otherwise expressly agreed to in writing between Synopsys and you.
23049 + *
23050 + * The Software IS NOT an item of Licensed Software or Licensed Product under
23051 + * any End User Software License Agreement or Agreement for Licensed Product
23052 + * with Synopsys or any supplement thereto. You are permitted to use and
23053 + * redistribute this Software in source and binary forms, with or without
23054 + * modification, provided that redistributions of source code must retain this
23055 + * notice. You may not view, use, disclose, copy or distribute this file or
23056 + * any information contained herein except pursuant to this license grant from
23057 + * Synopsys. If you do not agree with this notice, including the disclaimer
23058 + * below, then you are not authorized to use the Software.
23059 + *
23060 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
23061 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23062 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23063 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
23064 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23065 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23066 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23067 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23068 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23069 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
23070 + * DAMAGE.
23071 + * ========================================================================== */
23072 +#ifndef DWC_DEVICE_ONLY
23073 +
23074 +/** @file
23075 + * This file implements HCD Core. All code in this file is portable and don't
23076 + * use any OS specific functions.
23077 + * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
23078 + * header file.
23079 + */
23080 +
23081 +#include "dwc_otg_hcd.h"
23082 +#include "dwc_otg_regs.h"
23083 +
23084 +#ifdef HW2937_WORKAROUND
23085 +//#include <linux/kernel.h>
23086 +#include <linux/spinlock.h>
23087 +#endif
23088 +               
23089 +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
23090 +{
23091 +       return dwc_alloc(sizeof(dwc_otg_hcd_t));
23092 +}
23093 +
23094 +/**
23095 + * Connection timeout function.  An OTG host is required to display a
23096 + * message if the device does not connect within 10 seconds.
23097 + */
23098 +void dwc_otg_hcd_connect_timeout(void *ptr)
23099 +{
23100 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
23101 +       DWC_PRINTF("Connect Timeout\n");
23102 +       __DWC_ERROR("Device Not Connected/Responding\n");
23103 +}
23104 +
23105 +#ifdef DEBUG
23106 +static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
23107 +{
23108 +       if (qh->channel != NULL) {
23109 +               dwc_hc_t *hc = qh->channel;
23110 +               dwc_list_link_t *item;
23111 +               dwc_otg_qh_t *qh_item;
23112 +               int num_channels = hcd->core_if->core_params->host_channels;
23113 +               int i;
23114 +
23115 +               dwc_otg_hc_regs_t *hc_regs;
23116 +               hcchar_data_t hcchar;
23117 +               hcsplt_data_t hcsplt;
23118 +               hctsiz_data_t hctsiz;
23119 +               uint32_t hcdma;
23120 +
23121 +               hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
23122 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
23123 +               hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt);
23124 +               hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
23125 +               hcdma = dwc_read_reg32(&hc_regs->hcdma);
23126 +
23127 +               DWC_PRINTF("  Assigned to channel %p:\n", hc);
23128 +               DWC_PRINTF("    hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
23129 +                          hcsplt.d32);
23130 +               DWC_PRINTF("    hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
23131 +                          hcdma);
23132 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
23133 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
23134 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
23135 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
23136 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
23137 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
23138 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
23139 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
23140 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
23141 +               DWC_PRINTF("    qh: %p\n", hc->qh);
23142 +               DWC_PRINTF("  NP inactive sched:\n");
23143 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
23144 +                       qh_item =
23145 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
23146 +                       DWC_PRINTF("    %p\n", qh_item);
23147 +               }
23148 +               DWC_PRINTF("  NP active sched:\n");
23149 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
23150 +                       qh_item =
23151 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
23152 +                       DWC_PRINTF("    %p\n", qh_item);
23153 +               }
23154 +               DWC_PRINTF("  Channels: \n");
23155 +               for (i = 0; i < num_channels; i++) {
23156 +                       dwc_hc_t *hc = hcd->hc_ptr_array[i];
23157 +                       DWC_PRINTF("    %2d: %p\n", i, hc);
23158 +               }
23159 +       }
23160 +}
23161 +#endif                         /* DEBUG */
23162 +
23163 +/**
23164 + * Work queue function for starting the HCD when A-Cable is connected.
23165 + * The hcd_start() must be called in a process context.
23166 + */
23167 +static void hcd_start_func(void *_vp)
23168 +{
23169 +       dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
23170 +
23171 +       DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
23172 +       if (hcd) {
23173 +               hcd->fops->start(hcd);
23174 +       }
23175 +}
23176 +
23177 +static void del_xfer_timers(dwc_otg_hcd_t * hcd)
23178 +{
23179 +#ifdef DEBUG
23180 +       int i;
23181 +       int num_channels = hcd->core_if->core_params->host_channels;
23182 +       for (i = 0; i < num_channels; i++) {
23183 +               DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
23184 +       }
23185 +#endif
23186 +}
23187 +
23188 +static void del_timers(dwc_otg_hcd_t * hcd)
23189 +{
23190 +       del_xfer_timers(hcd);
23191 +       DWC_TIMER_CANCEL(hcd->conn_timer);
23192 +}
23193 +
23194 +/**
23195 + * Processes all the URBs in a single list of QHs. Completes them with
23196 + * -ETIMEDOUT and frees the QTD.
23197 + */
23198 +static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
23199 +{
23200 +       dwc_list_link_t *qh_item;
23201 +       dwc_otg_qh_t *qh;
23202 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
23203 +
23204 +       DWC_LIST_FOREACH(qh_item, qh_list) {
23205 +               qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
23206 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
23207 +                                        &qh->qtd_list, qtd_list_entry) {
23208 +                       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
23209 +                       if (qtd->urb != NULL) {
23210 +                               hcd->fops->complete(hcd, qtd->urb->priv,
23211 +                                                   qtd->urb,
23212 +                                                   -DWC_E_TIMEOUT);
23213 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
23214 +                       }
23215 +
23216 +               }
23217 +       }
23218 +}
23219 +
23220 +/**
23221 + * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
23222 + * and periodic schedules. The QTD associated with each URB is removed from
23223 + * the schedule and freed. This function may be called when a disconnect is
23224 + * detected or when the HCD is being stopped.
23225 + */
23226 +static void kill_all_urbs(dwc_otg_hcd_t * hcd)
23227 +{
23228 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
23229 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
23230 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
23231 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
23232 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
23233 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
23234 +}
23235 +
23236 +/**
23237 + * Start the connection timer.  An OTG host is required to display a
23238 + * message if the device does not connect within 10 seconds.  The
23239 + * timer is deleted if a port connect interrupt occurs before the
23240 + * timer expires.
23241 + */
23242 +static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
23243 +{
23244 +       DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
23245 +}
23246 +
23247 +/**
23248 + * HCD Callback function for disconnect of the HCD.
23249 + *
23250 + * @param p void pointer to the <code>struct usb_hcd</code>
23251 + */
23252 +static int32_t dwc_otg_hcd_session_start_cb(void *p)
23253 +{
23254 +       dwc_otg_hcd_t *dwc_otg_hcd;
23255 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
23256 +       dwc_otg_hcd = p;
23257 +       dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
23258 +       return 1;
23259 +}
23260 +
23261 +/**
23262 + * HCD Callback function for starting the HCD when A-Cable is
23263 + * connected.
23264 + *
23265 + * @param p void pointer to the <code>struct usb_hcd</code>
23266 + */
23267 +static int32_t dwc_otg_hcd_start_cb(void *p)
23268 +{
23269 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
23270 +       dwc_otg_core_if_t *core_if;
23271 +       hprt0_data_t hprt0;
23272 +
23273 +       core_if = dwc_otg_hcd->core_if;
23274 +
23275 +       if (core_if->op_state == B_HOST) {
23276 +               /*
23277 +                * Reset the port.  During a HNP mode switch the reset
23278 +                * needs to occur within 1ms and have a duration of at
23279 +                * least 50ms.
23280 +                */
23281 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
23282 +               hprt0.b.prtrst = 1;
23283 +               dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
23284 +       }
23285 +       DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
23286 +                                  hcd_start_func, dwc_otg_hcd, 50,
23287 +                                  "start hcd");
23288 +
23289 +       return 1;
23290 +}
23291 +
23292 +/**
23293 + * HCD Callback function for disconnect of the HCD.
23294 + *
23295 + * @param p void pointer to the <code>struct usb_hcd</code>
23296 + */
23297 +static int32_t dwc_otg_hcd_disconnect_cb(void *p)
23298 +{
23299 +       gintsts_data_t intr;
23300 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
23301 +
23302 +       /*
23303 +        * Set status flags for the hub driver.
23304 +        */
23305 +       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
23306 +       dwc_otg_hcd->flags.b.port_connect_status = 0;
23307 +
23308 +       /*
23309 +        * Shutdown any transfers in process by clearing the Tx FIFO Empty
23310 +        * interrupt mask and status bits and disabling subsequent host
23311 +        * channel interrupts.
23312 +        */
23313 +       intr.d32 = 0;
23314 +       intr.b.nptxfempty = 1;
23315 +       intr.b.ptxfempty = 1;
23316 +       intr.b.hcintr = 1;
23317 +       dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
23318 +                        intr.d32, 0);
23319 +       dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
23320 +                        intr.d32, 0);
23321 +
23322 +       del_timers(dwc_otg_hcd);
23323 +
23324 +       /*
23325 +        * Turn off the vbus power only if the core has transitioned to device
23326 +        * mode. If still in host mode, need to keep power on to detect a
23327 +        * reconnection.
23328 +        */
23329 +       if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
23330 +               if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
23331 +                       hprt0_data_t hprt0 = {.d32 = 0 };
23332 +                       DWC_PRINTF("Disconnect: PortPower off\n");
23333 +                       hprt0.b.prtpwr = 0;
23334 +                       dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0,
23335 +                                       hprt0.d32);
23336 +               }
23337 +
23338 +               dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
23339 +       }
23340 +
23341 +       /* Respond with an error status to all URBs in the schedule. */
23342 +       kill_all_urbs(dwc_otg_hcd);
23343 +
23344 +       if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
23345 +               /* Clean up any host channels that were in use. */
23346 +               int num_channels;
23347 +               int i;
23348 +               dwc_hc_t *channel;
23349 +               dwc_otg_hc_regs_t *hc_regs;
23350 +               hcchar_data_t hcchar;
23351 +
23352 +               num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
23353 +
23354 +               if (!dwc_otg_hcd->core_if->dma_enable) {
23355 +                       /* Flush out any channel requests in slave mode. */
23356 +                       for (i = 0; i < num_channels; i++) {
23357 +                               channel = dwc_otg_hcd->hc_ptr_array[i];
23358 +                               if (DWC_CIRCLEQ_EMPTY_ENTRY
23359 +                                   (channel, hc_list_entry)) {
23360 +                                       hc_regs =
23361 +                                           dwc_otg_hcd->core_if->host_if->
23362 +                                           hc_regs[i];
23363 +                                       hcchar.d32 =
23364 +                                           dwc_read_reg32(&hc_regs->hcchar);
23365 +                                       if (hcchar.b.chen) {
23366 +                                               hcchar.b.chen = 0;
23367 +                                               hcchar.b.chdis = 1;
23368 +                                               hcchar.b.epdir = 0;
23369 +                                               dwc_write_reg32(&hc_regs->
23370 +                                                               hcchar,
23371 +                                                               hcchar.d32);
23372 +                                       }
23373 +                               }
23374 +                       }
23375 +               }
23376 +
23377 +               for (i = 0; i < num_channels; i++) {
23378 +                       channel = dwc_otg_hcd->hc_ptr_array[i];
23379 +                       if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
23380 +                               hc_regs =
23381 +                                   dwc_otg_hcd->core_if->host_if->hc_regs[i];
23382 +                               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
23383 +                               if (hcchar.b.chen) {
23384 +                                       /* Halt the channel. */
23385 +                                       hcchar.b.chdis = 1;
23386 +                                       dwc_write_reg32(&hc_regs->hcchar,
23387 +                                                       hcchar.d32);
23388 +                               }
23389 +
23390 +                               dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
23391 +                                                  channel);
23392 +                               DWC_CIRCLEQ_INSERT_TAIL(&dwc_otg_hcd->
23393 +                                                       free_hc_list, channel,
23394 +                                                       hc_list_entry);
23395 +                               /* 
23396 +                                * Added for Descriptor DMA to prevent channel double cleanup 
23397 +                                * in release_channel_ddma(). Which called from ep_disable
23398 +                                * when device disconnect.
23399 +                                */                     
23400 +                               channel->qh = NULL;                     
23401 +                       }
23402 +               }
23403 +       }
23404 +
23405 +       if (dwc_otg_hcd->fops->disconnect) {
23406 +               dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
23407 +       }
23408 +
23409 +       return 1;
23410 +}
23411 +
23412 +/**
23413 + * HCD Callback function for stopping the HCD.
23414 + *
23415 + * @param p void pointer to the <code>struct usb_hcd</code>
23416 + */
23417 +static int32_t dwc_otg_hcd_stop_cb(void *p)
23418 +{
23419 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
23420 +
23421 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
23422 +       dwc_otg_hcd_stop(dwc_otg_hcd);
23423 +       return 1;
23424 +}
23425 +
23426 +#ifdef CONFIG_USB_DWC_OTG_LPM
23427 +/** 
23428 + * HCD Callback function for sleep of HCD.
23429 + *
23430 + * @param p void pointer to the <code>struct usb_hcd</code>
23431 + */
23432 +static int dwc_otg_hcd_sleep_cb(void *p)
23433 +{
23434 +       dwc_otg_hcd_t *hcd = p;
23435 +
23436 +       dwc_otg_hcd_free_hc_from_lpm(hcd);
23437 +
23438 +       return 0;
23439 +}
23440 +#endif
23441 +
23442 +/**
23443 + * HCD Callback function for Remote Wakeup.
23444 + *
23445 + * @param p void pointer to the <code>struct usb_hcd</code>
23446 + */
23447 +static int dwc_otg_hcd_rem_wakeup_cb(void *p)
23448 +{
23449 +       dwc_otg_hcd_t *hcd = p;
23450 +
23451 +       if (hcd->core_if->lx_state == DWC_OTG_L2) {
23452 +               hcd->flags.b.port_suspend_change = 1;
23453 +       }
23454 +#ifdef CONFIG_USB_DWC_OTG_LPM
23455 +       else {
23456 +               hcd->flags.b.port_l1_change = 1;
23457 +       }
23458 +#endif
23459 +       return 0;
23460 +}
23461 +
23462 +/**
23463 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
23464 + * stopped.
23465 + */
23466 +void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
23467 +{
23468 +       hprt0_data_t hprt0 = {.d32 = 0 };
23469 +
23470 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
23471
23472 +       /*
23473 +        * The root hub should be disconnected before this function is called.
23474 +        * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
23475 +        * and the QH lists (via ..._hcd_endpoint_disable).
23476 +        */
23477 +
23478 +       /* Turn off all host-specific interrupts. */
23479 +       dwc_otg_disable_host_interrupts(hcd->core_if);
23480 +
23481 +       /* Turn off the vbus power */
23482 +       DWC_PRINTF("PortPower off\n");
23483 +       hprt0.b.prtpwr = 0;
23484 +       dwc_write_reg32(hcd->core_if->host_if->hprt0, hprt0.d32);
23485 +       dwc_mdelay(1);
23486 +}
23487 +
23488 +int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
23489 +                           dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle)
23490 +{
23491 +       uint64_t flags;
23492 +       int retval = 0;
23493 +       dwc_otg_qtd_t *qtd;
23494 +
23495 +       if (NULL == hcd->core_if) { //GRAYG
23496 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");
23497 +               /* No longer connected. */
23498 +               return -DWC_E_INVALID;
23499 +       }
23500 +
23501 +       if (!hcd->flags.b.port_connect_status) {
23502 +               /* No longer connected. */
23503 +               return -DWC_E_NO_DEVICE;
23504 +       }
23505 +
23506 +       qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb);
23507 +       if (qtd == NULL) {
23508 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
23509 +               return -DWC_E_NO_MEMORY;
23510 +       }
23511 +       if (qtd->urb == NULL) { //GRAYG
23512 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");
23513 +               return -DWC_E_NO_MEMORY;
23514 +       }
23515 +       if (qtd->urb->priv == NULL) { //GRAYG
23516 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");
23517 +               return -DWC_E_NO_MEMORY;
23518 +       }
23519 +
23520 +       retval =
23521 +           dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle);
23522 +            // creates a new queue in ep_handle if it doesn't exist already
23523 +       if (retval < 0) {
23524 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
23525 +                         "Error status %d\n", retval);
23526 +               dwc_otg_hcd_qtd_free(qtd);
23527 +       } else {
23528 +               qtd->qh = *ep_handle;
23529 +       }
23530 +       
23531 +       if (hcd->core_if->dma_desc_enable && retval == 0) {
23532 +               dwc_otg_transaction_type_e tr_type;     
23533 +               if ((qtd->qh->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
23534 +                       /* Do not schedule SG transcations until qtd has URB_GIVEBACK_ASAP set */
23535 +                       return 0;
23536 +               }
23537 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
23538 +               tr_type = dwc_otg_hcd_select_transactions(hcd);
23539 +               if (tr_type != DWC_OTG_TRANSACTION_NONE) {
23540 +                       dwc_otg_hcd_queue_transactions(hcd, tr_type);
23541 +               }
23542 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
23543 +       }
23544 +
23545 +       return retval;
23546 +}
23547 +
23548 +int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
23549 +                           dwc_otg_hcd_urb_t * dwc_otg_urb)
23550 +{
23551 +       uint64_t flags;
23552 +
23553 +       dwc_otg_qh_t *qh;
23554 +       dwc_otg_qtd_t *urb_qtd;
23555 +
23556 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
23557 +       
23558 +       if (hcd == NULL) { //GRAYG
23559 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");
23560 +               return -DWC_E_INVALID;
23561 +       }
23562 +       if (dwc_otg_urb == NULL) { //GRAYG
23563 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");
23564 +               return -DWC_E_INVALID;
23565 +       }
23566 +       if (dwc_otg_urb->qtd == NULL) { //GRAYG
23567 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");
23568 +               return -DWC_E_INVALID;
23569 +       }
23570 +       urb_qtd = dwc_otg_urb->qtd;
23571 +       if (urb_qtd->qh == NULL) { //GRAYG
23572 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
23573 +               return -DWC_E_INVALID;
23574 +       }
23575 +       qh = urb_qtd->qh;
23576 +#ifdef DEBUG
23577 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
23578 +               if (urb_qtd->in_process) {
23579 +                       dump_channel_info(hcd, qh);
23580 +               }
23581 +       }
23582 +#endif
23583 +       if (hcd->core_if == NULL) { //GRAYG
23584 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");
23585 +               return -DWC_E_INVALID;
23586 +       }
23587 +       if (urb_qtd->in_process && qh->channel) {
23588 +               /* The QTD is in process (it has been assigned to a channel). */
23589 +               if (hcd->flags.b.port_connect_status) {
23590 +                       /*
23591 +                        * If still connected (i.e. in host mode), halt the
23592 +                        * channel so it can be used for other transfers. If
23593 +                        * no longer connected, the host registers can't be
23594 +                        * written to halt the channel since the core is in
23595 +                        * device mode.
23596 +                        */
23597 +                       dwc_otg_hc_halt(hcd->core_if, qh->channel,
23598 +                                       DWC_OTG_HC_XFER_URB_DEQUEUE);
23599 +               }
23600 +       }
23601 +
23602 +       /*
23603 +        * Free the QTD and clean up the associated QH. Leave the QH in the
23604 +        * schedule if it has any remaining QTDs.
23605 +        */
23606 +        
23607 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "
23608 +                    "delete %sQueue handler\n",
23609 +                    hcd->core_if->dma_desc_enable?"DMA ":""); //GRAYG
23610 +       if (!hcd->core_if->dma_desc_enable) {
23611 +               uint8_t b = urb_qtd->in_process;        
23612 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
23613 +               if (b) {
23614 +                       dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
23615 +                       qh->channel = NULL;
23616 +               } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
23617 +                       dwc_otg_hcd_qh_remove(hcd, qh);
23618 +               }
23619 +       }
23620 +       else {
23621 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
23622 +       }
23623 +       
23624 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
23625 +
23626 +       return 0;
23627 +}
23628 +
23629 +int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
23630 +                                int retry)
23631 +{
23632 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
23633 +       int retval = 0;
23634 +       uint64_t flags;
23635 +
23636 +       if (retry < 0) {
23637 +               retval = -DWC_E_INVALID;
23638 +               goto done;
23639 +       }
23640 +
23641 +       if (!qh) {
23642 +               goto done;
23643 +       }
23644 +
23645 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
23646 +       
23647 +       while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
23648 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
23649 +               retry--;
23650 +               dwc_msleep(5);
23651 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
23652 +       }
23653 +
23654 +       dwc_otg_hcd_qh_remove(hcd, qh);
23655 +       
23656 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
23657 +       /* 
23658 +        * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove 
23659 +        * and qh_free to prevent stack dump on dwc_dma_free() with 
23660 +        * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() 
23661 +        * and dwc_otg_hcd_frame_list_alloc().
23662 +        */
23663 +       dwc_otg_hcd_qh_free(hcd, qh);
23664 +
23665 +      done:
23666 +       return retval;
23667 +}
23668 +
23669 +/**
23670 + * HCD Callback structure for handling mode switching.
23671 + */
23672 +static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
23673 +       .start = dwc_otg_hcd_start_cb,
23674 +       .stop = dwc_otg_hcd_stop_cb,
23675 +       .disconnect = dwc_otg_hcd_disconnect_cb,
23676 +       .session_start = dwc_otg_hcd_session_start_cb,
23677 +       .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
23678 +#ifdef CONFIG_USB_DWC_OTG_LPM
23679 +       .sleep = dwc_otg_hcd_sleep_cb,
23680 +#endif
23681 +       .p = 0,
23682 +};
23683 +
23684 +/**
23685 + * Reset tasklet function
23686 + */
23687 +static void reset_tasklet_func(void *data)
23688 +{
23689 +       dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
23690 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
23691 +       hprt0_data_t hprt0;
23692 +
23693 +       DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
23694 +
23695 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
23696 +       hprt0.b.prtrst = 1;
23697 +       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
23698 +       dwc_mdelay(60);
23699 +
23700 +       hprt0.b.prtrst = 0;
23701 +       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
23702 +       dwc_otg_hcd->flags.b.port_reset_change = 1;
23703 +}
23704 +
23705 +static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
23706 +{
23707 +       dwc_list_link_t *item;
23708 +       dwc_otg_qh_t *qh;
23709 +
23710 +       if (!qh_list->next) {
23711 +               /* The list hasn't been initialized yet. */
23712 +               return;
23713 +       }
23714 +
23715 +       /* Ensure there are no QTDs or URBs left. */
23716 +       kill_urbs_in_qh_list(hcd, qh_list);
23717 +
23718 +       DWC_LIST_FOREACH(item, qh_list) {
23719 +               qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
23720 +               dwc_otg_hcd_qh_remove_and_free(hcd, qh);
23721 +       }
23722 +}
23723 +
23724 +/**
23725 + * Frees secondary storage associated with the dwc_otg_hcd structure contained
23726 + * in the struct usb_hcd field.
23727 + */
23728 +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
23729 +{
23730 +       int i;
23731 +
23732 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
23733 +
23734 +       del_timers(dwc_otg_hcd);
23735 +
23736 +       /* Free memory for QH/QTD lists */
23737 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
23738 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
23739 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
23740 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
23741 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
23742 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
23743 +
23744 +       /* Free memory for the host channels. */
23745 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
23746 +               dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
23747 +
23748 +#ifdef DEBUG
23749 +               if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
23750 +                       DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
23751 +               }
23752 +#endif
23753 +               if (hc != NULL) {
23754 +                       DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
23755 +                                   i, hc);
23756 +                       dwc_free(hc);
23757 +               }
23758 +       }
23759 +
23760 +       if (dwc_otg_hcd->core_if->dma_enable) {
23761 +               if (dwc_otg_hcd->status_buf_dma) {
23762 +                       dwc_dma_free(DWC_OTG_HCD_STATUS_BUF_SIZE,
23763 +                                    dwc_otg_hcd->status_buf,
23764 +                                    dwc_otg_hcd->status_buf_dma);
23765 +               }
23766 +       } else if (dwc_otg_hcd->status_buf != NULL) {
23767 +               dwc_free(dwc_otg_hcd->status_buf);
23768 +       }
23769 +       DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
23770 +       DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
23771 +       DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
23772 +       dwc_free(dwc_otg_hcd);
23773 +}
23774 +
23775 +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
23776 +{
23777 +       int retval = 0;
23778 +       int num_channels;
23779 +       int i;
23780 +       dwc_hc_t *channel;
23781 +
23782 +       hcd->lock = DWC_SPINLOCK_ALLOC();
23783 +
23784 +        DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
23785 +                    hcd, core_if);//GRAYG
23786 +        
23787 +       hcd->core_if = core_if;
23788 +       /* Register the HCD CIL Callbacks */
23789 +       dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
23790 +                                          &hcd_cil_callbacks, hcd);
23791 +
23792 +       /* Initialize the non-periodic schedule. */
23793 +       DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
23794 +       DWC_LIST_INIT(&hcd->non_periodic_sched_active);
23795 +
23796 +       /* Initialize the periodic schedule. */
23797 +       DWC_LIST_INIT(&hcd->periodic_sched_inactive);
23798 +       DWC_LIST_INIT(&hcd->periodic_sched_ready);
23799 +       DWC_LIST_INIT(&hcd->periodic_sched_assigned);
23800 +       DWC_LIST_INIT(&hcd->periodic_sched_queued);
23801 +
23802 +       /*
23803 +        * Create a host channel descriptor for each host channel implemented
23804 +        * in the controller. Initialize the channel descriptor array.
23805 +        */
23806 +       DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
23807 +       num_channels = hcd->core_if->core_params->host_channels;
23808 +       DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
23809 +       for (i = 0; i < num_channels; i++) {
23810 +               channel = dwc_alloc(sizeof(dwc_hc_t));
23811 +               if (channel == NULL) {
23812 +                       retval = -DWC_E_NO_MEMORY;
23813 +                       DWC_ERROR("%s: host channel allocation failed\n",
23814 +                                 __func__);
23815 +                       dwc_otg_hcd_free(hcd);
23816 +                       goto out;
23817 +               }
23818 +               channel->hc_num = i;
23819 +               hcd->hc_ptr_array[i] = channel;
23820 +#ifdef DEBUG
23821 +               hcd->core_if->hc_xfer_timer[i] =
23822 +                   DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
23823 +                                   &hcd->core_if->hc_xfer_info[i]);
23824 +#endif
23825 +               DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
23826 +                           channel);
23827 +       }
23828 +
23829 +       /* Initialize the Connection timeout timer. */
23830 +       hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
23831 +                                         dwc_otg_hcd_connect_timeout, 0);
23832 +
23833 +       /* Initialize reset tasklet. */
23834 +       hcd->reset_tasklet = DWC_TASK_ALLOC(reset_tasklet_func, hcd);
23835 +
23836 +       /*
23837 +        * Allocate space for storing data on status transactions. Normally no
23838 +        * data is sent, but this space acts as a bit bucket. This must be
23839 +        * done after usb_add_hcd since that function allocates the DMA buffer
23840 +        * pool.
23841 +        */
23842 +       if (hcd->core_if->dma_enable) {
23843 +               hcd->status_buf =
23844 +                   dwc_dma_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE,
23845 +                                 &hcd->status_buf_dma);
23846 +       } else {
23847 +               hcd->status_buf = dwc_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE);
23848 +       }
23849 +       if (!hcd->status_buf) {
23850 +               retval = -DWC_E_NO_MEMORY;
23851 +               DWC_ERROR("%s: status_buf allocation failed\n", __func__);
23852 +               dwc_otg_hcd_free(hcd);
23853 +               goto out;
23854 +       }
23855 +
23856 +       hcd->otg_port = 1;
23857 +       hcd->frame_list = NULL;
23858 +       hcd->frame_list_dma = 0;
23859 +
23860 +#ifdef HW2937_WORKAROUND
23861 +       hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IDLE;
23862 +       hcd->hw2937_assigned_channels = 0;
23863 +#endif
23864 +
23865 +out:
23866 +       return retval;
23867 +}
23868 +
23869 +void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
23870 +{
23871 +       /* Turn off all host-specific interrupts. */
23872 +       dwc_otg_disable_host_interrupts(hcd->core_if);
23873 +
23874 +       dwc_otg_hcd_free(hcd);
23875 +}
23876 +
23877 +/**
23878 + * Initializes dynamic portions of the DWC_otg HCD state.
23879 + */
23880 +static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
23881 +{
23882 +       int num_channels;
23883 +       int i;
23884 +       dwc_hc_t *channel;
23885 +       dwc_hc_t *channel_tmp;
23886 +
23887 +       hcd->flags.d32 = 0;
23888 +
23889 +       hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
23890 +       hcd->non_periodic_channels = 0;
23891 +       hcd->periodic_channels = 0;
23892 +
23893 +       /*
23894 +        * Put all channels in the free channel list and clean up channel
23895 +        * states.
23896 +        */
23897 +       DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
23898 +                                &hcd->free_hc_list, hc_list_entry) {
23899 +               DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
23900 +       }
23901 +
23902 +       num_channels = hcd->core_if->core_params->host_channels;
23903 +       for (i = 0; i < num_channels; i++) {
23904 +               channel = hcd->hc_ptr_array[i];
23905 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
23906 +                                       hc_list_entry);
23907 +               dwc_otg_hc_cleanup(hcd->core_if, channel);
23908 +       }
23909 +
23910 +       /* Initialize the DWC core for host mode operation. */
23911 +       dwc_otg_core_host_init(hcd->core_if);
23912 +}
23913 +
23914 +/**
23915 + * Assigns transactions from a QTD to a free host channel and initializes the
23916 + * host channel to perform the transactions. The host channel is removed from
23917 + * the free list.
23918 + *
23919 + * @param hcd The HCD state structure.
23920 + * @param qh Transactions from the first QTD for this QH are selected and
23921 + * assigned to a free host channel.
23922 + */
23923 +#ifdef HW2937_WORKAROUND
23924 +static int assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
23925 +#else
23926 +static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
23927 +#endif
23928 +{
23929 +       dwc_hc_t *hc;
23930 +       dwc_otg_qtd_t *qtd;
23931 +       dwc_otg_hcd_urb_t *urb;
23932 +       void* ptr = NULL;
23933 +#ifdef HW2937_WORKAROUND
23934 +       int ep_is_in;
23935 +#endif
23936 +
23937 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
23938 +       
23939 +       urb = qtd->urb;
23940 +
23941 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);
23942 +
23943 +#ifdef HW2937_WORKAROUND
23944 +       ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
23945 +       if (ep_is_in && ((hcd->hw2937_xfer_mode == HW2937_XFER_MODE_OUT) ||
23946 +                        (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_PAUSEIN)))
23947 +               return 0;
23948 +#endif
23949 +
23950 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
23951 +
23952 +       /* Remove the host channel from the free list. */
23953 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
23954 +       qh->channel = hc;
23955 +       
23956 +       qtd->in_process = 1;
23957 +
23958 +       /*
23959 +        * Use usb_pipedevice to determine device address. This address is
23960 +        * 0 before the SET_ADDRESS command and the correct address afterward.
23961 +        */
23962 +       hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
23963 +       hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
23964 +       hc->speed = qh->dev_speed;
23965 +       hc->max_packet = dwc_max_packet(qh->maxp);
23966 +
23967 +       hc->xfer_started = 0;
23968 +       hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
23969 +       hc->error_state = (qtd->error_count > 0);
23970 +       hc->halt_on_queue = 0;
23971 +       hc->halt_pending = 0;
23972 +       hc->requests = 0;
23973 +
23974 +       /*
23975 +        * The following values may be modified in the transfer type section
23976 +        * below. The xfer_len value may be reduced when the transfer is
23977 +        * started to accommodate the max widths of the XferSize and PktCnt
23978 +        * fields in the HCTSIZn register.
23979 +        */
23980 +       hc->do_ping = qh->ping_state;
23981 +#ifdef HW2937_WORKAROUND
23982 +       hc->ep_is_in = ep_is_in;
23983 +#else
23984 +       hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
23985 +#endif
23986 +       hc->data_pid_start = qh->data_toggle;
23987 +       hc->multi_count = 1;
23988 +
23989 +       if (hcd->core_if->dma_enable) {
23990 +               hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
23991 +       
23992 +               /* For non-dword aligned case */
23993 +               if (((uint32_t)hc->xfer_buff & 0x3) && !hcd->core_if->dma_desc_enable) {
23994 +                       ptr = (uint8_t *) urb->buf + urb->actual_length;
23995 +               }
23996 +       } else {
23997 +               hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
23998 +       }
23999 +       hc->xfer_len = urb->length - urb->actual_length;
24000 +       hc->xfer_count = 0;
24001 +
24002 +       /*
24003 +        * Set the split attributes
24004 +        */
24005 +       hc->do_split = 0;
24006 +       if (qh->do_split) {
24007 +               uint32_t hub_addr, port_addr;
24008 +               hc->do_split = 1;
24009 +               hc->xact_pos = qtd->isoc_split_pos;
24010 +               hc->complete_split = qtd->complete_split;
24011 +               hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
24012 +               hc->hub_addr = (uint8_t) hub_addr;
24013 +               hc->port_addr = (uint8_t) port_addr;
24014 +       }
24015 +
24016 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
24017 +       case UE_CONTROL:
24018 +               hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
24019 +               switch (qtd->control_phase) {
24020 +               case DWC_OTG_CONTROL_SETUP:
24021 +                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction\n");
24022 +                       hc->do_ping = 0;
24023 +                       hc->ep_is_in = 0;
24024 +                       hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
24025 +                       if (hcd->core_if->dma_enable) {
24026 +                               hc->xfer_buff = (uint8_t *) urb->setup_dma;
24027 +                       } else {
24028 +                               hc->xfer_buff = (uint8_t *) urb->setup_packet;
24029 +                       }
24030 +                       hc->xfer_len = 8;
24031 +                       ptr = NULL;
24032 +                       break;
24033 +               case DWC_OTG_CONTROL_DATA:
24034 +                       DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
24035 +                       hc->data_pid_start = qtd->data_toggle;
24036 +                       break;
24037 +               case DWC_OTG_CONTROL_STATUS:
24038 +                       /*
24039 +                        * Direction is opposite of data direction or IN if no
24040 +                        * data.
24041 +                        */
24042 +                       DWC_DEBUGPL(DBG_HCDV, "  Control status transaction\n");
24043 +                       if (urb->length == 0) {
24044 +                               hc->ep_is_in = 1;
24045 +                       } else {
24046 +                               hc->ep_is_in =
24047 +                                   dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
24048 +                       }
24049 +                       if (hc->ep_is_in) {
24050 +                               hc->do_ping = 0;
24051 +                       }
24052 +                       
24053 +                       hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
24054 +
24055 +                       hc->xfer_len = 0;
24056 +                       if (hcd->core_if->dma_enable) {
24057 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
24058 +                       } else {
24059 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf;
24060 +                       }
24061 +                       ptr = NULL;
24062 +                       break;
24063 +               }
24064 +               break;
24065 +       case UE_BULK:
24066 +               hc->ep_type = DWC_OTG_EP_TYPE_BULK;
24067 +               break;
24068 +       case UE_INTERRUPT:
24069 +               hc->ep_type = DWC_OTG_EP_TYPE_INTR;
24070 +               break;
24071 +       case UE_ISOCHRONOUS:
24072 +               {
24073 +                       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
24074 +                       
24075 +                       hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
24076 +                       
24077 +                       if (hcd->core_if->dma_desc_enable)
24078 +                               break;
24079 +                               
24080 +                       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
24081 +                       
24082 +                       frame_desc->status = 0;
24083 +                       
24084 +                       if (hcd->core_if->dma_enable) {
24085 +                               hc->xfer_buff = (uint8_t *) urb->dma;
24086 +                       } else {
24087 +                               hc->xfer_buff = (uint8_t *) urb->buf;
24088 +                       }
24089 +                       hc->xfer_buff +=
24090 +                           frame_desc->offset + qtd->isoc_split_offset;
24091 +                       hc->xfer_len =
24092 +                           frame_desc->length - qtd->isoc_split_offset;
24093 +
24094 +                       /* For non-dword aligned buffers */
24095 +                       if (((uint32_t)hc->xfer_buff & 0x3) && hcd->core_if->dma_enable) {
24096 +                               ptr = (uint8_t *) urb->buf + frame_desc->offset + qtd->isoc_split_offset;
24097 +                       }       
24098 +                       else
24099 +                           ptr = NULL;
24100 +                       
24101 +                       if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
24102 +                               if (hc->xfer_len <= 188) {
24103 +                                       hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
24104 +                               } else {
24105 +                                       hc->xact_pos =
24106 +                                           DWC_HCSPLIT_XACTPOS_BEGIN;
24107 +                               }
24108 +                       }
24109 +               }
24110 +               break;
24111 +       }
24112 +       /* non DWORD-aligned buffer case */     
24113 +       if (ptr) {
24114 +               uint32_t buf_size;
24115 +               if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
24116 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
24117 +               } else {                                
24118 +                       buf_size = 4096;
24119 +               }
24120 +               if (!qh->dw_align_buf) {
24121 +                       qh->dw_align_buf =
24122 +                                dwc_dma_alloc_atomic(buf_size,
24123 +                                                     &qh->dw_align_buf_dma);
24124 +                       if (!qh->dw_align_buf) {
24125 +                               DWC_ERROR("%s: Failed to allocate memory to handle "
24126 +                                         "non-dword aligned buffer case\n", __func__);
24127 +#ifdef HW2937_WORKAROUND
24128 +                               return 0;
24129 +#else
24130 +                               return;
24131 +#endif
24132 +                       }
24133 +               }
24134 +               if (!hc->ep_is_in) {
24135 +                       dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
24136 +               }
24137 +               hc->align_buff = qh->dw_align_buf_dma;
24138 +       }
24139 +       else {
24140 +               hc->align_buff = 0;
24141 +       }
24142 +
24143 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
24144 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
24145 +               /*
24146 +                * This value may be modified when the transfer is started to
24147 +                * reflect the actual transfer length.
24148 +                */
24149 +               hc->multi_count = dwc_hb_mult(qh->maxp);
24150 +       }
24151 +       
24152 +       if (hcd->core_if->dma_desc_enable)
24153 +               hc->desc_list_addr = qh->desc_list_dma;
24154 +       
24155 +       dwc_otg_hc_init(hcd->core_if, hc);
24156 +       hc->qh = qh;
24157 +#ifdef HW2937_WORKAROUND
24158 +       hcd->hw2937_assigned_channels |= (1 << hc->hc_num);
24159 +       DWC_DEBUGPL(DBG_HW2937, " assign %d -> hw2937_ac %x\n", hc->hc_num, hcd->hw2937_assigned_channels);
24160 +       return 1;
24161 +#endif
24162 +}
24163 +
24164 +#ifdef HW2937_WORKAROUND
24165 +
24166 +void debug_halt(void)
24167 +{
24168 +       spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
24169 +       unsigned long flags;
24170 +       extern void v6_flush_kern_cache_all(void);
24171 +
24172 +       spin_lock_irqsave(&mr_lock, flags);
24173 +#ifdef CONFIG_MACH_BCM2708
24174 +       v6_flush_kern_cache_all();
24175 +#endif
24176 +       while (1) continue;
24177 +}
24178 +
24179 +static
24180 +void dwc_otg_hcd_disable_in_channels(dwc_otg_hcd_t * hcd)
24181 +{
24182 +       int num_channels = hcd->core_if->core_params->host_channels;
24183 +       static int stall_count = 0;
24184 +       static int max_stall_count = 1;
24185 +       static int last_stalled = 0;
24186 +       int stalled = 0;
24187 +       int i;
24188 +
24189 +       DWC_DEBUGPL(DBG_HW2937, "  Disable In Channels(%x)\n", hcd->hw2937_assigned_channels);
24190 +
24191 +       for (i = 0; i < num_channels; i++) {
24192 +               if (hcd->hw2937_assigned_channels & (1 << i)) {
24193 +                       dwc_hc_t *hc = hcd->hc_ptr_array[i];
24194 +                       if (!hc->halt_pending) {
24195 +                               dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
24196 +                               hctsiz_data_t hctsiz;
24197 +                               hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
24198 +                               DWC_DEBUGPL(DBG_HW2937, "pktcnt %d, xfersize %x, xfer_len %x\n", hctsiz.b.pktcnt, hctsiz.b.xfersize, hc->xfer_len);
24199 +                               if (hctsiz.b.pktcnt == hc->start_pkt_count)
24200 +                               {
24201 +                                       dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_PAUSE_IN);
24202 +                               }
24203 +                               else
24204 +                               {
24205 +                                       /* Unless a receive is in progress */
24206 +                                       stalled |= (1<<i);
24207 +                               }
24208 +                       } else {
24209 +                               stalled |= (1<<i);
24210 +                       }
24211 +               }
24212 +       }
24213 +
24214 +       if (stalled && (stalled == last_stalled))
24215 +       {
24216 +               stall_count++;
24217 +               if (stall_count > max_stall_count)
24218 +               {
24219 +                       max_stall_count = stall_count;
24220 +                       DWC_PRINTF( "stall (%x) count -> %d\n", stalled, stall_count);
24221 +                       if (stall_count == 10)
24222 +                       {
24223 +                               debug_halt();
24224 +                       }
24225 +               }
24226 +       }
24227 +       else
24228 +       {
24229 +               stall_count = 0;
24230 +               last_stalled = stalled;
24231 +       }
24232 +}
24233 +
24234 +static
24235 +int dwc_otg_hcd_update_transaction_mode(dwc_otg_hcd_t * hcd)
24236 +{
24237 +       dwc_list_link_t *qh_ptr;
24238 +       dwc_otg_qh_t *qh;
24239 +       dwc_otg_qtd_t *qtd;
24240 +       dwc_otg_hcd_urb_t *urb;
24241 +       int found_in = 0;
24242 +
24243 +        /* If there are any existing out transactions, stay in OUT mode */
24244 +       if (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_OUT)
24245 +       {
24246 +               return 1;
24247 +       }
24248 +
24249 +       /* Scan entries in the periodic ready list. */
24250 +       qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
24251 +
24252 +       while (qh_ptr != &hcd->periodic_sched_ready) {
24253 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
24254 +               qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
24255 +               urb = qtd->urb;
24256 +               if (!dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) {
24257 +                       /* Switch to OUT mode */
24258 +                       switch (hcd->hw2937_xfer_mode)
24259 +                       {
24260 +                       case HW2937_XFER_MODE_IDLE:
24261 +                               DWC_DEBUGPL(DBG_HW2937, "utm -> OUT\n");
24262 +                               hcd->hw2937_xfer_mode = HW2937_XFER_MODE_OUT;
24263 +                               /* Drop through... */
24264 +                       case HW2937_XFER_MODE_OUT:
24265 +                               return 1;
24266 +                       case HW2937_XFER_MODE_IN:
24267 +                               DWC_DEBUGPL(DBG_HW2937, "utm - halting %x INs\n", hcd->hw2937_assigned_channels);
24268 +                               /* Disable the channels with outstanding INs */
24269 +                               dwc_otg_hcd_disable_in_channels(hcd);
24270 +                               
24271 +                               DWC_DEBUGPL(DBG_HW2937, "utm -> PAUSEIN\n");
24272 +                               hcd->hw2937_xfer_mode = HW2937_XFER_MODE_PAUSEIN;
24273 +                               /* Drop through... */
24274 +                       case HW2937_XFER_MODE_PAUSEIN:
24275 +                               /* Delay until the halt completes */
24276 +                               return 0;
24277 +                       }
24278 +               }
24279 +               found_in = 1;
24280 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
24281 +       }
24282 +
24283 +       /*
24284 +        * Scan entries in the inactive portion of the non-periodic
24285 +        * schedule.
24286 +        */
24287 +       qh_ptr = hcd->non_periodic_sched_inactive.next;
24288 +       while (qh_ptr != &hcd->non_periodic_sched_inactive) {
24289 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
24290 +               qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
24291 +               urb = qtd->urb;
24292 +               if (!dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) {
24293 +                       /* Switch to OUT mode */
24294 +                       switch (hcd->hw2937_xfer_mode)
24295 +                       {
24296 +                       case HW2937_XFER_MODE_IDLE:
24297 +                               DWC_DEBUGPL(DBG_HW2937, "utm -> OUT\n");
24298 +                               hcd->hw2937_xfer_mode = HW2937_XFER_MODE_OUT;
24299 +                               /* Drop through... */
24300 +                       case HW2937_XFER_MODE_OUT:
24301 +                               return 1;
24302 +                       case HW2937_XFER_MODE_IN:
24303 +                               DWC_DEBUGPL(DBG_HW2937, "utm - halting %x INs\n", hcd->hw2937_assigned_channels);
24304 +                               /* Disable the channels with outstanding INs */
24305 +                               dwc_otg_hcd_disable_in_channels(hcd);
24306 +                               
24307 +                               DWC_DEBUGPL(DBG_HW2937, "utm -> PAUSEIN\n");
24308 +                               hcd->hw2937_xfer_mode = HW2937_XFER_MODE_PAUSEIN;
24309 +                               /* Drop through... */
24310 +                       case HW2937_XFER_MODE_PAUSEIN:
24311 +                               /* Delay until the halt completes */
24312 +                               return 0;
24313 +                       }
24314 +               }
24315 +               found_in = 1;
24316 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
24317 +       }
24318 +
24319 +       if (found_in && (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_IDLE))
24320 +       {
24321 +               DWC_DEBUGPL(DBG_HW2937, "utm -> IN\n");
24322 +               hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IN;
24323 +       }
24324 +       return 1;
24325 +}
24326 +
24327 +#endif /* HW2937_WORKAROUND */
24328 +
24329 +/**
24330 + * This function selects transactions from the HCD transfer schedule and
24331 + * assigns them to available host channels. It is called from HCD interrupt
24332 + * handler functions.
24333 + *
24334 + * @param hcd The HCD state structure.
24335 + *
24336 + * @return The types of new transactions that were assigned to host channels.
24337 + */
24338 +dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
24339 +{
24340 +       dwc_list_link_t *qh_ptr;
24341 +       dwc_otg_qh_t *qh;
24342 +       int num_channels;
24343 +       dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
24344 +
24345 +#ifdef DEBUG_SOF
24346 +       DWC_DEBUGPL(DBG_HCD, "  Select Transactions\n");
24347 +#endif
24348 +
24349 +#ifdef HW2937_WORKAROUND
24350 +       if (!dwc_otg_hcd_update_transaction_mode(hcd))
24351 +       {
24352 +               return ret_val;
24353 +       }
24354 +#endif
24355 +
24356 +       /* Process entries in the periodic ready list. */
24357 +       qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
24358 +
24359 +       while (qh_ptr != &hcd->periodic_sched_ready &&
24360 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
24361 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
24362 +#ifdef HW2937_WORKAROUND
24363 +               if (assign_and_init_hc(hcd, qh)) {
24364 +#else
24365 +               assign_and_init_hc(hcd, qh);
24366 +#endif
24367 +
24368 +               /*
24369 +                * Move the QH from the periodic ready schedule to the
24370 +                * periodic assigned schedule.
24371 +                */
24372 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
24373 +               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
24374 +                                  &qh->qh_list_entry);
24375 +
24376 +               ret_val = DWC_OTG_TRANSACTION_PERIODIC;
24377 +#ifdef HW2937_WORKAROUND
24378 +               } else {
24379 +                       qh_ptr = DWC_LIST_NEXT(qh_ptr);
24380 +               }
24381 +#endif
24382 +       }
24383 +
24384 +       /*
24385 +        * Process entries in the inactive portion of the non-periodic
24386 +        * schedule. Some free host channels may not be used if they are
24387 +        * reserved for periodic transfers.
24388 +        */
24389 +       qh_ptr = hcd->non_periodic_sched_inactive.next;
24390 +       num_channels = hcd->core_if->core_params->host_channels;
24391 +       while (qh_ptr != &hcd->non_periodic_sched_inactive &&
24392 +              (hcd->non_periodic_channels <
24393 +               num_channels - hcd->periodic_channels) &&
24394 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
24395 +
24396 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
24397 +
24398 +#ifdef HW2937_WORKAROUND
24399 +               if (assign_and_init_hc(hcd, qh)) {
24400 +#else
24401 +               assign_and_init_hc(hcd, qh);
24402 +#endif
24403 +
24404 +               /*
24405 +                * Move the QH from the non-periodic inactive schedule to the
24406 +                * non-periodic active schedule.
24407 +                */
24408 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
24409 +               DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
24410 +                                  &qh->qh_list_entry);
24411 +
24412 +               if (ret_val == DWC_OTG_TRANSACTION_NONE) {
24413 +                       ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
24414 +               } else {
24415 +                       ret_val = DWC_OTG_TRANSACTION_ALL;
24416 +               }
24417 +
24418 +               hcd->non_periodic_channels++;
24419 +#ifdef HW2937_WORKAROUND
24420 +               } else {
24421 +                       qh_ptr = DWC_LIST_NEXT(qh_ptr);
24422 +               }
24423 +#endif
24424 +       }
24425 +
24426 +       return ret_val;
24427 +}
24428 +/**
24429 + * Attempts to queue a single transaction request for a host channel
24430 + * associated with either a periodic or non-periodic transfer. This function
24431 + * assumes that there is space available in the appropriate request queue. For
24432 + * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
24433 + * is available in the appropriate Tx FIFO.
24434 + *
24435 + * @param hcd The HCD state structure.
24436 + * @param hc Host channel descriptor associated with either a periodic or
24437 + * non-periodic transfer.
24438 + * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
24439 + * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
24440 + * transfers.
24441 + *
24442 + * @return 1 if a request is queued and more requests may be needed to
24443 + * complete the transfer, 0 if no more requests are required for this
24444 + * transfer, -1 if there is insufficient space in the Tx FIFO.
24445 + */
24446 +static int queue_transaction(dwc_otg_hcd_t * hcd,
24447 +                            dwc_hc_t * hc, uint16_t fifo_dwords_avail)
24448 +{
24449 +       int retval;
24450 +
24451 +       if (hcd->core_if->dma_enable) {
24452 +               if (hcd->core_if->dma_desc_enable) {
24453 +                       if (!hc->xfer_started || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {       
24454 +                               dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
24455 +                               hc->qh->ping_state = 0;
24456 +                       }
24457 +               }
24458 +               else if (!hc->xfer_started) {
24459 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
24460 +                       hc->qh->ping_state = 0;
24461 +               }
24462 +               retval = 0;
24463 +       } else if (hc->halt_pending) {
24464 +               /* Don't queue a request if the channel has been halted. */
24465 +               retval = 0;
24466 +       } else if (hc->halt_on_queue) {
24467 +               dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
24468 +               retval = 0;
24469 +       } else if (hc->do_ping) {
24470 +               if (!hc->xfer_started) {
24471 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
24472 +               }
24473 +               retval = 0;
24474 +       } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
24475 +               if ((fifo_dwords_avail * 4) >= hc->max_packet) {
24476 +                       if (!hc->xfer_started) {
24477 +                               dwc_otg_hc_start_transfer(hcd->core_if, hc);
24478 +                               retval = 1;
24479 +                       } else {
24480 +                               retval =
24481 +                                   dwc_otg_hc_continue_transfer(hcd->core_if,
24482 +                                                                hc);
24483 +                       }
24484 +               } else {
24485 +                       retval = -1;
24486 +               }
24487 +       } else {
24488 +               if (!hc->xfer_started) {
24489 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
24490 +                       retval = 1;
24491 +               } else {
24492 +                       retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
24493 +               }
24494 +       }
24495 +
24496 +       return retval;
24497 +}
24498 +
24499 +/**
24500 + * Processes periodic channels for the next frame and queues transactions for
24501 + * these channels to the DWC_otg controller. After queueing transactions, the
24502 + * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
24503 + * to queue as Periodic Tx FIFO or request queue space becomes available.
24504 + * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
24505 + */
24506 +static void process_periodic_channels(dwc_otg_hcd_t * hcd)
24507 +{
24508 +       hptxsts_data_t tx_status;
24509 +       dwc_list_link_t *qh_ptr;
24510 +       dwc_otg_qh_t *qh;
24511 +       int status;
24512 +       int no_queue_space = 0;
24513 +       int no_fifo_space = 0;
24514 +
24515 +       dwc_otg_host_global_regs_t *host_regs;
24516 +       host_regs = hcd->core_if->host_if->host_global_regs;
24517 +
24518 +       DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
24519 +#ifdef DEBUG
24520 +       tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts);
24521 +       DWC_DEBUGPL(DBG_HCDV,
24522 +                   "  P Tx Req Queue Space Avail (before queue): %d\n",
24523 +                   tx_status.b.ptxqspcavail);
24524 +       DWC_DEBUGPL(DBG_HCDV, "  P Tx FIFO Space Avail (before queue): %d\n",
24525 +                   tx_status.b.ptxfspcavail);
24526 +#endif
24527 +
24528 +       qh_ptr = hcd->periodic_sched_assigned.next;
24529 +       while (qh_ptr != &hcd->periodic_sched_assigned) {
24530 +               tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts);
24531 +               if (tx_status.b.ptxqspcavail == 0) {
24532 +                       no_queue_space = 1;
24533 +                       break;
24534 +               }
24535 +
24536 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
24537 +
24538 +               /*
24539 +                * Set a flag if we're queuing high-bandwidth in slave mode.
24540 +                * The flag prevents any halts to get into the request queue in
24541 +                * the middle of multiple high-bandwidth packets getting queued.
24542 +                */
24543 +               if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
24544 +                       hcd->core_if->queuing_high_bandwidth = 1;
24545 +               }
24546 +               status =
24547 +                   queue_transaction(hcd, qh->channel,
24548 +                                     tx_status.b.ptxfspcavail);
24549 +               if (status < 0) {
24550 +                       no_fifo_space = 1;
24551 +                       break;
24552 +               }
24553 +
24554 +               /*
24555 +                * In Slave mode, stay on the current transfer until there is
24556 +                * nothing more to do or the high-bandwidth request count is
24557 +                * reached. In DMA mode, only need to queue one request. The
24558 +                * controller automatically handles multiple packets for
24559 +                * high-bandwidth transfers.
24560 +                */
24561 +               if (hcd->core_if->dma_enable || status == 0 ||
24562 +                   qh->channel->requests == qh->channel->multi_count) {
24563 +                       qh_ptr = qh_ptr->next;
24564 +                       /*
24565 +                        * Move the QH from the periodic assigned schedule to
24566 +                        * the periodic queued schedule.
24567 +                        */
24568 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
24569 +                                          &qh->qh_list_entry);
24570 +
24571 +                       /* done queuing high bandwidth */
24572 +                       hcd->core_if->queuing_high_bandwidth = 0;
24573 +               }
24574 +       }
24575 +
24576 +       if (!hcd->core_if->dma_enable) {
24577 +               dwc_otg_core_global_regs_t *global_regs;
24578 +               gintmsk_data_t intr_mask = {.d32 = 0 };
24579 +
24580 +               global_regs = hcd->core_if->core_global_regs;
24581 +               intr_mask.b.ptxfempty = 1;
24582 +#ifdef DEBUG
24583 +               tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts);
24584 +               DWC_DEBUGPL(DBG_HCDV,
24585 +                           "  P Tx Req Queue Space Avail (after queue): %d\n",
24586 +                           tx_status.b.ptxqspcavail);
24587 +               DWC_DEBUGPL(DBG_HCDV,
24588 +                           "  P Tx FIFO Space Avail (after queue): %d\n",
24589 +                           tx_status.b.ptxfspcavail);
24590 +#endif
24591 +               if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
24592 +                   no_queue_space || no_fifo_space) {
24593 +                       /*
24594 +                        * May need to queue more transactions as the request
24595 +                        * queue or Tx FIFO empties. Enable the periodic Tx
24596 +                        * FIFO empty interrupt. (Always use the half-empty
24597 +                        * level to ensure that new requests are loaded as
24598 +                        * soon as possible.)
24599 +                        */
24600 +                       dwc_modify_reg32(&global_regs->gintmsk, 0,
24601 +                                        intr_mask.d32);
24602 +               } else {
24603 +                       /*
24604 +                        * Disable the Tx FIFO empty interrupt since there are
24605 +                        * no more transactions that need to be queued right
24606 +                        * now. This function is called from interrupt
24607 +                        * handlers to queue more transactions as transfer
24608 +                        * states change.
24609 +                        */
24610 +                       dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32,
24611 +                                        0);
24612 +               }
24613 +       }
24614 +}
24615 +
24616 +/**
24617 + * Processes active non-periodic channels and queues transactions for these
24618 + * channels to the DWC_otg controller. After queueing transactions, the NP Tx
24619 + * FIFO Empty interrupt is enabled if there are more transactions to queue as
24620 + * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
24621 + * FIFO Empty interrupt is disabled.
24622 + */
24623 +static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
24624 +{
24625 +       gnptxsts_data_t tx_status;
24626 +       dwc_list_link_t *orig_qh_ptr;
24627 +       dwc_otg_qh_t *qh;
24628 +       int status;
24629 +       int no_queue_space = 0;
24630 +       int no_fifo_space = 0;
24631 +       int more_to_do = 0;
24632 +
24633 +       dwc_otg_core_global_regs_t *global_regs =
24634 +           hcd->core_if->core_global_regs;
24635 +
24636 +       DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
24637 +#ifdef DEBUG
24638 +       tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts);
24639 +       DWC_DEBUGPL(DBG_HCDV,
24640 +                   "  NP Tx Req Queue Space Avail (before queue): %d\n",
24641 +                   tx_status.b.nptxqspcavail);
24642 +       DWC_DEBUGPL(DBG_HCDV, "  NP Tx FIFO Space Avail (before queue): %d\n",
24643 +                   tx_status.b.nptxfspcavail);
24644 +#endif
24645 +       /*
24646 +        * Keep track of the starting point. Skip over the start-of-list
24647 +        * entry.
24648 +        */
24649 +       if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
24650 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
24651 +       }
24652 +       orig_qh_ptr = hcd->non_periodic_qh_ptr;
24653 +
24654 +       /*
24655 +        * Process once through the active list or until no more space is
24656 +        * available in the request queue or the Tx FIFO.
24657 +        */
24658 +       do {
24659 +               tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts);
24660 +               if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
24661 +                       no_queue_space = 1;
24662 +                       break;
24663 +               }
24664 +
24665 +               qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
24666 +                                   qh_list_entry);
24667 +               status =
24668 +                   queue_transaction(hcd, qh->channel,
24669 +                                     tx_status.b.nptxfspcavail);
24670 +
24671 +               if (status > 0) {
24672 +                       more_to_do = 1;
24673 +               } else if (status < 0) {
24674 +                       no_fifo_space = 1;
24675 +                       break;
24676 +               }
24677 +
24678 +               /* Advance to next QH, skipping start-of-list entry. */
24679 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
24680 +               if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
24681 +                       hcd->non_periodic_qh_ptr =
24682 +                           hcd->non_periodic_qh_ptr->next;
24683 +               }
24684 +
24685 +       } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
24686 +
24687 +       if (!hcd->core_if->dma_enable) {
24688 +               gintmsk_data_t intr_mask = {.d32 = 0 };
24689 +               intr_mask.b.nptxfempty = 1;
24690 +
24691 +#ifdef DEBUG
24692 +               tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts);
24693 +               DWC_DEBUGPL(DBG_HCDV,
24694 +                           "  NP Tx Req Queue Space Avail (after queue): %d\n",
24695 +                           tx_status.b.nptxqspcavail);
24696 +               DWC_DEBUGPL(DBG_HCDV,
24697 +                           "  NP Tx FIFO Space Avail (after queue): %d\n",
24698 +                           tx_status.b.nptxfspcavail);
24699 +#endif
24700 +               if (more_to_do || no_queue_space || no_fifo_space) {
24701 +                       /*
24702 +                        * May need to queue more transactions as the request
24703 +                        * queue or Tx FIFO empties. Enable the non-periodic
24704 +                        * Tx FIFO empty interrupt. (Always use the half-empty
24705 +                        * level to ensure that new requests are loaded as
24706 +                        * soon as possible.)
24707 +                        */
24708 +                       dwc_modify_reg32(&global_regs->gintmsk, 0,
24709 +                                        intr_mask.d32);
24710 +               } else {
24711 +                       /*
24712 +                        * Disable the Tx FIFO empty interrupt since there are
24713 +                        * no more transactions that need to be queued right
24714 +                        * now. This function is called from interrupt
24715 +                        * handlers to queue more transactions as transfer
24716 +                        * states change.
24717 +                        */
24718 +                       dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32,
24719 +                                        0);
24720 +               }
24721 +       }
24722 +}
24723 +
24724 +/**
24725 + * This function processes the currently active host channels and queues
24726 + * transactions for these channels to the DWC_otg controller. It is called
24727 + * from HCD interrupt handler functions.
24728 + *
24729 + * @param hcd The HCD state structure.
24730 + * @param tr_type The type(s) of transactions to queue (non-periodic,
24731 + * periodic, or both).
24732 + */
24733 +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
24734 +                                          dwc_otg_transaction_type_e tr_type)
24735 +{
24736 +#ifdef DEBUG_SOF
24737 +       DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
24738 +#endif
24739 +       /* Process host channels associated with periodic transfers. */
24740 +       if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
24741 +            tr_type == DWC_OTG_TRANSACTION_ALL) &&
24742 +           !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
24743 +
24744 +               process_periodic_channels(hcd);
24745 +       }
24746 +
24747 +       /* Process host channels associated with non-periodic transfers. */
24748 +       if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
24749 +           tr_type == DWC_OTG_TRANSACTION_ALL) {
24750 +               if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
24751 +                       process_non_periodic_channels(hcd);
24752 +               } else {
24753 +                       /*
24754 +                        * Ensure NP Tx FIFO empty interrupt is disabled when
24755 +                        * there are no non-periodic transfers to process.
24756 +                        */
24757 +                       gintmsk_data_t gintmsk = {.d32 = 0 };
24758 +                       gintmsk.b.nptxfempty = 1;
24759 +                       dwc_modify_reg32(&hcd->core_if->core_global_regs->
24760 +                                        gintmsk, gintmsk.d32, 0);
24761 +               }
24762 +       }
24763 +}
24764
24765 +#ifdef DWC_HS_ELECT_TST
24766 +/*
24767 + * Quick and dirty hack to implement the HS Electrical Test
24768 + * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
24769 + *
24770 + * This code was copied from our userspace app "hset". It sends a
24771 + * Get Device Descriptor control sequence in two parts, first the
24772 + * Setup packet by itself, followed some time later by the In and
24773 + * Ack packets. Rather than trying to figure out how to add this
24774 + * functionality to the normal driver code, we just hijack the
24775 + * hardware, using these two function to drive the hardware
24776 + * directly.
24777 + */
24778 +
24779 +static dwc_otg_core_global_regs_t *global_regs;
24780 +static dwc_otg_host_global_regs_t *hc_global_regs;
24781 +static dwc_otg_hc_regs_t *hc_regs;
24782 +static uint32_t *data_fifo;
24783 +
24784 +static void do_setup(void)
24785 +{
24786 +       gintsts_data_t gintsts;
24787 +       hctsiz_data_t hctsiz;
24788 +       hcchar_data_t hcchar;
24789 +       haint_data_t haint;
24790 +       hcint_data_t hcint;
24791 +
24792 +       /* Enable HAINTs */
24793 +       dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001);
24794 +
24795 +       /* Enable HCINTs */
24796 +       dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3);
24797 +
24798 +       /* Read GINTSTS */
24799 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24800 +
24801 +       /* Read HAINT */
24802 +       haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
24803 +
24804 +       /* Read HCINT */
24805 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
24806 +
24807 +       /* Read HCCHAR */
24808 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24809 +
24810 +       /* Clear HCINT */
24811 +       dwc_write_reg32(&hc_regs->hcint, hcint.d32);
24812 +
24813 +       /* Clear HAINT */
24814 +       dwc_write_reg32(&hc_global_regs->haint, haint.d32);
24815 +
24816 +       /* Clear GINTSTS */
24817 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
24818 +
24819 +       /* Read GINTSTS */
24820 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24821 +
24822 +       /*
24823 +        * Send Setup packet (Get Device Descriptor)
24824 +        */
24825 +
24826 +       /* Make sure channel is disabled */
24827 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24828 +       if (hcchar.b.chen) {
24829 +               hcchar.b.chdis = 1;
24830 +//              hcchar.b.chen = 1;
24831 +               dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
24832 +               //sleep(1);
24833 +               dwc_mdelay(1000);
24834 +
24835 +               /* Read GINTSTS */
24836 +               gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24837 +
24838 +               /* Read HAINT */
24839 +               haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
24840 +
24841 +               /* Read HCINT */
24842 +               hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
24843 +
24844 +               /* Read HCCHAR */
24845 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24846 +
24847 +               /* Clear HCINT */
24848 +               dwc_write_reg32(&hc_regs->hcint, hcint.d32);
24849 +
24850 +               /* Clear HAINT */
24851 +               dwc_write_reg32(&hc_global_regs->haint, haint.d32);
24852 +
24853 +               /* Clear GINTSTS */
24854 +               dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
24855 +
24856 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24857 +       }
24858 +
24859 +       /* Set HCTSIZ */
24860 +       hctsiz.d32 = 0;
24861 +       hctsiz.b.xfersize = 8;
24862 +       hctsiz.b.pktcnt = 1;
24863 +       hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
24864 +       dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
24865 +
24866 +       /* Set HCCHAR */
24867 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24868 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
24869 +       hcchar.b.epdir = 0;
24870 +       hcchar.b.epnum = 0;
24871 +       hcchar.b.mps = 8;
24872 +       hcchar.b.chen = 1;
24873 +       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
24874 +
24875 +       /* Fill FIFO with Setup data for Get Device Descriptor */
24876 +       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
24877 +       dwc_write_reg32(data_fifo++, 0x01000680);
24878 +       dwc_write_reg32(data_fifo++, 0x00080000);
24879 +
24880 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24881 +
24882 +       /* Wait for host channel interrupt */
24883 +       do {
24884 +               gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24885 +       } while (gintsts.b.hcintr == 0);
24886 +
24887 +
24888 +       /* Disable HCINTs */
24889 +       dwc_write_reg32(&hc_regs->hcintmsk, 0x0000);
24890 +
24891 +       /* Disable HAINTs */
24892 +       dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000);
24893 +
24894 +       /* Read HAINT */
24895 +       haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
24896 +
24897 +       /* Read HCINT */
24898 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
24899 +
24900 +       /* Read HCCHAR */
24901 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24902 +
24903 +       /* Clear HCINT */
24904 +       dwc_write_reg32(&hc_regs->hcint, hcint.d32);
24905 +
24906 +       /* Clear HAINT */
24907 +       dwc_write_reg32(&hc_global_regs->haint, haint.d32);
24908 +
24909 +       /* Clear GINTSTS */
24910 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
24911 +
24912 +       /* Read GINTSTS */
24913 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24914 +}
24915 +
24916 +static void do_in_ack(void)
24917 +{
24918 +       gintsts_data_t gintsts;
24919 +       hctsiz_data_t hctsiz;
24920 +       hcchar_data_t hcchar;
24921 +       haint_data_t haint;
24922 +       hcint_data_t hcint;
24923 +       host_grxsts_data_t grxsts;
24924 +
24925 +       /* Enable HAINTs */
24926 +       dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001);
24927 +
24928 +       /* Enable HCINTs */
24929 +       dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3);
24930 +
24931 +       /* Read GINTSTS */
24932 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24933 +
24934 +       /* Read HAINT */
24935 +       haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
24936 +
24937 +       /* Read HCINT */
24938 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
24939 +
24940 +       /* Read HCCHAR */
24941 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24942 +
24943 +       /* Clear HCINT */
24944 +       dwc_write_reg32(&hc_regs->hcint, hcint.d32);
24945 +
24946 +       /* Clear HAINT */
24947 +       dwc_write_reg32(&hc_global_regs->haint, haint.d32);
24948 +
24949 +       /* Clear GINTSTS */
24950 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
24951 +
24952 +       /* Read GINTSTS */
24953 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24954 +
24955 +       /*
24956 +        * Receive Control In packet
24957 +        */
24958 +
24959 +       /* Make sure channel is disabled */
24960 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24961 +       if (hcchar.b.chen) {
24962 +               hcchar.b.chdis = 1;
24963 +               hcchar.b.chen = 1;
24964 +               dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
24965 +               //sleep(1);
24966 +               dwc_mdelay(1000);
24967 +
24968 +               /* Read GINTSTS */
24969 +               gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
24970 +
24971 +               /* Read HAINT */
24972 +               haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
24973 +
24974 +               /* Read HCINT */
24975 +               hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
24976 +
24977 +               /* Read HCCHAR */
24978 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24979 +
24980 +               /* Clear HCINT */
24981 +               dwc_write_reg32(&hc_regs->hcint, hcint.d32);
24982 +
24983 +               /* Clear HAINT */
24984 +               dwc_write_reg32(&hc_global_regs->haint, haint.d32);
24985 +
24986 +               /* Clear GINTSTS */
24987 +               dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
24988 +
24989 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
24990 +       }
24991 +
24992 +       /* Set HCTSIZ */
24993 +       hctsiz.d32 = 0;
24994 +       hctsiz.b.xfersize = 8;
24995 +       hctsiz.b.pktcnt = 1;
24996 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
24997 +       dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
24998 +
24999 +       /* Set HCCHAR */
25000 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
25001 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
25002 +       hcchar.b.epdir = 1;
25003 +       hcchar.b.epnum = 0;
25004 +       hcchar.b.mps = 8;
25005 +       hcchar.b.chen = 1;
25006 +       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
25007 +
25008 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25009 +
25010 +       /* Wait for receive status queue interrupt */
25011 +       do {
25012 +               gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25013 +       } while (gintsts.b.rxstsqlvl == 0);
25014 +
25015 +
25016 +       /* Read RXSTS */
25017 +       grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp);
25018 +
25019 +       /* Clear RXSTSQLVL in GINTSTS */
25020 +       gintsts.d32 = 0;
25021 +       gintsts.b.rxstsqlvl = 1;
25022 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
25023 +
25024 +       switch (grxsts.b.pktsts) {
25025 +       case DWC_GRXSTS_PKTSTS_IN:
25026 +               /* Read the data into the host buffer */
25027 +               if (grxsts.b.bcnt > 0) {
25028 +                       int i;
25029 +                       int word_count = (grxsts.b.bcnt + 3) / 4;
25030 +
25031 +                       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
25032 +
25033 +                       for (i = 0; i < word_count; i++) {
25034 +                               (void)dwc_read_reg32(data_fifo++);
25035 +                       }
25036 +               }
25037 +               break;
25038 +
25039 +       default:
25040 +               break;
25041 +       }
25042 +
25043 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25044 +
25045 +       /* Wait for receive status queue interrupt */
25046 +       do {
25047 +               gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25048 +       } while (gintsts.b.rxstsqlvl == 0);
25049 +
25050 +
25051 +       /* Read RXSTS */
25052 +       grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp);
25053 +
25054 +       /* Clear RXSTSQLVL in GINTSTS */
25055 +       gintsts.d32 = 0;
25056 +       gintsts.b.rxstsqlvl = 1;
25057 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
25058 +
25059 +       switch (grxsts.b.pktsts) {
25060 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
25061 +               break;
25062 +
25063 +       default:
25064 +               break;
25065 +       }
25066 +
25067 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25068 +
25069 +       /* Wait for host channel interrupt */
25070 +       do {
25071 +               gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25072 +       } while (gintsts.b.hcintr == 0);
25073 +
25074 +
25075 +       /* Read HAINT */
25076 +       haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
25077 +
25078 +       /* Read HCINT */
25079 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
25080 +
25081 +       /* Read HCCHAR */
25082 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
25083 +
25084 +       /* Clear HCINT */
25085 +       dwc_write_reg32(&hc_regs->hcint, hcint.d32);
25086 +
25087 +       /* Clear HAINT */
25088 +       dwc_write_reg32(&hc_global_regs->haint, haint.d32);
25089 +
25090 +       /* Clear GINTSTS */
25091 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
25092 +
25093 +       /* Read GINTSTS */
25094 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25095 +
25096 +//      usleep(100000);
25097 +//      mdelay(100);
25098 +       dwc_mdelay(1);
25099 +
25100 +       /*
25101 +        * Send handshake packet
25102 +        */
25103 +
25104 +       /* Read HAINT */
25105 +       haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
25106 +
25107 +       /* Read HCINT */
25108 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
25109 +
25110 +       /* Read HCCHAR */
25111 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
25112 +
25113 +       /* Clear HCINT */
25114 +       dwc_write_reg32(&hc_regs->hcint, hcint.d32);
25115 +
25116 +       /* Clear HAINT */
25117 +       dwc_write_reg32(&hc_global_regs->haint, haint.d32);
25118 +
25119 +       /* Clear GINTSTS */
25120 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
25121 +
25122 +       /* Read GINTSTS */
25123 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25124 +
25125 +       /* Make sure channel is disabled */
25126 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
25127 +       if (hcchar.b.chen) {
25128 +               hcchar.b.chdis = 1;
25129 +               hcchar.b.chen = 1;
25130 +               dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
25131 +               //sleep(1);
25132 +               dwc_mdelay(1000);
25133 +
25134 +               /* Read GINTSTS */
25135 +               gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25136 +
25137 +               /* Read HAINT */
25138 +               haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
25139 +
25140 +               /* Read HCINT */
25141 +               hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
25142 +
25143 +               /* Read HCCHAR */
25144 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
25145 +
25146 +               /* Clear HCINT */
25147 +               dwc_write_reg32(&hc_regs->hcint, hcint.d32);
25148 +
25149 +               /* Clear HAINT */
25150 +               dwc_write_reg32(&hc_global_regs->haint, haint.d32);
25151 +
25152 +               /* Clear GINTSTS */
25153 +               dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
25154 +
25155 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
25156 +       }
25157 +
25158 +       /* Set HCTSIZ */
25159 +       hctsiz.d32 = 0;
25160 +       hctsiz.b.xfersize = 0;
25161 +       hctsiz.b.pktcnt = 1;
25162 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
25163 +       dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
25164 +
25165 +       /* Set HCCHAR */
25166 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
25167 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
25168 +       hcchar.b.epdir = 0;
25169 +       hcchar.b.epnum = 0;
25170 +       hcchar.b.mps = 8;
25171 +       hcchar.b.chen = 1;
25172 +       dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
25173 +
25174 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25175 +
25176 +       /* Wait for host channel interrupt */
25177 +       do {
25178 +               gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25179 +       } while (gintsts.b.hcintr == 0);
25180 +
25181 +
25182 +       /* Disable HCINTs */
25183 +       dwc_write_reg32(&hc_regs->hcintmsk, 0x0000);
25184 +
25185 +       /* Disable HAINTs */
25186 +       dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000);
25187 +
25188 +       /* Read HAINT */
25189 +       haint.d32 = dwc_read_reg32(&hc_global_regs->haint);
25190 +
25191 +       /* Read HCINT */
25192 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
25193 +
25194 +       /* Read HCCHAR */
25195 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
25196 +
25197 +       /* Clear HCINT */
25198 +       dwc_write_reg32(&hc_regs->hcint, hcint.d32);
25199 +
25200 +       /* Clear HAINT */
25201 +       dwc_write_reg32(&hc_global_regs->haint, haint.d32);
25202 +
25203 +       /* Clear GINTSTS */
25204 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
25205 +
25206 +       /* Read GINTSTS */
25207 +       gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);
25208 +}
25209 +#endif
25210 +
25211 +/** Handles hub class-specific requests. */
25212 +int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
25213 +                           uint16_t typeReq,
25214 +                           uint16_t wValue,
25215 +                           uint16_t wIndex, uint8_t * buf, uint16_t wLength)
25216 +{
25217 +       int retval = 0;
25218 +
25219 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
25220 +       usb_hub_descriptor_t *hub_desc;
25221 +       hprt0_data_t hprt0 = {.d32 = 0 };
25222 +
25223 +       uint32_t port_status;
25224 +
25225 +       switch (typeReq) {
25226 +       case UCR_CLEAR_HUB_FEATURE:
25227 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25228 +                           "ClearHubFeature 0x%x\n", wValue);
25229 +               switch (wValue) {
25230 +               case UHF_C_HUB_LOCAL_POWER:
25231 +               case UHF_C_HUB_OVER_CURRENT:
25232 +                       /* Nothing required here */
25233 +                       break;
25234 +               default:
25235 +                       retval = -DWC_E_INVALID;
25236 +                       DWC_ERROR("DWC OTG HCD - "
25237 +                                 "ClearHubFeature request %xh unknown\n",
25238 +                                 wValue);
25239 +               }
25240 +               break;
25241 +       case UCR_CLEAR_PORT_FEATURE:
25242 +#ifdef CONFIG_USB_DWC_OTG_LPM
25243 +               if (wValue != UHF_PORT_L1)
25244 +#endif
25245 +                       if (!wIndex || wIndex > 1)
25246 +                               goto error;
25247 +
25248 +               switch (wValue) {
25249 +               case UHF_PORT_ENABLE:
25250 +                       DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
25251 +                                   "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
25252 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
25253 +                       hprt0.b.prtena = 1;
25254 +                       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
25255 +                       break;
25256 +               case UHF_PORT_SUSPEND:
25257 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25258 +                                   "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
25259 +
25260 +                       dwc_write_reg32(core_if->pcgcctl, 0);
25261 +                       dwc_mdelay(5);
25262 +
25263 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
25264 +                       hprt0.b.prtres = 1;
25265 +                       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
25266 +                       hprt0.b.prtsusp = 0;
25267 +                       /* Clear Resume bit */
25268 +                       dwc_mdelay(100);
25269 +                       hprt0.b.prtres = 0;
25270 +                       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
25271 +                       break;
25272 +#ifdef CONFIG_USB_DWC_OTG_LPM
25273 +               case UHF_PORT_L1:
25274 +                       {
25275 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
25276 +                               glpmcfg_data_t lpmcfg = {.d32 = 0 };
25277 +
25278 +                               lpmcfg.d32 =
25279 +                                   dwc_read_reg32(&core_if->core_global_regs->
25280 +                                                  glpmcfg);
25281 +                               lpmcfg.b.en_utmi_sleep = 0;
25282 +                               lpmcfg.b.hird_thres &= (~(1 << 4));
25283 +                               lpmcfg.b.prt_sleep_sts = 1;
25284 +                               dwc_write_reg32(&core_if->core_global_regs->
25285 +                                               glpmcfg, lpmcfg.d32);
25286 +
25287 +                               /* Clear Enbl_L1Gating bit. */
25288 +                               pcgcctl.b.enbl_sleep_gating = 1;
25289 +                               dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32,
25290 +                                                0);
25291 +
25292 +                               dwc_mdelay(5);
25293 +
25294 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
25295 +                               hprt0.b.prtres = 1;
25296 +                               dwc_write_reg32(core_if->host_if->hprt0,
25297 +                                               hprt0.d32);
25298 +                               /* This bit will be cleared in wakeup interrupt handle */
25299 +                               break;
25300 +                       }
25301 +#endif
25302 +               case UHF_PORT_POWER:
25303 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25304 +                                   "ClearPortFeature USB_PORT_FEAT_POWER\n");
25305 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
25306 +                       hprt0.b.prtpwr = 0;
25307 +                       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
25308 +                       break;
25309 +               case UHF_PORT_INDICATOR:
25310 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25311 +                                   "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
25312 +                       /* Port inidicator not supported */
25313 +                       break;
25314 +               case UHF_C_PORT_CONNECTION:
25315 +                       /* Clears drivers internal connect status change
25316 +                        * flag */
25317 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25318 +                                   "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
25319 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 0;
25320 +                       break;
25321 +               case UHF_C_PORT_RESET:
25322 +                       /* Clears the driver's internal Port Reset Change
25323 +                        * flag */
25324 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25325 +                                   "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
25326 +                       dwc_otg_hcd->flags.b.port_reset_change = 0;
25327 +                       break;
25328 +               case UHF_C_PORT_ENABLE:
25329 +                       /* Clears the driver's internal Port
25330 +                        * Enable/Disable Change flag */
25331 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25332 +                                   "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
25333 +                       dwc_otg_hcd->flags.b.port_enable_change = 0;
25334 +                       break;
25335 +               case UHF_C_PORT_SUSPEND:
25336 +                       /* Clears the driver's internal Port Suspend
25337 +                        * Change flag, which is set when resume signaling on
25338 +                        * the host port is complete */
25339 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25340 +                                   "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
25341 +                       dwc_otg_hcd->flags.b.port_suspend_change = 0;
25342 +                       break;
25343 +#ifdef CONFIG_USB_DWC_OTG_LPM
25344 +               case UHF_C_PORT_L1:
25345 +                       dwc_otg_hcd->flags.b.port_l1_change = 0;
25346 +                       break;
25347 +#endif
25348 +               case UHF_C_PORT_OVER_CURRENT:
25349 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25350 +                                   "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
25351 +                       dwc_otg_hcd->flags.b.port_over_current_change = 0;
25352 +                       break;
25353 +               default:
25354 +                       retval = -DWC_E_INVALID;
25355 +                       DWC_ERROR("DWC OTG HCD - "
25356 +                                 "ClearPortFeature request %xh "
25357 +                                 "unknown or unsupported\n", wValue);
25358 +               }
25359 +               break;
25360 +       case UCR_GET_HUB_DESCRIPTOR:
25361 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25362 +                           "GetHubDescriptor\n");
25363 +               hub_desc = (usb_hub_descriptor_t *) buf;
25364 +               hub_desc->bDescLength = 9;
25365 +               hub_desc->bDescriptorType = 0x29;
25366 +               hub_desc->bNbrPorts = 1;
25367 +               USETW(hub_desc->wHubCharacteristics, 0x08);
25368 +               hub_desc->bPwrOn2PwrGood = 1;
25369 +               hub_desc->bHubContrCurrent = 0;
25370 +               hub_desc->DeviceRemovable[0] = 0;
25371 +               hub_desc->DeviceRemovable[1] = 0xff;
25372 +               break;
25373 +       case UCR_GET_HUB_STATUS:
25374 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25375 +                           "GetHubStatus\n");
25376 +               DWC_MEMSET(buf, 0, 4);
25377 +               break;
25378 +       case UCR_GET_PORT_STATUS:
25379 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25380 +                           "GetPortStatus\n");
25381 +               if (!wIndex || wIndex > 1)
25382 +                       goto error;
25383 +
25384 +               port_status = 0;
25385 +
25386 +               if (dwc_otg_hcd->flags.b.port_connect_status_change)
25387 +                       port_status |= (1 << UHF_C_PORT_CONNECTION);
25388 +
25389 +               if (dwc_otg_hcd->flags.b.port_enable_change)
25390 +                       port_status |= (1 << UHF_C_PORT_ENABLE);
25391 +
25392 +               if (dwc_otg_hcd->flags.b.port_suspend_change)
25393 +                       port_status |= (1 << UHF_C_PORT_SUSPEND);
25394 +
25395 +               if (dwc_otg_hcd->flags.b.port_l1_change)
25396 +                       port_status |= (1 << UHF_C_PORT_L1);
25397 +
25398 +               if (dwc_otg_hcd->flags.b.port_reset_change) {
25399 +                       port_status |= (1 << UHF_C_PORT_RESET);
25400 +               }
25401 +
25402 +               if (dwc_otg_hcd->flags.b.port_over_current_change) {
25403 +                       DWC_ERROR("Device Not Supported\n");
25404 +                       port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
25405 +               }
25406 +
25407 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
25408 +                       /*
25409 +                        * The port is disconnected, which means the core is
25410 +                        * either in device mode or it soon will be. Just
25411 +                        * return 0's for the remainder of the port status
25412 +                        * since the port register can't be read if the core
25413 +                        * is in device mode.
25414 +                        */
25415 +                       *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
25416 +                       break;
25417 +               }
25418 +
25419 +               hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
25420 +               DWC_DEBUGPL(DBG_HCDV, "  HPRT0: 0x%08x\n", hprt0.d32);
25421 +
25422 +               if (hprt0.b.prtconnsts)
25423 +                       port_status |= (1 << UHF_PORT_CONNECTION);
25424 +
25425 +               if (hprt0.b.prtena)
25426 +                       port_status |= (1 << UHF_PORT_ENABLE);
25427 +
25428 +               if (hprt0.b.prtsusp)
25429 +                       port_status |= (1 << UHF_PORT_SUSPEND);
25430 +
25431 +               if (hprt0.b.prtovrcurract)
25432 +                       port_status |= (1 << UHF_PORT_OVER_CURRENT);
25433 +
25434 +               if (hprt0.b.prtrst)
25435 +                       port_status |= (1 << UHF_PORT_RESET);
25436 +
25437 +               if (hprt0.b.prtpwr)
25438 +                       port_status |= (1 << UHF_PORT_POWER);
25439 +
25440 +               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
25441 +                       port_status |= (1 << UHF_PORT_HIGH_SPEED);
25442 +               else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
25443 +                       port_status |= (1 << UHF_PORT_LOW_SPEED);
25444 +
25445 +               if (hprt0.b.prttstctl)
25446 +                       port_status |= (1 << UHF_PORT_TEST);
25447 +               if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
25448 +                       port_status |= (1 << UHF_PORT_L1);
25449 +               }
25450 +
25451 +               /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
25452 +
25453 +               *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
25454 +
25455 +               break;
25456 +       case UCR_SET_HUB_FEATURE:
25457 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25458 +                           "SetHubFeature\n");
25459 +               /* No HUB features supported */
25460 +               break;
25461 +       case UCR_SET_PORT_FEATURE:
25462 +               if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
25463 +                       goto error;
25464 +
25465 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
25466 +                       /*
25467 +                        * The port is disconnected, which means the core is
25468 +                        * either in device mode or it soon will be. Just
25469 +                        * return without doing anything since the port
25470 +                        * register can't be written if the core is in device
25471 +                        * mode.
25472 +                        */
25473 +                       break;
25474 +               }
25475 +
25476 +               switch (wValue) {
25477 +               case UHF_PORT_SUSPEND:
25478 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25479 +                                   "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
25480 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
25481 +                           dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
25482 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
25483 +                               gotgctl.b.hstsethnpen = 1;
25484 +                               dwc_modify_reg32(&core_if->core_global_regs->
25485 +                                                gotgctl, 0, gotgctl.d32);
25486 +                               core_if->op_state = A_SUSPEND;
25487 +                       }
25488 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
25489 +                       hprt0.b.prtsusp = 1;
25490 +                       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
25491 +                       {
25492 +                               uint64_t flags;
25493 +                               /* Update lx_state */
25494 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
25495 +                               core_if->lx_state = DWC_OTG_L2;
25496 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
25497 +                       }
25498 +                       /* Suspend the Phy Clock */
25499 +                       {
25500 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
25501 +                               pcgcctl.b.stoppclk = 1;
25502 +                               dwc_modify_reg32(core_if->pcgcctl, 0,
25503 +                                                pcgcctl.d32);
25504 +                       }
25505 +
25506 +                       /* For HNP the bus must be suspended for at least 200ms. */
25507 +                       if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
25508 +                               dwc_mdelay(200);
25509 +                       }
25510 +                       break;
25511 +               case UHF_PORT_POWER:
25512 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25513 +                                   "SetPortFeature - USB_PORT_FEAT_POWER\n");
25514 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
25515 +                       hprt0.b.prtpwr = 1;
25516 +                       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
25517 +                       break;
25518 +               case UHF_PORT_RESET:
25519 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25520 +                                   "SetPortFeature - USB_PORT_FEAT_RESET\n");
25521 +                       {
25522 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
25523 +                               pcgcctl.b.enbl_sleep_gating = 1;
25524 +                               pcgcctl.b.stoppclk = 1;
25525 +                               dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32,
25526 +                                                0);
25527 +                               dwc_write_reg32(core_if->pcgcctl, 0);
25528 +                       }
25529 +#ifdef CONFIG_USB_DWC_OTG_LPM
25530 +                       {
25531 +                               glpmcfg_data_t lpmcfg;
25532 +                               lpmcfg.d32 =
25533 +                                   dwc_read_reg32(&core_if->core_global_regs->
25534 +                                                  glpmcfg);
25535 +                               if (lpmcfg.b.prt_sleep_sts) {
25536 +                                       lpmcfg.b.en_utmi_sleep = 0;
25537 +                                       lpmcfg.b.hird_thres &= (~(1 << 4));
25538 +                                       dwc_write_reg32(&core_if->
25539 +                                                       core_global_regs->
25540 +                                                       glpmcfg, lpmcfg.d32);
25541 +                                       dwc_mdelay(1);
25542 +                               }
25543 +                       }
25544 +#endif
25545 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
25546 +                       /* When B-Host the Port reset bit is set in
25547 +                        * the Start HCD Callback function, so that
25548 +                        * the reset is started within 1ms of the HNP
25549 +                        * success interrupt. */
25550 +                       if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
25551 +                               hprt0.b.prtrst = 1;
25552 +                               dwc_write_reg32(core_if->host_if->hprt0,
25553 +                                               hprt0.d32);
25554 +                       }
25555 +                       /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
25556 +                       dwc_mdelay(60);
25557 +                       hprt0.b.prtrst = 0;
25558 +                       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
25559 +                       core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
25560 +                       break;
25561 +#ifdef DWC_HS_ELECT_TST
25562 +               case UHF_PORT_TEST:
25563 +                       {
25564 +                               uint32_t t;
25565 +                               gintmsk_data_t gintmsk;
25566 +
25567 +                               t = (wIndex >> 8);      /* MSB wIndex USB */
25568 +                               DWC_DEBUGPL(DBG_HCD,
25569 +                                           "DWC OTG HCD HUB CONTROL - "
25570 +                                           "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
25571 +                                           t);
25572 +                               DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
25573 +                               if (t < 6) {
25574 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
25575 +                                       hprt0.b.prttstctl = t;
25576 +                                       dwc_write_reg32(core_if->host_if->hprt0,
25577 +                                                       hprt0.d32);
25578 +                               } else {
25579 +                                       /* Setup global vars with reg addresses (quick and
25580 +                                        * dirty hack, should be cleaned up)
25581 +                                        */
25582 +                                       global_regs = core_if->core_global_regs;
25583 +                                       hc_global_regs =
25584 +                                           core_if->host_if->host_global_regs;
25585 +                                       hc_regs =
25586 +                                           (dwc_otg_hc_regs_t *) ((char *)
25587 +                                                                  global_regs +
25588 +                                                                  0x500);
25589 +                                       data_fifo =
25590 +                                           (uint32_t *) ((char *)global_regs +
25591 +                                                         0x1000);
25592 +
25593 +                                       if (t == 6) {   /* HS_HOST_PORT_SUSPEND_RESUME */
25594 +                                               /* Save current interrupt mask */
25595 +                                               gintmsk.d32 =
25596 +                                                   dwc_read_reg32
25597 +                                                   (&global_regs->gintmsk);
25598 +
25599 +                                               /* Disable all interrupts while we muck with
25600 +                                                * the hardware directly
25601 +                                                */
25602 +                                               dwc_write_reg32(&global_regs->
25603 +                                                               gintmsk, 0);
25604 +
25605 +                                               /* 15 second delay per the test spec */
25606 +                                               dwc_mdelay(15000);
25607 +
25608 +                                               /* Drive suspend on the root port */
25609 +                                               hprt0.d32 =
25610 +                                                   dwc_otg_read_hprt0(core_if);
25611 +                                               hprt0.b.prtsusp = 1;
25612 +                                               hprt0.b.prtres = 0;
25613 +                                               dwc_write_reg32(core_if->
25614 +                                                               host_if->hprt0,
25615 +                                                               hprt0.d32);
25616 +
25617 +                                               /* 15 second delay per the test spec */
25618 +                                               dwc_mdelay(15000);
25619 +
25620 +                                               /* Drive resume on the root port */
25621 +                                               hprt0.d32 =
25622 +                                                   dwc_otg_read_hprt0(core_if);
25623 +                                               hprt0.b.prtsusp = 0;
25624 +                                               hprt0.b.prtres = 1;
25625 +                                               dwc_write_reg32(core_if->
25626 +                                                               host_if->hprt0,
25627 +                                                               hprt0.d32);
25628 +                                               dwc_mdelay(100);
25629 +
25630 +                                               /* Clear the resume bit */
25631 +                                               hprt0.b.prtres = 0;
25632 +                                               dwc_write_reg32(core_if->
25633 +                                                               host_if->hprt0,
25634 +                                                               hprt0.d32);
25635 +
25636 +                                               /* Restore interrupts */
25637 +                                               dwc_write_reg32(&global_regs->
25638 +                                                               gintmsk,
25639 +                                                               gintmsk.d32);
25640 +                                       } else if (t == 7) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
25641 +                                               /* Save current interrupt mask */
25642 +                                               gintmsk.d32 =
25643 +                                                   dwc_read_reg32
25644 +                                                   (&global_regs->gintmsk);
25645 +
25646 +                                               /* Disable all interrupts while we muck with
25647 +                                                * the hardware directly
25648 +                                                */
25649 +                                               dwc_write_reg32(&global_regs->
25650 +                                                               gintmsk, 0);
25651 +
25652 +                                               /* 15 second delay per the test spec */
25653 +                                               dwc_mdelay(15000);
25654 +
25655 +                                               /* Send the Setup packet */
25656 +                                               do_setup();
25657 +
25658 +                                               /* 15 second delay so nothing else happens for awhile */
25659 +                                               dwc_mdelay(15000);
25660 +
25661 +                                               /* Restore interrupts */
25662 +                                               dwc_write_reg32(&global_regs->
25663 +                                                               gintmsk,
25664 +                                                               gintmsk.d32);
25665 +                                       } else if (t == 8) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
25666 +                                               /* Save current interrupt mask */
25667 +                                               gintmsk.d32 =
25668 +                                                   dwc_read_reg32
25669 +                                                   (&global_regs->gintmsk);
25670 +
25671 +                                               /* Disable all interrupts while we muck with
25672 +                                                * the hardware directly
25673 +                                                */
25674 +                                               dwc_write_reg32(&global_regs->
25675 +                                                               gintmsk, 0);
25676 +
25677 +                                               /* Send the Setup packet */
25678 +                                               do_setup();
25679 +
25680 +                                               /* 15 second delay so nothing else happens for awhile */
25681 +                                               dwc_mdelay(15000);
25682 +
25683 +                                               /* Send the In and Ack packets */
25684 +                                               do_in_ack();
25685 +
25686 +                                               /* 15 second delay so nothing else happens for awhile */
25687 +                                               dwc_mdelay(15000);
25688 +
25689 +                                               /* Restore interrupts */
25690 +                                               dwc_write_reg32(&global_regs->
25691 +                                                               gintmsk,
25692 +                                                               gintmsk.d32);
25693 +                                       }
25694 +                               }
25695 +                               break;
25696 +                       }
25697 +#endif                         /* DWC_HS_ELECT_TST */
25698 +
25699 +               case UHF_PORT_INDICATOR:
25700 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
25701 +                                   "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
25702 +                       /* Not supported */
25703 +                       break;
25704 +               default:
25705 +                       retval = -DWC_E_INVALID;
25706 +                       DWC_ERROR("DWC OTG HCD - "
25707 +                                 "SetPortFeature request %xh "
25708 +                                 "unknown or unsupported\n", wValue);
25709 +                       break;
25710 +               }
25711 +               break;
25712 +#ifdef CONFIG_USB_DWC_OTG_LPM
25713 +       case UCR_SET_AND_TEST_PORT_FEATURE:
25714 +               if (wValue != UHF_PORT_L1) {
25715 +                       goto error;
25716 +               }
25717 +               {
25718 +                       int portnum, hird, devaddr, remwake;
25719 +                       glpmcfg_data_t lpmcfg;
25720 +                       uint32_t time_usecs;
25721 +                       gintsts_data_t gintsts;
25722 +                       gintmsk_data_t gintmsk;
25723 +
25724 +                       if (!dwc_otg_get_param_lpm_enable(core_if)) {
25725 +                               goto error;
25726 +                       }
25727 +                       if (wValue != UHF_PORT_L1 || wLength != 1) {
25728 +                               goto error;
25729 +                       }
25730 +                       /* Check if the port currently is in SLEEP state */
25731 +                       lpmcfg.d32 =
25732 +                           dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
25733 +                       if (lpmcfg.b.prt_sleep_sts) {
25734 +                               DWC_INFO("Port is already in sleep mode\n");
25735 +                               buf[0] = 0;     /* Return success */
25736 +                               break;
25737 +                       }
25738 +
25739 +                       portnum = wIndex & 0xf;
25740 +                       hird = (wIndex >> 4) & 0xf;
25741 +                       devaddr = (wIndex >> 8) & 0x7f;
25742 +                       remwake = (wIndex >> 15);
25743 +
25744 +                       if (portnum != 1) {
25745 +                               retval = -DWC_E_INVALID;
25746 +                               DWC_WARN
25747 +                                   ("Wrong port number(%d) in SetandTestPortFeature request\n",
25748 +                                    portnum);
25749 +                               break;
25750 +                       }
25751 +
25752 +                       DWC_PRINTF
25753 +                           ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
25754 +                            portnum, hird, devaddr, remwake);
25755 +                       /* Disable LPM interrupt */
25756 +                       gintmsk.d32 = 0;
25757 +                       gintmsk.b.lpmtranrcvd = 1;
25758 +                       dwc_modify_reg32(&core_if->core_global_regs->gintmsk,
25759 +                                        gintmsk.d32, 0);
25760 +
25761 +                       if (dwc_otg_hcd_send_lpm
25762 +                           (dwc_otg_hcd, devaddr, hird, remwake)) {
25763 +                               retval = -DWC_E_INVALID;
25764 +                               break;
25765 +                       }
25766 +
25767 +                       time_usecs = 10 * (lpmcfg.b.retry_count + 1);
25768 +                       /* We will consider timeout if time_usecs microseconds pass,
25769 +                        * and we don't receive LPM transaction status.
25770 +                        * After receiving non-error responce(ACK/NYET/STALL) from device,
25771 +                        *  core will set lpmtranrcvd bit.
25772 +                        */
25773 +                       do {
25774 +                               gintsts.d32 =
25775 +                                   dwc_read_reg32(&core_if->core_global_regs->
25776 +                                                  gintsts);
25777 +                               if (gintsts.b.lpmtranrcvd) {
25778 +                                       break;
25779 +                               }
25780 +                               dwc_udelay(1);
25781 +                       } while (--time_usecs);
25782 +                       /* lpm_int bit will be cleared in LPM interrupt handler */
25783 +
25784 +                       /* Now fill status
25785 +                        * 0x00 - Success
25786 +                        * 0x10 - NYET
25787 +                        * 0x11 - Timeout
25788 +                        */
25789 +                       if (!gintsts.b.lpmtranrcvd) {
25790 +                               buf[0] = 0x3;   /* Completion code is Timeout */
25791 +                               dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
25792 +                       } else {
25793 +                               lpmcfg.d32 =
25794 +                                   dwc_read_reg32(&core_if->core_global_regs->
25795 +                                                  glpmcfg);
25796 +                               if (lpmcfg.b.lpm_resp == 0x3) {
25797 +                                       /* ACK responce from the device */
25798 +                                       buf[0] = 0x00;  /* Success */
25799 +                               } else if (lpmcfg.b.lpm_resp == 0x2) {
25800 +                                       /* NYET responce from the device */
25801 +                                       buf[0] = 0x2;
25802 +                               } else {
25803 +                                       /* Otherwise responce with Timeout */
25804 +                                       buf[0] = 0x3;
25805 +                               }
25806 +                       }
25807 +                       DWC_PRINTF("Device responce to LPM trans is %x\n",
25808 +                                  lpmcfg.b.lpm_resp);
25809 +                       dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0,
25810 +                                        gintmsk.d32);
25811 +
25812 +                       break;
25813 +               }
25814 +#endif                         /* CONFIG_USB_DWC_OTG_LPM */
25815 +       default:
25816 +             error:
25817 +               retval = -DWC_E_INVALID;
25818 +               DWC_WARN("DWC OTG HCD - "
25819 +                        "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
25820 +                        typeReq, wIndex, wValue);
25821 +               break;
25822 +       }
25823 +
25824 +       return retval;
25825 +}
25826 +
25827 +#ifdef CONFIG_USB_DWC_OTG_LPM
25828 +/** Returns index of host channel to perform LPM transaction. */
25829 +int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
25830 +{
25831 +       dwc_otg_core_if_t *core_if = hcd->core_if;
25832 +       dwc_hc_t *hc;
25833 +       hcchar_data_t hcchar;
25834 +       gintmsk_data_t gintmsk = {.d32 = 0 };
25835 +
25836 +       if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
25837 +               DWC_PRINTF("No free channel to select for LPM transaction\n");
25838 +               return -1;
25839 +       }
25840 +
25841 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
25842 +
25843 +       /* Mask host channel interrupts. */
25844 +       gintmsk.b.hcintr = 1;
25845 +       dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
25846 +
25847 +       /* Fill fields that core needs for LPM transaction */
25848 +       hcchar.b.devaddr = devaddr;
25849 +       hcchar.b.epnum = 0;
25850 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
25851 +       hcchar.b.mps = 64;
25852 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
25853 +       hcchar.b.epdir = 0;     /* OUT */
25854 +       dwc_write_reg32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
25855 +                       hcchar.d32);
25856 +
25857 +       /* Remove the host channel from the free list. */
25858 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
25859 +
25860 +       DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
25861 +
25862 +       return hc->hc_num;
25863 +}
25864 +
25865 +/** Release hc after performing LPM transaction */
25866 +void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
25867 +{
25868 +       dwc_hc_t *hc;
25869 +       glpmcfg_data_t lpmcfg;
25870 +       uint8_t hc_num;
25871 +
25872 +       lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg);
25873 +       hc_num = lpmcfg.b.lpm_chan_index;
25874 +
25875 +       hc = hcd->hc_ptr_array[hc_num];
25876 +
25877 +       DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
25878 +       /* Return host channel to free list */
25879 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
25880 +}
25881 +
25882 +int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
25883 +                        uint8_t bRemoteWake)
25884 +{
25885 +       glpmcfg_data_t lpmcfg;
25886 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
25887 +       int channel;
25888 +
25889 +       channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
25890 +       if (channel < 0) {
25891 +               return channel;
25892 +       }
25893 +
25894 +       pcgcctl.b.enbl_sleep_gating = 1;
25895 +       dwc_modify_reg32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
25896 +
25897 +       /* Read LPM config register */
25898 +       lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg);
25899 +
25900 +       /* Program LPM transaction fields */
25901 +       lpmcfg.b.rem_wkup_en = bRemoteWake;
25902 +       lpmcfg.b.hird = hird;
25903 +       lpmcfg.b.hird_thres = 0x1c;
25904 +       lpmcfg.b.lpm_chan_index = channel;
25905 +       lpmcfg.b.en_utmi_sleep = 1;
25906 +       /* Program LPM config register */
25907 +       dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
25908 +
25909 +       /* Send LPM transaction */
25910 +       lpmcfg.b.send_lpm = 1;
25911 +       dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
25912 +
25913 +       return 0;
25914 +}
25915 +
25916 +#endif                         /* CONFIG_USB_DWC_OTG_LPM */
25917 +
25918 +int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
25919 +{
25920 +       int retval;
25921 +
25922 +       if (port != 1) {
25923 +               return -DWC_E_INVALID;
25924 +       }
25925 +
25926 +       retval = (hcd->flags.b.port_connect_status_change ||
25927 +                 hcd->flags.b.port_reset_change ||
25928 +                 hcd->flags.b.port_enable_change ||
25929 +                 hcd->flags.b.port_suspend_change ||
25930 +                 hcd->flags.b.port_over_current_change);
25931 +#ifdef DEBUG
25932 +       if (retval) {
25933 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
25934 +                           " Root port status changed\n");
25935 +               DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",
25936 +                           hcd->flags.b.port_connect_status_change);
25937 +               DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",
25938 +                           hcd->flags.b.port_reset_change);
25939 +               DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",
25940 +                           hcd->flags.b.port_enable_change);
25941 +               DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",
25942 +                           hcd->flags.b.port_suspend_change);
25943 +               DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",
25944 +                           hcd->flags.b.port_over_current_change);
25945 +       }
25946 +#endif
25947 +       return retval;
25948 +}
25949 +
25950 +int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
25951 +{
25952 +       hfnum_data_t hfnum;
25953 +       hfnum.d32 = dwc_read_reg32(&dwc_otg_hcd->core_if->
25954 +                                  host_if->host_global_regs->hfnum);
25955 +
25956 +#ifdef DEBUG_SOF
25957 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
25958 +                   hfnum.b.frnum);
25959 +#endif
25960 +       return hfnum.b.frnum;
25961 +}
25962 +
25963 +int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
25964 +                     struct dwc_otg_hcd_function_ops *fops)
25965 +{
25966 +       int retval = 0;
25967 +
25968 +       hcd->fops = fops;
25969 +       if (!dwc_otg_is_device_mode(hcd->core_if)) {
25970 +               dwc_otg_hcd_reinit(hcd);
25971 +       } else {
25972 +               retval = -DWC_E_NO_DEVICE;
25973 +       }
25974 +
25975 +       return retval;
25976 +}
25977 +
25978 +void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
25979 +{
25980 +       return hcd->priv;
25981 +}
25982 +
25983 +void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
25984 +{
25985 +       hcd->priv = priv_data;
25986 +}
25987 +
25988 +uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
25989 +{
25990 +       return hcd->otg_port;
25991 +}
25992 +
25993 +uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
25994 +{
25995 +       uint32_t is_b_host;
25996 +       if (hcd->core_if->op_state == B_HOST) {
25997 +               is_b_host = 1;
25998 +       } else {
25999 +               is_b_host = 0;
26000 +       }
26001 +
26002 +       return is_b_host;
26003 +}
26004 +
26005 +dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
26006 +                                        int iso_desc_count, int atomic_alloc)
26007 +{
26008 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
26009 +       uint32_t size;
26010 +
26011 +       size =
26012 +           sizeof(*dwc_otg_urb) +
26013 +           iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
26014 +       if (atomic_alloc) {
26015 +               dwc_otg_urb = dwc_alloc_atomic(size);
26016 +       } else {
26017 +               dwc_otg_urb = dwc_alloc(size);
26018 +       }
26019 +       dwc_otg_urb->packet_count = iso_desc_count;
26020 +
26021 +       return dwc_otg_urb;
26022 +}
26023 +
26024 +void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
26025 +                                 uint8_t dev_addr, uint8_t ep_num,
26026 +                                 uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
26027 +{
26028 +       dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
26029 +                             ep_type, ep_dir, mps);
26030 +#if 0
26031 +       DWC_PRINTF
26032 +           ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
26033 +            dev_addr, ep_num, ep_dir, ep_type, mps);
26034 +#endif
26035 +}
26036 +
26037 +void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
26038 +                               void *urb_handle, void *buf, dwc_dma_t dma,
26039 +                               uint32_t buflen, void *setup_packet,
26040 +                               dwc_dma_t setup_dma, uint32_t flags,
26041 +                               uint16_t interval)
26042 +{
26043 +       dwc_otg_urb->priv = urb_handle;
26044 +       dwc_otg_urb->buf = buf;
26045 +       dwc_otg_urb->dma = dma;
26046 +       dwc_otg_urb->length = buflen;
26047 +       dwc_otg_urb->setup_packet = setup_packet;
26048 +       dwc_otg_urb->setup_dma = setup_dma;
26049 +       dwc_otg_urb->flags = flags;
26050 +       dwc_otg_urb->interval = interval;
26051 +       dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
26052 +}
26053 +
26054 +uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
26055 +{
26056 +       return dwc_otg_urb->status;
26057 +}
26058 +
26059 +uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
26060 +{
26061 +       return dwc_otg_urb->actual_length;
26062 +}
26063 +
26064 +uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
26065 +{
26066 +       return dwc_otg_urb->error_count;
26067 +}
26068 +
26069 +void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
26070 +                                        int desc_num, uint32_t offset,
26071 +                                        uint32_t length)
26072 +{
26073 +       dwc_otg_urb->iso_descs[desc_num].offset = offset;
26074 +       dwc_otg_urb->iso_descs[desc_num].length = length;
26075 +}
26076 +
26077 +uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
26078 +                                            int desc_num)
26079 +{
26080 +       return dwc_otg_urb->iso_descs[desc_num].status;
26081 +}
26082 +
26083 +uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
26084 +                                                   dwc_otg_urb, int desc_num)
26085 +{
26086 +       return dwc_otg_urb->iso_descs[desc_num].actual_length;
26087 +}
26088 +
26089 +int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
26090 +{
26091 +       int allocated = 0;
26092 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
26093 +
26094 +       if (qh) {
26095 +               if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
26096 +                       allocated = 1;
26097 +               }
26098 +       }
26099 +       return allocated;
26100 +}
26101 +
26102 +int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
26103 +{
26104 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
26105 +       int freed = 0;
26106 +       DWC_ASSERT(qh, "qh is not allocated\n");
26107 +
26108 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
26109 +               freed = 1;
26110 +       }
26111 +
26112 +       return freed;
26113 +}
26114 +
26115 +uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
26116 +{
26117 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
26118 +       DWC_ASSERT(qh, "qh is not allocated\n");
26119 +       return qh->usecs;
26120 +}
26121 +
26122 +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
26123 +{
26124 +#ifdef DEBUG
26125 +       int num_channels;
26126 +       int i;
26127 +       gnptxsts_data_t np_tx_status;
26128 +       hptxsts_data_t p_tx_status;
26129 +
26130 +       num_channels = hcd->core_if->core_params->host_channels;
26131 +       DWC_PRINTF("\n");
26132 +       DWC_PRINTF
26133 +           ("************************************************************\n");
26134 +       DWC_PRINTF("HCD State:\n");
26135 +       DWC_PRINTF("  Num channels: %d\n", num_channels);
26136 +       for (i = 0; i < num_channels; i++) {
26137 +               dwc_hc_t *hc = hcd->hc_ptr_array[i];
26138 +               DWC_PRINTF("  Channel %d:\n", i);
26139 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
26140 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
26141 +               DWC_PRINTF("    speed: %d\n", hc->speed);
26142 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
26143 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
26144 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
26145 +               DWC_PRINTF("    multi_count: %d\n", hc->multi_count);
26146 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
26147 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
26148 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
26149 +               DWC_PRINTF("    xfer_count: %d\n", hc->xfer_count);
26150 +               DWC_PRINTF("    halt_on_queue: %d\n", hc->halt_on_queue);
26151 +               DWC_PRINTF("    halt_pending: %d\n", hc->halt_pending);
26152 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
26153 +               DWC_PRINTF("    do_split: %d\n", hc->do_split);
26154 +               DWC_PRINTF("    complete_split: %d\n", hc->complete_split);
26155 +               DWC_PRINTF("    hub_addr: %d\n", hc->hub_addr);
26156 +               DWC_PRINTF("    port_addr: %d\n", hc->port_addr);
26157 +               DWC_PRINTF("    xact_pos: %d\n", hc->xact_pos);
26158 +               DWC_PRINTF("    requests: %d\n", hc->requests);
26159 +               DWC_PRINTF("    qh: %p\n", hc->qh);
26160 +               if (hc->xfer_started) {
26161 +                       hfnum_data_t hfnum;
26162 +                       hcchar_data_t hcchar;
26163 +                       hctsiz_data_t hctsiz;
26164 +                       hcint_data_t hcint;
26165 +                       hcintmsk_data_t hcintmsk;
26166 +                       hfnum.d32 =
26167 +                           dwc_read_reg32(&hcd->core_if->host_if->
26168 +                                          host_global_regs->hfnum);
26169 +                       hcchar.d32 =
26170 +                           dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->
26171 +                                          hcchar);
26172 +                       hctsiz.d32 =
26173 +                           dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->
26174 +                                          hctsiz);
26175 +                       hcint.d32 =
26176 +                           dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->
26177 +                                          hcint);
26178 +                       hcintmsk.d32 =
26179 +                           dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]->
26180 +                                          hcintmsk);
26181 +                       DWC_PRINTF("    hfnum: 0x%08x\n", hfnum.d32);
26182 +                       DWC_PRINTF("    hcchar: 0x%08x\n", hcchar.d32);
26183 +                       DWC_PRINTF("    hctsiz: 0x%08x\n", hctsiz.d32);
26184 +                       DWC_PRINTF("    hcint: 0x%08x\n", hcint.d32);
26185 +                       DWC_PRINTF("    hcintmsk: 0x%08x\n", hcintmsk.d32);
26186 +               }
26187 +               if (hc->xfer_started && hc->qh) {
26188 +                       dwc_otg_qtd_t *qtd;
26189 +                       dwc_otg_hcd_urb_t *urb;
26190 +                       
26191 +                       DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
26192 +                               if(!qtd->in_process)
26193 +                                       break;
26194 +                               
26195 +                               urb = qtd->urb;
26196 +                       DWC_PRINTF("    URB Info:\n");
26197 +                       DWC_PRINTF("      qtd: %p, urb: %p\n", qtd, urb);
26198 +                       if (urb) {
26199 +                               DWC_PRINTF("      Dev: %d, EP: %d %s\n",
26200 +                                          dwc_otg_hcd_get_dev_addr(&urb->
26201 +                                                                   pipe_info),
26202 +                                          dwc_otg_hcd_get_ep_num(&urb->
26203 +                                                                 pipe_info),
26204 +                                          dwc_otg_hcd_is_pipe_in(&urb->
26205 +                                                                 pipe_info) ?
26206 +                                          "IN" : "OUT");
26207 +                               DWC_PRINTF("      Max packet size: %d\n",
26208 +                                          dwc_otg_hcd_get_mps(&urb->
26209 +                                                              pipe_info));
26210 +                               DWC_PRINTF("      transfer_buffer: %p\n",
26211 +                                          urb->buf);
26212 +                               DWC_PRINTF("      transfer_dma: %p\n",
26213 +                                          (void *)urb->dma);
26214 +                               DWC_PRINTF("      transfer_buffer_length: %d\n",
26215 +                                          urb->length);
26216 +                               DWC_PRINTF("      actual_length: %d\n",
26217 +                                          urb->actual_length);
26218 +                       }
26219 +               }
26220 +       }
26221 +       }
26222 +       DWC_PRINTF("  non_periodic_channels: %d\n", hcd->non_periodic_channels);
26223 +       DWC_PRINTF("  periodic_channels: %d\n", hcd->periodic_channels);
26224 +       DWC_PRINTF("  periodic_usecs: %d\n", hcd->periodic_usecs);
26225 +       np_tx_status.d32 =
26226 +           dwc_read_reg32(&hcd->core_if->core_global_regs->gnptxsts);
26227 +       DWC_PRINTF("  NP Tx Req Queue Space Avail: %d\n",
26228 +                  np_tx_status.b.nptxqspcavail);
26229 +       DWC_PRINTF("  NP Tx FIFO Space Avail: %d\n",
26230 +                  np_tx_status.b.nptxfspcavail);
26231 +       p_tx_status.d32 =
26232 +           dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hptxsts);
26233 +       DWC_PRINTF("  P Tx Req Queue Space Avail: %d\n",
26234 +                  p_tx_status.b.ptxqspcavail);
26235 +       DWC_PRINTF("  P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
26236 +       dwc_otg_hcd_dump_frrem(hcd);
26237 +       dwc_otg_dump_global_registers(hcd->core_if);
26238 +       dwc_otg_dump_host_registers(hcd->core_if);
26239 +       DWC_PRINTF
26240 +           ("************************************************************\n");
26241 +       DWC_PRINTF("\n");
26242 +#endif
26243 +}
26244 +
26245 +#ifdef DEBUG
26246 +void dwc_print_setup_data(uint8_t * setup)
26247 +{
26248 +       int i;
26249 +       if (CHK_DEBUG_LEVEL(DBG_HCD)) {
26250 +               DWC_PRINTF("Setup Data = MSB ");
26251 +               for (i = 7; i >= 0; i--)
26252 +                       DWC_PRINTF("%02x ", setup[i]);
26253 +               DWC_PRINTF("\n");
26254 +               DWC_PRINTF("  bmRequestType Tranfer = %s\n",
26255 +                          (setup[0] & 0x80) ? "Device-to-Host" :
26256 +                          "Host-to-Device");
26257 +               DWC_PRINTF("  bmRequestType Type = ");
26258 +               switch ((setup[0] & 0x60) >> 5) {
26259 +               case 0:
26260 +                       DWC_PRINTF("Standard\n");
26261 +                       break;
26262 +               case 1:
26263 +                       DWC_PRINTF("Class\n");
26264 +                       break;
26265 +               case 2:
26266 +                       DWC_PRINTF("Vendor\n");
26267 +                       break;
26268 +               case 3:
26269 +                       DWC_PRINTF("Reserved\n");
26270 +                       break;
26271 +               }
26272 +               DWC_PRINTF("  bmRequestType Recipient = ");
26273 +               switch (setup[0] & 0x1f) {
26274 +               case 0:
26275 +                       DWC_PRINTF("Device\n");
26276 +                       break;
26277 +               case 1:
26278 +                       DWC_PRINTF("Interface\n");
26279 +                       break;
26280 +               case 2:
26281 +                       DWC_PRINTF("Endpoint\n");
26282 +                       break;
26283 +               case 3:
26284 +                       DWC_PRINTF("Other\n");
26285 +                       break;
26286 +               default:
26287 +                       DWC_PRINTF("Reserved\n");
26288 +                       break;
26289 +               }
26290 +               DWC_PRINTF("  bRequest = 0x%0x\n", setup[1]);
26291 +               DWC_PRINTF("  wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
26292 +               DWC_PRINTF("  wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
26293 +               DWC_PRINTF("  wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
26294 +       }
26295 +}
26296 +#endif
26297 +
26298 +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
26299 +{
26300 +#if 0
26301 +       DWC_PRINTF("Frame remaining at SOF:\n");
26302 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26303 +                  hcd->frrem_samples, hcd->frrem_accum,
26304 +                  (hcd->frrem_samples > 0) ?
26305 +                  hcd->frrem_accum / hcd->frrem_samples : 0);
26306 +
26307 +       DWC_PRINTF("\n");
26308 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
26309 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26310 +                  hcd->core_if->hfnum_7_samples,
26311 +                  hcd->core_if->hfnum_7_frrem_accum,
26312 +                  (hcd->core_if->hfnum_7_samples >
26313 +                   0) ? hcd->core_if->hfnum_7_frrem_accum /
26314 +                  hcd->core_if->hfnum_7_samples : 0);
26315 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
26316 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26317 +                  hcd->core_if->hfnum_0_samples,
26318 +                  hcd->core_if->hfnum_0_frrem_accum,
26319 +                  (hcd->core_if->hfnum_0_samples >
26320 +                   0) ? hcd->core_if->hfnum_0_frrem_accum /
26321 +                  hcd->core_if->hfnum_0_samples : 0);
26322 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
26323 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26324 +                  hcd->core_if->hfnum_other_samples,
26325 +                  hcd->core_if->hfnum_other_frrem_accum,
26326 +                  (hcd->core_if->hfnum_other_samples >
26327 +                   0) ? hcd->core_if->hfnum_other_frrem_accum /
26328 +                  hcd->core_if->hfnum_other_samples : 0);
26329 +
26330 +       DWC_PRINTF("\n");
26331 +       DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
26332 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26333 +                  hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
26334 +                  (hcd->hfnum_7_samples_a > 0) ?
26335 +                  hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
26336 +       DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
26337 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26338 +                  hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
26339 +                  (hcd->hfnum_0_samples_a > 0) ?
26340 +                  hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
26341 +       DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
26342 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26343 +                  hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
26344 +                  (hcd->hfnum_other_samples_a > 0) ?
26345 +                  hcd->hfnum_other_frrem_accum_a /
26346 +                  hcd->hfnum_other_samples_a : 0);
26347 +
26348 +       DWC_PRINTF("\n");
26349 +       DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
26350 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26351 +                  hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
26352 +                  (hcd->hfnum_7_samples_b > 0) ?
26353 +                  hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
26354 +       DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
26355 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26356 +                  hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
26357 +                  (hcd->hfnum_0_samples_b > 0) ?
26358 +                  hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
26359 +       DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
26360 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
26361 +                  hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
26362 +                  (hcd->hfnum_other_samples_b > 0) ?
26363 +                  hcd->hfnum_other_frrem_accum_b /
26364 +                  hcd->hfnum_other_samples_b : 0);
26365 +#endif
26366 +}
26367 +
26368 +#endif                         /* DWC_DEVICE_ONLY */
26369 --- /dev/null
26370 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
26371 @@ -0,0 +1,804 @@
26372 +/* ==========================================================================
26373 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
26374 + * $Revision: #52 $
26375 + * $Date: 2009/04/21 $
26376 + * $Change: 1237472 $
26377 + *
26378 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
26379 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
26380 + * otherwise expressly agreed to in writing between Synopsys and you.
26381 + *
26382 + * The Software IS NOT an item of Licensed Software or Licensed Product under
26383 + * any End User Software License Agreement or Agreement for Licensed Product
26384 + * with Synopsys or any supplement thereto. You are permitted to use and
26385 + * redistribute this Software in source and binary forms, with or without
26386 + * modification, provided that redistributions of source code must retain this
26387 + * notice. You may not view, use, disclose, copy or distribute this file or
26388 + * any information contained herein except pursuant to this license grant from
26389 + * Synopsys. If you do not agree with this notice, including the disclaimer
26390 + * below, then you are not authorized to use the Software.
26391 + *
26392 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
26393 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26394 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26395 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
26396 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26397 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26398 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26399 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26400 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26401 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26402 + * DAMAGE.
26403 + * ========================================================================== */
26404 +#ifndef DWC_DEVICE_ONLY
26405 +#ifndef __DWC_HCD_H__
26406 +#define __DWC_HCD_H__
26407 +
26408 +#include <usb.h>
26409 +#include "dwc_otg_hcd_if.h"
26410 +#include "dwc_otg_core_if.h"
26411 +#include "dwc_list.h"
26412 +#include "dwc_otg_cil.h"
26413 +
26414 +/**
26415 + * @file
26416 + *
26417 + * This file contains the structures, constants, and interfaces for
26418 + * the Host Contoller Driver (HCD).
26419 + *
26420 + * The Host Controller Driver (HCD) is responsible for translating requests
26421 + * from the USB Driver into the appropriate actions on the DWC_otg controller.
26422 + * It isolates the USBD from the specifics of the controller by providing an
26423 + * API to the USBD.
26424 + */
26425 +
26426 +struct dwc_otg_hcd_pipe_info {
26427 +       uint8_t dev_addr;
26428 +       uint8_t ep_num;
26429 +       uint8_t pipe_type;
26430 +       uint8_t pipe_dir;
26431 +       uint16_t mps;
26432 +};
26433 +
26434 +struct dwc_otg_hcd_iso_packet_desc {
26435 +       uint32_t offset;
26436 +       uint32_t length;
26437 +       uint32_t actual_length;
26438 +       uint32_t status;
26439 +};
26440 +
26441 +struct dwc_otg_qtd;
26442 +
26443 +struct dwc_otg_hcd_urb {
26444 +       void *priv;
26445 +       struct dwc_otg_qtd *qtd;
26446 +       void *buf;
26447 +       dwc_dma_t dma;
26448 +       void *setup_packet;
26449 +       dwc_dma_t setup_dma;
26450 +       uint32_t length;
26451 +       uint32_t actual_length;
26452 +       uint32_t status;
26453 +       uint32_t error_count;
26454 +       uint32_t packet_count;
26455 +       uint32_t flags;
26456 +       uint16_t interval;
26457 +       struct dwc_otg_hcd_pipe_info pipe_info;
26458 +       struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
26459 +};
26460 +
26461 +static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
26462 +{
26463 +       return pipe->ep_num;
26464 +}
26465 +
26466 +static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
26467 +                                               *pipe)
26468 +{
26469 +       return pipe->pipe_type;
26470 +}
26471 +
26472 +static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
26473 +{
26474 +       return pipe->mps;
26475 +}
26476 +
26477 +static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
26478 +                                              *pipe)
26479 +{
26480 +       return pipe->dev_addr;
26481 +}
26482 +
26483 +static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
26484 +                                              *pipe)
26485 +{
26486 +       return (pipe->pipe_type == UE_ISOCHRONOUS);
26487 +}
26488 +
26489 +static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
26490 +                                             *pipe)
26491 +{
26492 +       return (pipe->pipe_type == UE_INTERRUPT);
26493 +}
26494 +
26495 +static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
26496 +                                              *pipe)
26497 +{
26498 +       return (pipe->pipe_type == UE_BULK);
26499 +}
26500 +
26501 +static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
26502 +                                                 *pipe)
26503 +{
26504 +       return (pipe->pipe_type == UE_CONTROL);
26505 +}
26506 +
26507 +static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
26508 +{
26509 +       return (pipe->pipe_dir == UE_DIR_IN);
26510 +}
26511 +
26512 +static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
26513 +                                             *pipe)
26514 +{
26515 +       return (!dwc_otg_hcd_is_pipe_in(pipe));
26516 +}
26517 +
26518 +static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
26519 +                                        uint8_t devaddr, uint8_t ep_num,
26520 +                                        uint8_t pipe_type, uint8_t pipe_dir,
26521 +                                        uint16_t mps)
26522 +{
26523 +       pipe->dev_addr = devaddr;
26524 +       pipe->ep_num = ep_num;
26525 +       pipe->pipe_type = pipe_type;
26526 +       pipe->pipe_dir = pipe_dir;
26527 +       pipe->mps = mps;
26528 +}
26529 +
26530 +/**
26531 + * Phases for control transfers.
26532 + */
26533 +typedef enum dwc_otg_control_phase {
26534 +       DWC_OTG_CONTROL_SETUP,
26535 +       DWC_OTG_CONTROL_DATA,
26536 +       DWC_OTG_CONTROL_STATUS
26537 +} dwc_otg_control_phase_e;
26538 +
26539 +/** Transaction types. */
26540 +typedef enum dwc_otg_transaction_type {
26541 +       DWC_OTG_TRANSACTION_NONE,
26542 +       DWC_OTG_TRANSACTION_PERIODIC,
26543 +       DWC_OTG_TRANSACTION_NON_PERIODIC,
26544 +       DWC_OTG_TRANSACTION_ALL
26545 +} dwc_otg_transaction_type_e;
26546 +
26547 +struct dwc_otg_qh;
26548 +
26549 +/**
26550 + * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
26551 + * interrupt, or isochronous transfer. A single QTD is created for each URB
26552 + * (of one of these types) submitted to the HCD. The transfer associated with
26553 + * a QTD may require one or multiple transactions.
26554 + *
26555 + * A QTD is linked to a Queue Head, which is entered in either the
26556 + * non-periodic or periodic schedule for execution. When a QTD is chosen for
26557 + * execution, some or all of its transactions may be executed. After
26558 + * execution, the state of the QTD is updated. The QTD may be retired if all
26559 + * its transactions are complete or if an error occurred. Otherwise, it
26560 + * remains in the schedule so more transactions can be executed later.
26561 + */
26562 +typedef struct dwc_otg_qtd {
26563 +       /**
26564 +        * Determines the PID of the next data packet for the data phase of
26565 +        * control transfers. Ignored for other transfer types.<br>
26566 +        * One of the following values:
26567 +        *      - DWC_OTG_HC_PID_DATA0
26568 +        *      - DWC_OTG_HC_PID_DATA1
26569 +        */
26570 +       uint8_t data_toggle;
26571 +
26572 +       /** Current phase for control transfers (Setup, Data, or Status). */
26573 +       dwc_otg_control_phase_e control_phase;
26574 +
26575 +       /** Keep track of the current split type
26576 +        * for FS/LS endpoints on a HS Hub */
26577 +       uint8_t complete_split;
26578 +
26579 +       /** How many bytes transferred during SSPLIT OUT */
26580 +       uint32_t ssplit_out_xfer_count;
26581 +
26582 +       /**
26583 +        * Holds the number of bus errors that have occurred for a transaction
26584 +        * within this transfer.
26585 +        */
26586 +       uint8_t error_count;
26587 +
26588 +       /**
26589 +        * Index of the next frame descriptor for an isochronous transfer. A
26590 +        * frame descriptor describes the buffer position and length of the
26591 +        * data to be transferred in the next scheduled (micro)frame of an
26592 +        * isochronous transfer. It also holds status for that transaction.
26593 +        * The frame index starts at 0.
26594 +        */
26595 +       uint16_t isoc_frame_index;
26596 +
26597 +       /** Position of the ISOC split on full/low speed */
26598 +       uint8_t isoc_split_pos;
26599 +
26600 +       /** Position of the ISOC split in the buffer for the current frame */
26601 +       uint16_t isoc_split_offset;
26602 +
26603 +       /** URB for this transfer */
26604 +       struct dwc_otg_hcd_urb *urb;
26605 +
26606 +       struct dwc_otg_qh *qh;
26607 +
26608 +       /** This list of QTDs */
26609 +        DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
26610 +
26611 +       /** Indicates if this QTD is currently processed by HW. */
26612 +       uint8_t in_process;
26613 +
26614 +       /** Number of DMA descriptors for this QTD */
26615 +       uint8_t n_desc;
26616 +       
26617 +       /** 
26618 +        * Last activated frame(packet) index. 
26619 +        * Used in Descriptor DMA mode only.
26620 +        */
26621 +       uint16_t isoc_frame_index_last;
26622 +       
26623 +} dwc_otg_qtd_t;
26624 +
26625 +DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
26626 +
26627 +/**
26628 + * A Queue Head (QH) holds the static characteristics of an endpoint and
26629 + * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
26630 + * be entered in either the non-periodic or periodic schedule.
26631 + */
26632 +typedef struct dwc_otg_qh {
26633 +       /**
26634 +        * Endpoint type.
26635 +        * One of the following values:
26636 +        *      - UE_CONTROL
26637 +        *      - UE_BULK
26638 +        *      - UE_INTERRUPT
26639 +        *      - UE_ISOCHRONOUS
26640 +        */
26641 +       uint8_t ep_type;
26642 +       uint8_t ep_is_in;
26643 +
26644 +       /** wMaxPacketSize Field of Endpoint Descriptor. */
26645 +       uint16_t maxp;
26646 +
26647 +       /**
26648 +        * Device speed.
26649 +        * One of the following values:
26650 +        *      - DWC_OTG_EP_SPEED_LOW
26651 +        *      - DWC_OTG_EP_SPEED_FULL
26652 +        *      - DWC_OTG_EP_SPEED_HIGH
26653 +        */
26654 +       uint8_t dev_speed;
26655 +
26656 +       /**
26657 +        * Determines the PID of the next data packet for non-control
26658 +        * transfers. Ignored for control transfers.<br>
26659 +        * One of the following values:
26660 +        *      - DWC_OTG_HC_PID_DATA0
26661 +        *      - DWC_OTG_HC_PID_DATA1
26662 +        */
26663 +       uint8_t data_toggle;
26664 +
26665 +       /** Ping state if 1. */
26666 +       uint8_t ping_state;
26667 +
26668 +       /**
26669 +        * List of QTDs for this QH.
26670 +        */
26671 +       struct dwc_otg_qtd_list qtd_list;
26672 +
26673 +       /** Host channel currently processing transfers for this QH. */
26674 +       struct dwc_hc *channel;
26675 +
26676 +       /** Full/low speed endpoint on high-speed hub requires split. */
26677 +       uint8_t do_split;
26678 +
26679 +       /** @name Periodic schedule information */
26680 +       /** @{ */
26681 +
26682 +       /** Bandwidth in microseconds per (micro)frame. */
26683 +       uint16_t usecs;
26684 +
26685 +       /** Interval between transfers in (micro)frames. */
26686 +       uint16_t interval;
26687 +
26688 +       /**
26689 +        * (micro)frame to initialize a periodic transfer. The transfer
26690 +        * executes in the following (micro)frame.
26691 +        */
26692 +       uint16_t sched_frame;
26693 +
26694 +       /** (micro)frame at which last start split was initialized. */
26695 +       uint16_t start_split_frame;
26696 +
26697 +       /** @} */
26698 +
26699 +       /** 
26700 +        * Used instead of original buffer if 
26701 +        * it(physical address) is not dword-aligned.
26702 +        */
26703 +       uint8_t *dw_align_buf;
26704 +       dwc_dma_t dw_align_buf_dma;
26705 +       
26706 +       /** Entry for QH in either the periodic or non-periodic schedule. */
26707 +       dwc_list_link_t qh_list_entry;
26708 +       
26709 +       /** @name Descriptor DMA support */
26710 +       /** @{ */
26711 +       
26712 +       /** Descriptor List. */
26713 +       dwc_otg_host_dma_desc_t *desc_list;
26714 +       
26715 +       /** Descriptor List physical address. */
26716 +       dwc_dma_t desc_list_dma;
26717 +       
26718 +       /** 
26719 +        * Xfer Bytes array.
26720 +        * Each element corresponds to a descriptor and indicates 
26721 +        * original XferSize size value for the descriptor.
26722 +        */
26723 +       uint32_t *n_bytes;
26724 +       
26725 +       /** Actual number of transfer descriptors in a list. */
26726 +       uint16_t ntd;
26727 +       
26728 +       /** First activated isochronous transfer descriptor index. */
26729 +       uint8_t td_first;
26730 +       /** Last activated isochronous transfer descriptor index. */
26731 +       uint8_t td_last;
26732 +       
26733 +       /** @} */
26734 +       
26735 +} dwc_otg_qh_t;
26736 +
26737 +DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
26738 +
26739 +#ifdef HW2937_WORKAROUND
26740 +
26741 +typedef enum {
26742 +       HW2937_XFER_MODE_IDLE,
26743 +       HW2937_XFER_MODE_IN,
26744 +       HW2937_XFER_MODE_OUT,
26745 +       HW2937_XFER_MODE_PAUSEIN /* Transitioning from IN to IDLE */
26746 +} hw2937_xfer_mode_t;
26747 +#endif
26748 +
26749 +/**
26750 + * This structure holds the state of the HCD, including the non-periodic and
26751 + * periodic schedules.
26752 + */
26753 +struct dwc_otg_hcd {
26754 +       /** DWC OTG Core Interface Layer */
26755 +       dwc_otg_core_if_t *core_if;
26756 +
26757 +       /** Function HCD driver callbacks */
26758 +       struct dwc_otg_hcd_function_ops *fops;
26759 +
26760 +       /** Internal DWC HCD Flags */
26761 +       volatile union dwc_otg_hcd_internal_flags {
26762 +               uint32_t d32;
26763 +               struct {
26764 +                       unsigned port_connect_status_change:1;
26765 +                       unsigned port_connect_status:1;
26766 +                       unsigned port_reset_change:1;
26767 +                       unsigned port_enable_change:1;
26768 +                       unsigned port_suspend_change:1;
26769 +                       unsigned port_over_current_change:1;
26770 +                       unsigned port_l1_change:1;
26771 +                       unsigned reserved:26;
26772 +               } b;
26773 +       } flags;
26774 +
26775 +       /**
26776 +        * Inactive items in the non-periodic schedule. This is a list of
26777 +        * Queue Heads. Transfers associated with these Queue Heads are not
26778 +        * currently assigned to a host channel.
26779 +        */
26780 +       dwc_list_link_t non_periodic_sched_inactive;
26781 +
26782 +       /**
26783 +        * Active items in the non-periodic schedule. This is a list of
26784 +        * Queue Heads. Transfers associated with these Queue Heads are
26785 +        * currently assigned to a host channel.
26786 +        */
26787 +       dwc_list_link_t non_periodic_sched_active;
26788 +
26789 +       /**
26790 +        * Pointer to the next Queue Head to process in the active
26791 +        * non-periodic schedule.
26792 +        */
26793 +       dwc_list_link_t *non_periodic_qh_ptr;
26794 +
26795 +       /**
26796 +        * Inactive items in the periodic schedule. This is a list of QHs for
26797 +        * periodic transfers that are _not_ scheduled for the next frame.
26798 +        * Each QH in the list has an interval counter that determines when it
26799 +        * needs to be scheduled for execution. This scheduling mechanism
26800 +        * allows only a simple calculation for periodic bandwidth used (i.e.
26801 +        * must assume that all periodic transfers may need to execute in the
26802 +        * same frame). However, it greatly simplifies scheduling and should
26803 +        * be sufficient for the vast majority of OTG hosts, which need to
26804 +        * connect to a small number of peripherals at one time.
26805 +        *
26806 +        * Items move from this list to periodic_sched_ready when the QH
26807 +        * interval counter is 0 at SOF.
26808 +        */
26809 +       dwc_list_link_t periodic_sched_inactive;
26810 +
26811 +       /**
26812 +        * List of periodic QHs that are ready for execution in the next
26813 +        * frame, but have not yet been assigned to host channels.
26814 +        *
26815 +        * Items move from this list to periodic_sched_assigned as host
26816 +        * channels become available during the current frame.
26817 +        */
26818 +       dwc_list_link_t periodic_sched_ready;
26819 +
26820 +       /**
26821 +        * List of periodic QHs to be executed in the next frame that are
26822 +        * assigned to host channels.
26823 +        *
26824 +        * Items move from this list to periodic_sched_queued as the
26825 +        * transactions for the QH are queued to the DWC_otg controller.
26826 +        */
26827 +       dwc_list_link_t periodic_sched_assigned;
26828 +
26829 +       /**
26830 +        * List of periodic QHs that have been queued for execution.
26831 +        *
26832 +        * Items move from this list to either periodic_sched_inactive or
26833 +        * periodic_sched_ready when the channel associated with the transfer
26834 +        * is released. If the interval for the QH is 1, the item moves to
26835 +        * periodic_sched_ready because it must be rescheduled for the next
26836 +        * frame. Otherwise, the item moves to periodic_sched_inactive.
26837 +        */
26838 +       dwc_list_link_t periodic_sched_queued;
26839 +
26840 +       /**
26841 +        * Total bandwidth claimed so far for periodic transfers. This value
26842 +        * is in microseconds per (micro)frame. The assumption is that all
26843 +        * periodic transfers may occur in the same (micro)frame.
26844 +        */
26845 +       uint16_t periodic_usecs;
26846 +
26847 +       /**
26848 +        * Frame number read from the core at SOF. The value ranges from 0 to
26849 +        * DWC_HFNUM_MAX_FRNUM.
26850 +        */
26851 +       uint16_t frame_number;
26852 +
26853 +       /**
26854 +        * Free host channels in the controller. This is a list of
26855 +        * dwc_hc_t items.
26856 +        */
26857 +       struct hc_list free_hc_list;
26858 +       /**
26859 +        * Number of host channels assigned to periodic transfers. Currently
26860 +        * assuming that there is a dedicated host channel for each periodic
26861 +        * transaction and at least one host channel available for
26862 +        * non-periodic transactions.
26863 +        */
26864 +       int periodic_channels;
26865 +
26866 +       /**
26867 +        * Number of host channels assigned to non-periodic transfers.
26868 +        */
26869 +       int non_periodic_channels;
26870 +
26871 +       /**
26872 +        * Array of pointers to the host channel descriptors. Allows accessing
26873 +        * a host channel descriptor given the host channel number. This is
26874 +        * useful in interrupt handlers.
26875 +        */
26876 +       struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
26877 +
26878 +       /**
26879 +        * Buffer to use for any data received during the status phase of a
26880 +        * control transfer. Normally no data is transferred during the status
26881 +        * phase. This buffer is used as a bit bucket.
26882 +        */
26883 +       uint8_t *status_buf;
26884 +
26885 +       /**
26886 +        * DMA address for status_buf.
26887 +        */
26888 +       dma_addr_t status_buf_dma;
26889 +#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
26890 +
26891 +       /**
26892 +        * Connection timer. An OTG host must display a message if the device
26893 +        * does not connect. Started when the VBus power is turned on via
26894 +        * sysfs attribute "buspower".
26895 +        */
26896 +       dwc_timer_t *conn_timer;
26897 +
26898 +       /* Tasket to do a reset */
26899 +       dwc_tasklet_t *reset_tasklet;
26900 +
26901 +       /*  */
26902 +       dwc_spinlock_t *lock;
26903 +
26904 +       /**
26905 +        * Private data that could be used by OS wrapper.
26906 +        */
26907 +       void *priv;
26908 +
26909 +       uint8_t otg_port;
26910 +
26911 +       /** Frame List */
26912 +       uint32_t *frame_list;
26913 +
26914 +       /** Frame List DMA address */
26915 +       dma_addr_t frame_list_dma;
26916 +
26917 +#ifdef HW2937_WORKAROUND
26918 +       /** Current transfer mode (IN, OUT, or IDLE) */
26919 +       hw2937_xfer_mode_t hw2937_xfer_mode;
26920 +
26921 +       /** Mask of channels assigned to the current mode */
26922 +       uint32_t hw2937_assigned_channels;
26923 +#endif
26924 +
26925 +#ifdef DEBUG
26926 +       uint32_t frrem_samples;
26927 +       uint64_t frrem_accum;
26928 +
26929 +       uint32_t hfnum_7_samples_a;
26930 +       uint64_t hfnum_7_frrem_accum_a;
26931 +       uint32_t hfnum_0_samples_a;
26932 +       uint64_t hfnum_0_frrem_accum_a;
26933 +       uint32_t hfnum_other_samples_a;
26934 +       uint64_t hfnum_other_frrem_accum_a;
26935 +
26936 +       uint32_t hfnum_7_samples_b;
26937 +       uint64_t hfnum_7_frrem_accum_b;
26938 +       uint32_t hfnum_0_samples_b;
26939 +       uint64_t hfnum_0_frrem_accum_b;
26940 +       uint32_t hfnum_other_samples_b;
26941 +       uint64_t hfnum_other_frrem_accum_b;
26942 +#endif
26943 +};
26944 +
26945 +/** @name Transaction Execution Functions */
26946 +/** @{ */
26947 +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
26948 +                                                                 * hcd);
26949 +extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
26950 +                                   dwc_otg_transaction_type_e tr_type);
26951 +
26952 +/** @} */
26953 +
26954 +/** @name Interrupt Handler Functions */
26955 +/** @{ */
26956 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
26957 +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
26958 +extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
26959 +                                                        dwc_otg_hcd);
26960 +extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
26961 +                                                       dwc_otg_hcd);
26962 +extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
26963 +                                                          dwc_otg_hcd);
26964 +extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
26965 +                                                          dwc_otg_hcd);
26966 +extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
26967 +extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
26968 +                                                            dwc_otg_hcd);
26969 +extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
26970 +extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
26971 +extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
26972 +                                           uint32_t num);
26973 +extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
26974 +extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
26975 +                                                      dwc_otg_hcd);
26976 +/** @} */
26977 +
26978 +/** @name Schedule Queue Functions */
26979 +/** @{ */
26980 +
26981 +/* Implemented in dwc_otg_hcd_queue.c */
26982 +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
26983 +                                          dwc_otg_hcd_urb_t * urb);
26984 +extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
26985 +extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
26986 +extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
26987 +extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
26988 +                                     int sched_csplit);
26989 +
26990 +/** Remove and free a QH */
26991 +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
26992 +                                                 dwc_otg_qh_t * qh)
26993 +{
26994 +       dwc_otg_hcd_qh_remove(hcd, qh);
26995 +       dwc_otg_hcd_qh_free(hcd, qh);
26996 +}
26997 +
26998 +/** Allocates memory for a QH structure.
26999 + * @return Returns the memory allocate or NULL on error. */
27000 +static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(void)
27001 +{
27002 +       return (dwc_otg_qh_t *) dwc_alloc(sizeof(dwc_otg_qh_t));
27003 +}
27004 +
27005 +extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb);
27006 +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
27007 +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
27008 +                              dwc_otg_qh_t ** qh);
27009 +
27010 +/** Allocates memory for a QTD structure.
27011 + * @return Returns the memory allocate or NULL on error. */
27012 +static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void)
27013 +{
27014 +       return (dwc_otg_qtd_t *) dwc_alloc(sizeof(dwc_otg_qtd_t));
27015 +}
27016 +
27017 +/** Frees the memory for a QTD structure.  QTD should already be removed from
27018 + * list.
27019 + * @param qtd QTD to free.*/
27020 +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
27021 +{
27022 +       dwc_free(qtd);
27023 +}
27024 +
27025 +/** Removes a QTD from list.
27026 + * @param hcd HCD instance.
27027 + * @param qtd QTD to remove from list.
27028 + * @param qh QTD belongs to.
27029 + */
27030 +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
27031 +                                         dwc_otg_qtd_t * qtd,
27032 +                                         dwc_otg_qh_t * qh)
27033 +{
27034 +       uint64_t flags;
27035 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
27036 +       DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
27037 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
27038 +}
27039 +
27040 +/** Remove and free a QTD */
27041 +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
27042 +                                                  dwc_otg_qtd_t * qtd,
27043 +                                                  dwc_otg_qh_t * qh)
27044 +{
27045 +       dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
27046 +       dwc_otg_hcd_qtd_free(qtd);
27047 +}
27048 +
27049 +/** @} */
27050 +
27051 +/** @name Descriptor DMA Supporting Functions */
27052 +/** @{ */
27053 +
27054 +extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
27055 +extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
27056 +                                          dwc_hc_t * hc,
27057 +                                          dwc_otg_hc_regs_t * hc_regs,
27058 +                                          dwc_otg_halt_status_e halt_status);
27059 +
27060 +extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
27061 +extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
27062 +
27063 +/** @} */
27064 +               
27065 +/** @name Internal Functions */
27066 +/** @{ */
27067 +dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
27068 +/** @} */
27069 +
27070 +#ifdef CONFIG_USB_DWC_OTG_LPM
27071 +extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
27072 +                                          uint8_t devaddr);
27073 +extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
27074 +#endif
27075 +
27076 +/** Gets the QH that contains the list_head */
27077 +#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
27078 +
27079 +/** Gets the QTD that contains the list_head */
27080 +#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
27081 +
27082 +/** Check if QH is non-periodic  */
27083 +#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
27084 +                                    (_qh_ptr_->ep_type == UE_CONTROL))
27085 +
27086 +/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
27087 +#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
27088 +
27089 +/** Packet size for any kind of endpoint descriptor */
27090 +#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
27091 +
27092 +/**
27093 + * Returns true if _frame1 is less than or equal to _frame2. The comparison is
27094 + * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
27095 + * frame number when the max frame number is reached.
27096 + */
27097 +static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
27098 +{
27099 +       return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
27100 +           (DWC_HFNUM_MAX_FRNUM >> 1);
27101 +}
27102 +
27103 +/**
27104 + * Returns true if _frame1 is greater than _frame2. The comparison is done
27105 + * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
27106 + * number when the max frame number is reached.
27107 + */
27108 +static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
27109 +{
27110 +       return (frame1 != frame2) &&
27111 +           (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
27112 +            (DWC_HFNUM_MAX_FRNUM >> 1));
27113 +}
27114 +
27115 +/**
27116 + * Increments _frame by the amount specified by _inc. The addition is done
27117 + * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
27118 + */
27119 +static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
27120 +{
27121 +       return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
27122 +}
27123 +
27124 +static inline uint16_t dwc_full_frame_num(uint16_t frame)
27125 +{
27126 +       return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
27127 +}
27128 +
27129 +static inline uint16_t dwc_micro_frame_num(uint16_t frame)
27130 +{
27131 +       return frame & 0x7;
27132 +}
27133 +
27134 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
27135 +                                 dwc_otg_hc_regs_t * hc_regs, 
27136 +                                 dwc_otg_qtd_t * qtd);
27137 +
27138 +#ifdef DEBUG
27139 +/**
27140 + * Macro to sample the remaining PHY clocks left in the current frame. This
27141 + * may be used during debugging to determine the average time it takes to
27142 + * execute sections of code. There are two possible sample points, "a" and
27143 + * "b", so the _letter argument must be one of these values.
27144 + *
27145 + * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
27146 + * example, "cat /sys/devices/lm0/hcd_frrem".
27147 + */
27148 +#define dwc_sample_frrem(_hcd, _qh, _letter) \
27149 +{ \
27150 +       hfnum_data_t hfnum; \
27151 +       dwc_otg_qtd_t *qtd; \
27152 +       qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
27153 +       if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
27154 +               hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
27155 +               switch (hfnum.b.frnum & 0x7) { \
27156 +               case 7: \
27157 +                       _hcd->hfnum_7_samples_##_letter++; \
27158 +                       _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
27159 +                       break; \
27160 +               case 0: \
27161 +                       _hcd->hfnum_0_samples_##_letter++; \
27162 +                       _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
27163 +                       break; \
27164 +               default: \
27165 +                       _hcd->hfnum_other_samples_##_letter++; \
27166 +                       _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
27167 +                       break; \
27168 +               } \
27169 +       } \
27170 +}
27171 +#else
27172 +#define dwc_sample_frrem(_hcd, _qh, _letter)
27173 +#endif
27174 +#endif
27175 +#endif                         /* DWC_DEVICE_ONLY */
27176 --- /dev/null
27177 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
27178 @@ -0,0 +1,1106 @@
27179 +/*==========================================================================
27180 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
27181 + * $Revision: #2 $
27182 + * $Date: 2009/04/21 $
27183 + * $Change: 1237473 $
27184 + *
27185 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
27186 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
27187 + * otherwise expressly agreed to in writing between Synopsys and you.
27188 + *
27189 + * The Software IS NOT an item of Licensed Software or Licensed Product under
27190 + * any End User Software License Agreement or Agreement for Licensed Product
27191 + * with Synopsys or any supplement thereto. You are permitted to use and
27192 + * redistribute this Software in source and binary forms, with or without
27193 + * modification, provided that redistributions of source code must retain this
27194 + * notice. You may not view, use, disclose, copy or distribute this file or
27195 + * any information contained herein except pursuant to this license grant from
27196 + * Synopsys. If you do not agree with this notice, including the disclaimer
27197 + * below, then you are not authorized to use the Software.
27198 + *
27199 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
27200 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27201 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27202 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
27203 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27204 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27205 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27206 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27207 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27208 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27209 + * DAMAGE.
27210 + * ========================================================================== */
27211 +#ifndef DWC_DEVICE_ONLY
27212 +
27213 +/** @file
27214 + * This file contains Descriptor DMA support implementation for host mode.
27215 + */
27216
27217 +#include "dwc_otg_hcd.h"
27218 +#include "dwc_otg_regs.h"
27219 +               
27220 +               
27221 +static inline uint8_t frame_list_idx(uint16_t frame)
27222 +{
27223 +       return (frame & (MAX_FRLIST_EN_NUM - 1));
27224 +}
27225 +
27226 +static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed)
27227 +{
27228 +       return (idx + inc) & 
27229 +               (((speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1);
27230 +}
27231 +
27232 +static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed)
27233 +{
27234 +       return (idx - inc) & 
27235 +               (((speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1);
27236 +}
27237 +
27238 +static inline uint16_t max_desc_num(dwc_otg_qh_t * qh)
27239 +{
27240 +       return (((qh->ep_type == UE_ISOCHRONOUS) && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) 
27241 +                                                       ?
27242 +                                                       MAX_DMA_DESC_NUM_HS_ISOC
27243 +                                                       :
27244 +                                                       MAX_DMA_DESC_NUM_GENERIC);
27245 +}
27246 +static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh)
27247 +{
27248 +       return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) 
27249 +                                               ? ((qh->interval + 8 - 1) / 8)
27250 +                                               :
27251 +                                               qh->interval);
27252 +}
27253 +
27254 +static int desc_list_alloc(dwc_otg_qh_t * qh)
27255 +{
27256 +       int retval = 0;
27257 +       
27258 +       qh->desc_list = (dwc_otg_host_dma_desc_t *) 
27259 +                               dwc_dma_alloc(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh),
27260 +                                             &qh->desc_list_dma
27261 +                                             );
27262 +       
27263 +       if (!qh->desc_list) {
27264 +               retval = -DWC_E_NO_MEMORY;
27265 +               DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__);
27266 +               
27267 +       }
27268 +       
27269 +       dwc_memset(qh->desc_list, 0x00, sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
27270 +        
27271 +
27272 +       qh->n_bytes = (uint32_t *) dwc_alloc(sizeof(uint32_t) * max_desc_num(qh));
27273 +       
27274 +       if (!qh->n_bytes) {
27275 +               retval = -DWC_E_NO_MEMORY;
27276 +               DWC_ERROR("%s: Failed to allocate array for descriptors' size actual values\n",
27277 +                         __func__);
27278 +               
27279 +       }       
27280 +       return retval;
27281 +
27282 +}
27283 +
27284 +static void desc_list_free(dwc_otg_qh_t * qh)
27285 +{
27286 +       if(qh->desc_list) {
27287 +               dwc_dma_free(max_desc_num(qh), qh->desc_list, qh->desc_list_dma);
27288 +               qh->desc_list = NULL;
27289 +       }
27290 +       
27291 +       if (qh->n_bytes) {
27292 +               dwc_free(qh->n_bytes);
27293 +               qh->n_bytes = NULL;
27294 +       }
27295 +}
27296 +
27297 +static int frame_list_alloc(dwc_otg_hcd_t * hcd)
27298 +{
27299 +       int retval = 0; 
27300 +       if (hcd->frame_list)
27301 +               return 0;
27302 +       
27303 +       hcd->frame_list = dwc_dma_alloc(4 * MAX_FRLIST_EN_NUM,
27304 +                                       &hcd->frame_list_dma
27305 +                                       );
27306 +       if (!hcd->frame_list) {
27307 +               retval = -DWC_E_NO_MEMORY;
27308 +               DWC_ERROR("%s: Frame List allocation failed\n", __func__);
27309 +       }
27310 +       
27311 +       dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM);
27312 +       
27313 +       return retval;
27314 +}
27315 +
27316 +static void frame_list_free(dwc_otg_hcd_t * hcd)
27317 +{
27318 +       if (!hcd->frame_list)
27319 +               return;
27320 +       
27321 +       dwc_dma_free(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma);
27322 +       hcd->frame_list = NULL;
27323 +}
27324 +
27325 +static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en)
27326 +{
27327 +               
27328 +       hcfg_data_t hcfg;
27329 +
27330 +       hcfg.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hcfg);
27331 +
27332 +       if (hcfg.b.perschedstat) {
27333 +               /* already enabled*/    
27334 +               return;
27335 +       }
27336 +       
27337 +       dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hflbaddr, hcd->frame_list_dma);
27338 +       
27339 +       switch(fr_list_en) {
27340 +       case 64:
27341 +           hcfg.b.frlisten = 3;
27342 +           break;
27343 +       case 32:
27344 +           hcfg.b.frlisten = 2;
27345 +           break;
27346 +       case 16:
27347 +           hcfg.b.frlisten = 1;    
27348 +       case 8:
27349 +           hcfg.b.frlisten = 0;
27350 +       default:
27351 +           break;        
27352 +       }
27353 +       
27354 +       hcfg.b.perschedena = 1;
27355 +
27356 +       DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n");
27357 +       dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
27358 +
27359 +}
27360
27361 +static void per_sched_disable(dwc_otg_hcd_t * hcd)
27362 +{
27363 +       hcfg_data_t hcfg;
27364 +
27365 +       hcfg.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hcfg);
27366 +       
27367 +       if (!hcfg.b.perschedstat) {
27368 +               /* already disabled */  
27369 +               return;
27370 +       }
27371 +       hcfg.b.perschedena = 0;
27372 +       
27373 +       DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n");
27374 +       dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
27375 +}
27376 +
27377 +/* 
27378 + * Activates/Deactivates FrameList entries for the channel 
27379 + * based on endpoint servicing period.
27380 + */
27381 +void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable)
27382 +{
27383 +       uint16_t i, j, inc;
27384 +       dwc_hc_t *hc = qh->channel;
27385 +       
27386 +       inc = frame_incr_val(qh);
27387 +       
27388 +       if (qh->ep_type == UE_ISOCHRONOUS)
27389 +               i = frame_list_idx(qh->sched_frame);
27390 +       else
27391 +               i = 0;
27392 +
27393 +       j = i;
27394 +       do {
27395 +               if (enable)
27396 +                       hcd->frame_list[j] |= (1 << hc->hc_num);
27397 +               else
27398 +                       hcd->frame_list[j] &= ~(1 << hc->hc_num);
27399 +               j = (j + inc) & (MAX_FRLIST_EN_NUM - 1);
27400 +       }
27401 +       while (j != i);
27402 +       
27403 +       if (!enable)
27404 +               return;
27405 +       
27406 +       hc->schinfo = 0;
27407 +       if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) {
27408 +               j = 1;
27409 +               for (i = 0 ; i < 8 / qh->interval; i++) {
27410 +                       hc->schinfo |= j;
27411 +                       j = j << qh->interval;
27412 +               }
27413 +       }
27414 +       else {
27415 +               hc->schinfo = 0xff;
27416 +       }       
27417 +}              
27418 +#if 1
27419 +void dump_frame_list(dwc_otg_hcd_t * hcd)
27420 +{
27421 +       int i = 0;
27422 +       DWC_PRINTF("--FRAME LIST (hex) --\n");          
27423 +       for (i = 0; i < MAX_FRLIST_EN_NUM; i++) {
27424 +               DWC_PRINTF("%x\t",hcd->frame_list[i]);
27425 +               if (!(i % 8) && i)    
27426 +                       DWC_PRINTF("\n");
27427 +       }
27428 +       DWC_PRINTF("\n----\n");
27429 +
27430 +}
27431 +#endif
27432 +
27433 +static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
27434 +{
27435 +       dwc_hc_t *hc = qh->channel;
27436 +       if (dwc_qh_is_non_per(qh)) {
27437 +               hcd->non_periodic_channels--;                   
27438 +       }
27439 +       else {
27440 +               update_frame_list(hcd, qh, 0);
27441 +       }
27442 +       /* 
27443 +        * The condition is added to prevent double cleanup try in case of device
27444 +        * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb().
27445 +        */
27446 +       if (hc->qh) {   
27447 +               dwc_otg_hc_cleanup(hcd->core_if, hc);
27448 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
27449 +               hc->qh = NULL;
27450 +       }
27451 +       
27452 +       qh->channel = NULL;
27453 +       qh->ntd = 0;
27454 +       
27455 +       if (qh->desc_list) {
27456 +               dwc_memset(qh->desc_list, 0x00, 
27457 +                           sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
27458 +       }
27459 +}
27460 +
27461 +/** 
27462 + * Initializes a QH structure's Descriptor DMA related members.
27463 + * Allocates memory for descriptor list.
27464 + * On first periodic QH, allocates memory for FrameList 
27465 + * and enables periodic scheduling.
27466 + *
27467 + * @param hcd The HCD state structure for the DWC OTG controller.
27468 + * @param qh The QH to init.
27469 + *
27470 + * @return 0 if successful, negative error code otherwise.
27471 + */            
27472 +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
27473 +{
27474 +       int retval = 0;
27475 +       
27476 +       if (qh->do_split) {
27477 +               DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n");
27478 +               return -1;
27479 +       }
27480 +
27481 +       retval = desc_list_alloc(qh);
27482 +       
27483 +       if ((retval == 0) && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) {
27484 +               if(!hcd->frame_list) {
27485 +                       retval = frame_list_alloc(hcd); 
27486 +                       /* Enable periodic schedule on first periodic QH */
27487 +                       if (retval == 0)                
27488 +                               per_sched_enable(hcd, MAX_FRLIST_EN_NUM);
27489 +               }
27490 +       }
27491 +       
27492 +       qh->ntd = 0;
27493 +       
27494 +       return retval;
27495 +}
27496 +
27497 +/** 
27498 + * Frees descriptor list memory associated with the QH. 
27499 + * If QH is periodic and the last, frees FrameList memory 
27500 + * and disables periodic scheduling. 
27501 + *
27502 + * @param hcd The HCD state structure for the DWC OTG controller.
27503 + * @param qh The QH to init.
27504 + */
27505 +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
27506 +{
27507 +       desc_list_free(qh);
27508 +
27509 +       /* 
27510 +        * Channel still assigned due to some reasons. 
27511 +        * Seen on Isoc URB dequeue. Channel halted but no subsequent
27512 +        * ChHalted interrupt to release the channel. Afterwards
27513 +        * when it comes here from endpoint disable routine
27514 +        * channel remains assigned.
27515 +        */
27516 +       if (qh->channel)
27517 +               release_channel_ddma(hcd, qh);
27518 +
27519 +       if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) 
27520 +                       && !hcd->periodic_channels && hcd->frame_list) {
27521 +               
27522 +               per_sched_disable(hcd); 
27523 +               frame_list_free(hcd);   
27524 +       }
27525 +}      
27526 +
27527 +static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx)
27528 +{
27529 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
27530 +               /* 
27531 +                * Descriptor set(8 descriptors) index
27532 +                * which is 8-aligned.
27533 +                */     
27534 +               return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
27535 +       }
27536 +       else {
27537 +               return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1));
27538 +       }       
27539 +}
27540 +
27541 +/* 
27542 + * Determine starting frame for Isochronous transfer. 
27543 + * Few frames skipped to prevent race condition with HC. 
27544 + */
27545 +static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t* skip_frames)
27546 +{
27547 +       uint16_t frame = 0;
27548 +       hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd);
27549 +       
27550 +       /* sched_frame is always frame number(not uFrame) both in FS and HS !! */
27551 +       
27552 +       /* 
27553 +        * skip_frames is used to limit activated descriptors number
27554 +        * to avoid the situation when HC services the last activated
27555 +        * descriptor firstly.
27556 +        * Example for FS:
27557 +        * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor
27558 +        * corresponding to curr_frame+1, the descriptor corresponding to frame 2
27559 +        * will be fetched. If the number of descriptors is max=64 (or greather) the list will
27560 +        * be fully programmed with Active descriptors and it is possible case(rare) that the latest 
27561 +        * descriptor(considering rollback) corresponding to frame 2 will be serviced first.
27562 +        * HS case is more probable because, in fact, up to 11 uframes(16 in the code)
27563 +        * may be skipped.
27564 +        */
27565 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
27566 +               /* 
27567 +                * Consider uframe counter also, to start xfer asap.
27568 +                * If half of the frame elapsed skip 2 frames otherwise
27569 +                * just 1 frame. 
27570 +                * Starting descriptor index must be 8-aligned, so
27571 +                * if the current frame is near to complete the next one
27572 +                * is skipped as well.
27573 +                */
27574 +                       
27575 +               if (dwc_micro_frame_num(hcd->frame_number)  >= 5) {
27576 +                       *skip_frames = 2 * 8;
27577 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
27578 +               }       
27579 +               else {
27580 +                       *skip_frames = 1 * 8;
27581 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
27582 +               }       
27583 +                                
27584 +               frame = dwc_full_frame_num(frame); 
27585 +       } else {
27586 +               /* 
27587 +                * Two frames are skipped for FS - the current and the next.
27588 +                * But for descriptor programming, 1 frame(descriptor) is enough,
27589 +                * see example above.
27590 +                */
27591 +               *skip_frames = 1;        
27592 +               frame = dwc_frame_num_inc(hcd->frame_number, 2);
27593 +       }
27594 +       
27595 +       return frame;
27596 +}
27597 +/* 
27598 + * Calculate initial descriptor index for isochronous transfer
27599 + * based on scheduled frame. 
27600 + */
27601 +static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
27602 +{
27603 +       uint16_t frame = 0, fr_idx, fr_idx_tmp; 
27604 +       uint8_t skip_frames = 0 ;
27605 +       /* 
27606 +        * With current ISOC processing algorithm the channel is being
27607 +        * released when no more QTDs in the list(qh->ntd == 0).
27608 +        * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. 
27609 +        *
27610 +        * So qh->channel != NULL branch is not used and just not removed from the
27611 +        * source file. It is required for another possible approach which is,
27612 +        * do not disable and release the channel when ISOC session completed, 
27613 +        * just move QH to inactive schedule until new QTD arrives. 
27614 +        * On new QTD, the QH moved back to 'ready' schedule,
27615 +        * starting frame and therefore starting desc_index are recalculated.
27616 +        * In this case channel is released only on ep_disable.
27617 +        */
27618 +        
27619 +       /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */
27620 +       if (qh->channel) {
27621 +               frame = calc_starting_frame(hcd, qh, &skip_frames);     
27622 +               /* 
27623 +                * Calculate initial descriptor index based on FrameList current bitmap
27624 +                * and servicing period.
27625 +                */
27626 +               fr_idx_tmp = frame_list_idx(frame);
27627 +               fr_idx = (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - fr_idx_tmp) 
27628 +                               % frame_incr_val(qh);
27629 +               fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM;
27630 +       }
27631 +       else {
27632 +               qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames);   
27633 +               fr_idx = frame_list_idx(qh->sched_frame);
27634 +       }
27635 +       
27636 +       qh->td_first = qh->td_last =  frame_to_desc_idx(qh, fr_idx);
27637 +       
27638 +       return skip_frames;
27639 +}
27640
27641 +#define        ISOC_URB_GIVEBACK_ASAP
27642
27643 +#define MAX_ISOC_XFER_SIZE_FS 1023
27644 +#define MAX_ISOC_XFER_SIZE_HS 3072
27645 +#define DESCNUM_THRESHOLD 4
27646 +
27647 +static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t skip_frames)
27648 +{
27649 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
27650 +       dwc_otg_qtd_t *qtd;
27651 +       dwc_otg_host_dma_desc_t *dma_desc;
27652 +       uint16_t idx, inc, n_desc, ntd_max, max_xfer_size;
27653 +       
27654 +       idx = qh->td_last;
27655 +       inc = qh->interval;
27656 +       n_desc = 0;
27657 +       
27658 +       ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval;
27659 +       if (skip_frames && !qh->channel)
27660 +               ntd_max = ntd_max - skip_frames / qh->interval; 
27661 +       
27662 +       max_xfer_size = (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS 
27663 +                                                                : MAX_ISOC_XFER_SIZE_FS;
27664 +                       
27665 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
27666 +               while ((qh->ntd < ntd_max) && (qtd->isoc_frame_index_last < qtd->urb->packet_count)) {
27667 +                               
27668 +                       dma_desc = &qh->desc_list[idx];
27669 +                       dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t));
27670 +
27671 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
27672 +                       
27673 +                       if (frame_desc->length > max_xfer_size)
27674 +                               qh->n_bytes[idx] = max_xfer_size;
27675 +                       else
27676 +                               qh->n_bytes[idx] = frame_desc->length;
27677 +                       dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];
27678 +                       dma_desc->status.b_isoc.a = 1;
27679 +                       
27680 +                       dma_desc->buf = qtd->urb->dma + frame_desc->offset;
27681 +                       
27682 +                       qh->ntd++;
27683 +
27684 +                       qtd->isoc_frame_index_last++;
27685 +                       
27686 +               #ifdef  ISOC_URB_GIVEBACK_ASAP
27687 +                       /* 
27688 +                        * Set IOC for each descriptor corresponding to the 
27689 +                        * last frame of the URB.
27690 +                        */     
27691 +                       if (qtd->isoc_frame_index_last == qtd->urb->packet_count)
27692 +                               dma_desc->status.b_isoc.ioc = 1;
27693 +                       
27694 +               #endif  
27695 +                       idx = desclist_idx_inc(idx, inc, qh->dev_speed);
27696 +                       n_desc++;
27697 +                       
27698 +               }
27699 +               qtd->in_process = 1;
27700 +       }
27701 +       
27702 +       qh->td_last = idx;
27703 +       
27704 +#ifdef ISOC_URB_GIVEBACK_ASAP
27705 +       /* Set IOC for the last descriptor if descriptor list is full */        
27706 +       if (qh->ntd == ntd_max) {
27707 +               idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
27708 +               qh->desc_list[idx].status.b_isoc.ioc = 1;
27709 +       }
27710 +#else  
27711 +       /* 
27712 +        * Set IOC bit only for one descriptor. 
27713 +        * Always try to be ahead of HW processing,
27714 +        * i.e. on IOC generation driver activates next descriptors but
27715 +        * core continues to process descriptors followed the one with IOC set.
27716 +        */
27717 +
27718 +       if (n_desc > DESCNUM_THRESHOLD) {
27719 +               /* 
27720 +                * Move IOC "up". Required even if there is only one QTD 
27721 +                * in the list, cause QTDs migth continue to be queued,
27722 +                * but during the activation it was only one queued.
27723 +                * Actually more than one QTD might be in the list if this function called 
27724 +                * from XferCompletion - QTDs was queued during HW processing of the previous
27725 +                * descriptor chunk.
27726 +                */     
27727 +               idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed);
27728 +       }
27729 +       else {
27730 +               /* 
27731 +                * Set the IOC for the latest descriptor
27732 +                * if either number of descriptor is not greather than threshold
27733 +                * or no more new descriptors activated.
27734 +                */     
27735 +               idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
27736 +       }
27737 +       
27738 +       qh->desc_list[idx].status.b_isoc.ioc = 1;
27739 +#endif
27740 +}
27741 +
27742 +
27743 +static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
27744 +{
27745 +
27746 +       dwc_hc_t *hc;
27747 +       dwc_otg_host_dma_desc_t *dma_desc;
27748 +       dwc_otg_qtd_t *qtd;
27749 +       int     num_packets, len, n_desc = 0;
27750 +       
27751 +       hc =  qh->channel;
27752 +        
27753 +       /* 
27754 +        * Start with hc->xfer_buff initialized in 
27755 +        * assign_and_init_hc(), then if SG transfer consists of multiple URBs,
27756 +        * this pointer re-assigned to the buffer of the currently processed QTD.
27757 +        * For non-SG request there is always one QTD active.
27758 +        */
27759 +       
27760 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
27761 +                       
27762 +               if (n_desc) {
27763 +                       /* SG request - more than 1 QTDs */
27764 +                       hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;
27765 +                       hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;
27766 +               }
27767 +
27768 +               qtd->n_desc = 0;
27769 +               
27770 +               do {
27771 +                       dma_desc = &qh->desc_list[n_desc];
27772 +                       len = hc->xfer_len;
27773 +                       
27774 +
27775 +                       if (len > MAX_DMA_DESC_SIZE)
27776 +                               len = MAX_DMA_DESC_SIZE - hc->max_packet + 1;
27777 +                       
27778 +                       if (hc->ep_is_in) {
27779 +                               if (len > 0) {
27780 +                                       num_packets = (len + hc->max_packet - 1) / hc->max_packet;
27781 +                               }
27782 +                               else {
27783 +                                       /* Need 1 packet for transfer length of 0. */
27784 +                                       num_packets = 1;
27785 +                               }
27786 +                               /* Always program an integral # of max packets for IN transfers. */
27787 +                               len = num_packets * hc->max_packet;     
27788 +                       }                               
27789 +                               
27790 +                       dma_desc->status.b.n_bytes = len;
27791 +                       
27792 +                       qh->n_bytes[n_desc] = len;
27793 +                       
27794 +
27795 +                       if ((qh->ep_type == UE_CONTROL) && (qtd->control_phase == DWC_OTG_CONTROL_SETUP))
27796 +                               dma_desc->status.b.sup = 1; /* Setup Packet */
27797 +                               
27798 +                       dma_desc->status.b.a = 1; /* Active descriptor */
27799 +                       
27800 +                       dma_desc->buf = (uint32_t) hc->xfer_buff;
27801 +
27802 +                       /* 
27803 +                        * Last descriptor(or single) of IN transfer 
27804 +                        * with actual size less than MaxPacket.
27805 +                        */
27806 +                       if (len > hc->xfer_len) {
27807 +                               hc->xfer_len = 0;
27808 +                       }
27809 +                       else {
27810 +                               hc->xfer_buff += len;
27811 +                               hc->xfer_len -= len;
27812 +                       }
27813 +                       
27814 +                       qtd->n_desc++;
27815 +                       n_desc++;
27816 +               }
27817 +               while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC));
27818 +               
27819 +
27820 +               qtd->in_process = 1;
27821 +               
27822 +               if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
27823 +                       break;
27824 +       }
27825 +
27826 +       if (n_desc) {
27827 +               /* Request Transfer Complete interrupt for the last descriptor */
27828 +               qh->desc_list[n_desc-1].status.b.ioc = 1;
27829 +               /* End of List indicator */
27830 +               qh->desc_list[n_desc-1].status.b.eol = 1;
27831 +               
27832 +               hc->ntd = n_desc;
27833 +       }
27834 +}
27835 +
27836 +/** 
27837 + * For Control and Bulk endpoints initializes descriptor list
27838 + * and starts the transfer.
27839 + *
27840 + * For Interrupt and Isochronous endpoints initializes descriptor list
27841 + * then updates FrameList, marking appropriate entries as active.
27842 + * In case of Isochronous, the starting descriptor index is calculated based
27843 + * on the scheduled frame, but only on the first transfer descriptor within a session.
27844 + * Then starts the transfer via enabling the channel. 
27845 + * For Isochronous endpoint the channel is not halted on XferComplete 
27846 + * interrupt so remains assigned to the endpoint(QH) until session is done.
27847 + *
27848 + * @param hcd The HCD state structure for the DWC OTG controller.
27849 + * @param qh The QH to init.
27850 + *
27851 + * @return 0 if successful, negative error code otherwise.
27852 + */
27853 +void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
27854 +{
27855 +       /* Channel is already assigned */
27856 +       dwc_hc_t *hc = qh->channel;
27857 +       uint8_t skip_frames = 0;
27858 +       
27859 +       switch (hc->ep_type) {
27860 +       case DWC_OTG_EP_TYPE_CONTROL:
27861 +       case DWC_OTG_EP_TYPE_BULK:
27862 +               init_non_isoc_dma_desc(hcd, qh);
27863 +               
27864 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
27865 +               break;
27866 +       case DWC_OTG_EP_TYPE_INTR:
27867 +               init_non_isoc_dma_desc(hcd, qh);
27868 +               
27869 +               update_frame_list(hcd, qh, 1);
27870 +               
27871 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
27872 +               break;
27873 +       case DWC_OTG_EP_TYPE_ISOC:
27874 +                       
27875 +               if(!qh->ntd)
27876 +                       skip_frames = recalc_initial_desc_idx(hcd, qh);
27877 +               
27878 +               init_isoc_dma_desc(hcd, qh, skip_frames);
27879 +
27880 +               if (!hc->xfer_started) {
27881 +
27882 +                       update_frame_list(hcd, qh, 1);
27883 +               
27884 +                       /* 
27885 +                        * Always set to max, instead of actual size.
27886 +                        * Otherwise ntd will be changed with 
27887 +                        * channel being enabled. Not recommended.
27888 +                        *
27889 +                        */     
27890 +                       hc->ntd = max_desc_num(qh);
27891 +                       /* Enable channel only once for ISOC */ 
27892 +                       dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
27893 +               }
27894 +               
27895 +               break;
27896 +       default:
27897 +               
27898 +               break;
27899 +       }
27900 +}
27901 +
27902 +static void complete_isoc_xfer_ddma(dwc_otg_hcd_t *hcd,
27903 +                                  dwc_hc_t *hc,
27904 +                                  dwc_otg_hc_regs_t *hc_regs,
27905 +                                  dwc_otg_halt_status_e halt_status)
27906 +{
27907 +       struct dwc_otg_hcd_iso_packet_desc      *frame_desc;            
27908 +       dwc_otg_qtd_t                           *qtd, *qtd_tmp;
27909 +       dwc_otg_qh_t                            *qh;
27910 +       dwc_otg_host_dma_desc_t                 *dma_desc;
27911 +       uint16_t                                idx, remain;
27912 +       uint8_t                                 urb_compl;      
27913 +       
27914 +       qh = hc->qh;
27915 +       idx = qh->td_first;
27916 +       
27917 +
27918 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
27919 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry)
27920 +                       qtd->in_process = 0;
27921 +               return; 
27922 +       }
27923 +       else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || 
27924 +                       (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) {
27925 +               /* 
27926 +                * Channel is halted in these error cases.
27927 +                * Considered as serious issues.
27928 +                * Complete all URBs marking all frames as failed, 
27929 +                * irrespective whether some of the descriptors(frames) succeeded or no.
27930 +                * Pass error code to completion routine as well, to
27931 +                * update urb->status, some of class drivers might use it to stop
27932 +                * queing transfer requests.
27933 +                */     
27934 +               int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) 
27935 +                                                       ? (-DWC_E_IO)
27936 +                                                       : (-DWC_E_OVERFLOW);
27937 +                                               
27938 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
27939 +                       for(idx = 0; idx < qtd->urb->packet_count; idx++) {
27940 +                               frame_desc = &qtd->urb->iso_descs[idx];
27941 +                               frame_desc->status = err;
27942 +                       }
27943 +                       hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err);
27944 +                       dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
27945 +               }
27946 +               return; 
27947 +       }
27948 +       
27949 +       
27950 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
27951 +               
27952 +               if (!qtd->in_process)
27953 +                   break;
27954 +               
27955 +               urb_compl = 0;
27956 +               
27957 +               do {
27958 +
27959 +                       dma_desc = &qh->desc_list[idx];
27960 +                       
27961 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
27962 +                       remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0;
27963 +       
27964 +                       if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) {
27965 +                               /* 
27966 +                                * XactError or, unable to complete all the transactions 
27967 +                                * in the scheduled micro-frame/frame, 
27968 +                                * both indicated by DMA_DESC_STS_PKTERR.
27969 +                                */     
27970 +                               qtd->urb->error_count++;
27971 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
27972 +                               frame_desc->status = -DWC_E_PROTOCOL;
27973 +                       }
27974 +                       else {
27975 +                               /* Success */   
27976 +                                                               
27977 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
27978 +                               frame_desc->status = 0;
27979 +                       }
27980 +                       
27981 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
27982 +                               /*
27983 +                                * urb->status is not used for isoc transfers here.
27984 +                                * The individual frame_desc status are used instead.
27985 +                                */
27986 +
27987 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
27988 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
27989 +                               
27990 +                               /* 
27991 +                                * This check is necessary because urb_dequeue can be called 
27992 +                                * from urb complete callback(sound driver example).
27993 +                                * All pending URBs are dequeued there, so no need for
27994 +                                * further processing.
27995 +                                */
27996 +                               if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {   
27997 +                                       return;
27998 +                               }
27999 +                               
28000 +                               urb_compl = 1;          
28001 +                               
28002 +                       }
28003 +                       
28004 +                       qh->ntd--;
28005 +                       
28006 +                       /* Stop if IOC requested descriptor reached */
28007 +                       if (dma_desc->status.b_isoc.ioc) {
28008 +                               idx = desclist_idx_inc(idx, qh->interval, hc->speed);   
28009 +                               goto stop_scan;
28010 +                       }
28011 +                       
28012 +                       idx = desclist_idx_inc(idx, qh->interval, hc->speed);
28013 +                       
28014 +                       if (urb_compl)
28015 +                               break;
28016 +               }
28017 +               while(idx != qh->td_first);
28018 +       }
28019 +stop_scan:     
28020 +       qh->td_first = idx;
28021 +}
28022 +       
28023 +uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
28024 +                          dwc_hc_t * hc,
28025 +                          dwc_otg_qtd_t * qtd,
28026 +                          dwc_otg_host_dma_desc_t * dma_desc,
28027 +                          dwc_otg_halt_status_e halt_status,
28028 +                          uint32_t n_bytes,
28029 +                          uint8_t *xfer_done)
28030 +{
28031 +
28032 +       uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0;
28033 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
28034 +       
28035 +       
28036 +       if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
28037 +               urb->status = -DWC_E_IO;
28038 +               return 1;
28039 +       }
28040 +       if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) {
28041 +               switch (halt_status) {
28042 +               case DWC_OTG_HC_XFER_STALL:
28043 +                       urb->status = -DWC_E_PIPE;
28044 +                       break;
28045 +               case DWC_OTG_HC_XFER_BABBLE_ERR:
28046 +                       urb->status = -DWC_E_OVERFLOW;
28047 +                       break;
28048 +               case DWC_OTG_HC_XFER_XACT_ERR:
28049 +                       urb->status = -DWC_E_PROTOCOL;
28050 +                       break;
28051 +               default:        
28052 +                       DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__,
28053 +                                 halt_status);
28054 +                       break;
28055 +               }
28056 +               return 1;
28057 +       }
28058 +       
28059 +       if (dma_desc->status.b.a == 1) {
28060 +               DWC_DEBUGPL(DBG_HCDV, "Active descriptor encountered on channel %d\n", hc->hc_num);
28061 +               return 0;
28062 +       }
28063 +       
28064 +       if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {
28065 +           if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
28066 +               urb->actual_length += n_bytes - remain;
28067 +               if (remain || urb->actual_length == urb->length) {
28068 +                       /* 
28069 +                        * For Control Data stage do not set urb->status=0 to prevent
28070 +                        * URB callback. Set it when Status phase done. See below.
28071 +                        */
28072 +                       *xfer_done = 1;
28073 +               }               
28074 +           
28075 +           }
28076 +           else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) {
28077 +               urb->status = 0;
28078 +               *xfer_done = 1;
28079 +           }
28080 +           /* No handling for SETUP stage */
28081 +
28082 +       }
28083 +       else { 
28084 +           /* BULK and INTR */
28085 +           urb->actual_length += n_bytes - remain;
28086 +           if (remain || urb->actual_length == urb->length) {
28087 +               urb->status = 0;
28088 +               *xfer_done = 1;
28089 +           }
28090 +       }
28091 +
28092 +       return 0;
28093 +}
28094 +
28095 +static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
28096 +                                       dwc_hc_t * hc,
28097 +                                       dwc_otg_hc_regs_t * hc_regs,
28098 +                                       dwc_otg_halt_status_e halt_status)
28099 +{
28100 +       dwc_otg_hcd_urb_t       *urb = NULL;
28101 +       dwc_otg_qtd_t           *qtd, *qtd_tmp;
28102 +       dwc_otg_qh_t            *qh;
28103 +       dwc_otg_host_dma_desc_t *dma_desc;
28104 +       uint32_t                n_bytes, n_desc, i;
28105 +       uint8_t                 failed = 0, xfer_done;
28106 +       
28107 +       n_desc = 0;
28108 +       
28109 +       qh = hc->qh;
28110 +
28111 +       
28112 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
28113 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
28114 +                       qtd->in_process = 0;
28115 +               }
28116 +               return;
28117 +       }
28118 +       
28119 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
28120 +               
28121 +               urb = qtd->urb;
28122 +
28123 +               n_bytes = 0; 
28124 +               xfer_done = 0; 
28125 +               
28126 +               for (i = 0; i < qtd->n_desc; i++) {
28127 +                       dma_desc = &qh->desc_list[n_desc];
28128 +               
28129 +                       n_bytes = qh->n_bytes[n_desc];
28130 +                       
28131 +                       
28132 +                       failed = update_non_isoc_urb_state_ddma(hcd, hc, qtd, dma_desc, 
28133 +                                                               halt_status, n_bytes, &xfer_done);
28134 +                       
28135 +                       if (failed || (xfer_done && (urb->status != -DWC_E_IN_PROGRESS))) {
28136 +                               
28137 +                               hcd->fops->complete(hcd, urb->priv, urb, urb->status);
28138 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
28139 +
28140 +                               if (failed)
28141 +                                       goto stop_scan;
28142 +                       }
28143 +                       else if (qh->ep_type == UE_CONTROL) {
28144 +                               if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) {
28145 +                                       if (urb->length > 0) {
28146 +                                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
28147 +                                       } else {
28148 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
28149 +                                       }
28150 +                                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction done\n");
28151 +                               }
28152 +                               else if(qtd->control_phase == DWC_OTG_CONTROL_DATA) {
28153 +                                       if (xfer_done) {
28154 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
28155 +                                               DWC_DEBUGPL(DBG_HCDV, "  Control data transfer done\n");
28156 +                                       } else if (i+1 == qtd->n_desc){
28157 +                                               /* 
28158 +                                                * Last descriptor for Control data stage which is
28159 +                                                * not completed yet.
28160 +                                                */     
28161 +                                               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
28162 +                                       }
28163 +                               }
28164 +                       }
28165 +                       
28166 +                       n_desc++;
28167 +               }
28168 +               
28169 +       }
28170 +       
28171 +stop_scan:     
28172 +       
28173 +       if (qh->ep_type != UE_CONTROL) {
28174 +               /* 
28175 +                * Resetting the data toggle for bulk
28176 +                * and interrupt endpoints in case of stall. See handle_hc_stall_intr() 
28177 +                */     
28178 +               if (halt_status == DWC_OTG_HC_XFER_STALL) {     
28179 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0; 
28180 +               }
28181 +               else {
28182 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
28183 +               }
28184 +       }
28185 +       
28186 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
28187 +               hcint_data_t hcint;
28188 +               hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
28189 +               if (hcint.b.nyet) {
28190 +                       /*
28191 +                        * Got a NYET on the last transaction of the transfer. It
28192 +                        * means that the endpoint should be in the PING state at the
28193 +                        * beginning of the next transfer.
28194 +                        */
28195 +                       qh->ping_state = 1;
28196 +                       clear_hc_int(hc_regs, nyet);
28197 +               }
28198 +
28199 +       }
28200 +
28201 +}
28202 +
28203 +/**
28204 + * This function is called from interrupt handlers.
28205 + * Scans the descriptor list, updates URB's status and
28206 + * calls completion routine for the URB if it's done.
28207 + * Releases the channel to be used by other transfers.
28208 + * In case of Isochronous endpoint the channel is not halted until 
28209 + * the end of the session, i.e. QTD list is empty.
28210 + * If periodic channel released the FrameList is updated accordingly.
28211 + *
28212 + * Calls transaction selection routines to activate pending transfers.
28213 + *
28214 + * @param hcd The HCD state structure for the DWC OTG controller.
28215 + * @param hc Host channel, the transfer is completed on.
28216 + * @param hc_regs Host channel registers.
28217 + * @param halt_status Reason the channel is being halted, 
28218 + *                   or just XferComplete for isochronous transfer
28219 + */
28220 +void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t *hcd,
28221 +                           dwc_hc_t *hc,
28222 +                           dwc_otg_hc_regs_t *hc_regs,
28223 +                           dwc_otg_halt_status_e halt_status)
28224 +{
28225 +       uint8_t continue_isoc_xfer = 0;
28226 +       dwc_otg_transaction_type_e tr_type;
28227 +       dwc_otg_qh_t *qh = hc->qh;
28228 +       
28229 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
28230 +
28231 +               complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
28232 +               
28233 +               /* Release the channel if halted or session completed */        
28234 +               if (halt_status != DWC_OTG_HC_XFER_COMPLETE ||
28235 +                               DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
28236 +
28237 +                       /* Halt the channel if session completed */     
28238 +                       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
28239 +                               dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
28240 +                       }       
28241 +                       
28242 +                       release_channel_ddma(hcd, qh);
28243 +                       dwc_otg_hcd_qh_remove(hcd, qh);
28244 +               }
28245 +               else {
28246 +                       /* Keep in assigned schedule to continue transfer */
28247 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
28248 +                                          &qh->qh_list_entry);
28249 +                       continue_isoc_xfer = 1;
28250 +                               
28251 +               }
28252 +               /** @todo Consider the case when period exceeds FrameList size.
28253 +                *  Frame Rollover interrupt should be used. 
28254 +                */
28255 +       }
28256 +       else {
28257 +               /* Scan descriptor list to complete the URB(s), then release the channel */     
28258 +               complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
28259 +               
28260 +               release_channel_ddma(hcd, qh);
28261 +               
28262 +               dwc_otg_hcd_qh_remove(hcd, qh);
28263 +               
28264 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
28265 +                       /* Add back to inactive non-periodic schedule on normal completion */
28266 +                       dwc_otg_hcd_qh_add(hcd, qh);
28267 +               }
28268 +       
28269 +
28270 +       }
28271 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
28272 +       if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) {
28273 +               if (continue_isoc_xfer) {
28274 +                       if (tr_type == DWC_OTG_TRANSACTION_NONE) {
28275 +                               tr_type = DWC_OTG_TRANSACTION_PERIODIC;
28276 +                       } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) {
28277 +                               tr_type = DWC_OTG_TRANSACTION_ALL;
28278 +                       }
28279 +               }
28280 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
28281 +       }
28282 +}
28283 +       
28284 +#endif /* DWC_DEVICE_ONLY */
28285 --- /dev/null
28286 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
28287 @@ -0,0 +1,393 @@
28288 +/* ==========================================================================
28289 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
28290 + * $Revision: #6 $
28291 + * $Date: 2009/04/21 $
28292 + * $Change: 1237474 $
28293 + *
28294 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
28295 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
28296 + * otherwise expressly agreed to in writing between Synopsys and you.
28297 + *
28298 + * The Software IS NOT an item of Licensed Software or Licensed Product under
28299 + * any End User Software License Agreement or Agreement for Licensed Product
28300 + * with Synopsys or any supplement thereto. You are permitted to use and
28301 + * redistribute this Software in source and binary forms, with or without
28302 + * modification, provided that redistributions of source code must retain this
28303 + * notice. You may not view, use, disclose, copy or distribute this file or
28304 + * any information contained herein except pursuant to this license grant from
28305 + * Synopsys. If you do not agree with this notice, including the disclaimer
28306 + * below, then you are not authorized to use the Software.
28307 + *
28308 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
28309 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28310 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28311 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
28312 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28313 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28314 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28315 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28316 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28317 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28318 + * DAMAGE.
28319 + * ========================================================================== */
28320 +#ifndef DWC_DEVICE_ONLY
28321 +#ifndef __DWC_HCD_IF_H__
28322 +#define __DWC_HCD_IF_H__
28323 +
28324 +#include "dwc_otg_core_if.h"
28325 +
28326 +/** @file
28327 + * This file defines DWC_OTG HCD Core API.
28328 + */
28329 +
28330 +struct dwc_otg_hcd;
28331 +typedef struct dwc_otg_hcd dwc_otg_hcd_t;
28332 +
28333 +struct dwc_otg_hcd_urb;
28334 +typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t;
28335 +
28336 +/** @name HCD Function Driver Callbacks */
28337 +/** @{ */
28338 +
28339 +/** This function is called whenever core switches to host mode. */
28340 +typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd);
28341 +
28342 +/** This function is called when device has been disconnected */
28343 +typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd);
28344 +
28345 +/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */
28346 +typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
28347 +                                                  void *urb_handle,
28348 +                                                  uint32_t * hub_addr,
28349 +                                                  uint32_t * port_addr);
28350 +/** Via this function HCD core gets device speed */
28351 +typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
28352 +                                               void *urb_handle);
28353 +
28354 +/** This function is called when urb is completed */
28355 +typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd,
28356 +                                             void *urb_handle,
28357 +                                             dwc_otg_hcd_urb_t * dwc_otg_urb,
28358 +                                             int32_t status);
28359 +
28360 +/** Via this function HCD core gets b_hnp_enable parameter */
28361 +typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd);
28362 +
28363 +struct dwc_otg_hcd_function_ops {
28364 +       dwc_otg_hcd_start_cb_t start;
28365 +       dwc_otg_hcd_disconnect_cb_t disconnect;
28366 +       dwc_otg_hcd_hub_info_from_urb_cb_t hub_info;
28367 +       dwc_otg_hcd_speed_from_urb_cb_t speed;
28368 +       dwc_otg_hcd_complete_urb_cb_t complete;
28369 +       dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable;
28370 +};
28371 +/** @} */
28372 +
28373 +/** @name HCD Core API */
28374 +/** @{ */
28375 +/** This function allocates dwc_otg_hcd structure and returns pointer on it. */
28376 +extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void);
28377 +
28378 +/** This function should be called to initiate HCD Core.
28379 + *
28380 + * @param hcd The HCD
28381 + * @param core_if The DWC_OTG Core
28382 + *
28383 + * Returns -DWC_E_NO_MEMORY if no enough memory.
28384 + * Returns 0 on success  
28385 + */
28386 +extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if);
28387 +
28388 +/** Frees HCD
28389 + *
28390 + * @param hcd The HCD
28391 + */
28392 +extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
28393 +
28394 +/** This function should be called on every hardware interrupt.
28395 + *
28396 + * @param dwc_otg_hcd The HCD
28397 + *
28398 + * Returns non zero if interrupt is handled
28399 + * Return 0 if interrupt is not handled
28400 + */
28401 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
28402 +
28403 +/**
28404 + * Returns private data set by
28405 + * dwc_otg_hcd_set_priv_data function.
28406 + *
28407 + * @param hcd The HCD
28408 + */
28409 +extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd);
28410 +
28411 +/**
28412 + * Set private data.
28413 + *
28414 + * @param hcd The HCD
28415 + * @param priv_data pointer to be stored in private data
28416 + */
28417 +extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data);
28418 +
28419 +/**
28420 + * This function initializes the HCD Core.
28421 + *
28422 + * @param hcd The HCD
28423 + * @param fops The Function Driver Operations data structure containing pointers to all callbacks.
28424 + *
28425 + * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode.
28426 + * Returns 0 on success
28427 + */
28428 +extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
28429 +                            struct dwc_otg_hcd_function_ops *fops);
28430 +
28431 +/**
28432 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
28433 + * stopped. 
28434 + *
28435 + * @param hcd The HCD
28436 + */
28437 +extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd);
28438 +
28439 +/**
28440 + * Handles hub class-specific requests.
28441 + *
28442 + * @param dwc_otg_hcd The HCD
28443 + * @param typeReq Request Type
28444 + * @param wValue wValue from control request
28445 + * @param wIndex wIndex from control request
28446 + * @param buf data buffer 
28447 + * @param wLength data buffer length
28448 + *
28449 + * Returns -DWC_E_INVALID if invalid argument is passed
28450 + * Returns 0 on success
28451 + */
28452 +extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
28453 +                                  uint16_t typeReq, uint16_t wValue,
28454 +                                  uint16_t wIndex, uint8_t * buf,
28455 +                                  uint16_t wLength);
28456 +
28457 +/**
28458 + * Returns otg port number.
28459 + *
28460 + * @param hcd The HCD
28461 + */
28462 +extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd);
28463 +
28464 +/**
28465 + * Returns 1 if currently core is acting as B host, and 0 otherwise.
28466 + *
28467 + * @param hcd The HCD
28468 + */
28469 +extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd);
28470 +
28471 +/**
28472 + * Returns current frame number.
28473 + *
28474 + * @param hcd The HCD
28475 + */
28476 +extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd);
28477 +
28478 +/**
28479 + * Dumps hcd state.
28480 + *
28481 + * @param hcd The HCD
28482 + */
28483 +extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd);
28484 +
28485 +/**
28486 + * Dump the average frame remaining at SOF. This can be used to
28487 + * determine average interrupt latency. Frame remaining is also shown for
28488 + * start transfer and two additional sample points.
28489 + * Currently this function is not implemented.
28490 + *
28491 + * @param hcd The HCD
28492 + */
28493 +extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd);
28494 +
28495 +/**
28496 + * Sends LPM transaction to the local device.
28497 + *
28498 + * @param hcd The HCD
28499 + * @param devaddr Device Address
28500 + * @param hird Host initiated resume duration
28501 + * @param bRemoteWake Value of bRemoteWake field in LPM transaction
28502 + *
28503 + * Returns negative value if sending LPM transaction was not succeeded.
28504 + * Returns 0 on success.
28505 + */
28506 +extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr,
28507 +                               uint8_t hird, uint8_t bRemoteWake);
28508 +
28509 +/* URB interface */
28510 +
28511 +/**
28512 + * Allocates memory for dwc_otg_hcd_urb structure.
28513 + * Allocated memory should be freed by call dwc_free function.
28514 + *
28515 + * @param hcd The HCD
28516 + * @param iso_desc_count Count of ISOC descriptors
28517 + * @param atomic_alloc Specefies whether to perform atomic allocation.
28518 + */
28519 +extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
28520 +                                               int iso_desc_count,
28521 +                                               int atomic_alloc);
28522 +
28523 +/**
28524 + * Set pipe information in URB.
28525 + *
28526 + * @param hcd_urb DWC_OTG URB
28527 + * @param devaddr Device Address
28528 + * @param ep_num Endpoint Number
28529 + * @param ep_type Endpoint Type
28530 + * @param ep_dir Endpoint Direction
28531 + * @param mps Max Packet Size
28532 + */
28533 +extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb,
28534 +                                        uint8_t devaddr, uint8_t ep_num,
28535 +                                        uint8_t ep_type, uint8_t ep_dir,
28536 +                                        uint16_t mps);
28537 +
28538 +/* Transfer flags */ 
28539 +#define URB_GIVEBACK_ASAP 0x1
28540 +#define URB_SEND_ZERO_PACKET 0x2
28541 +
28542 +/**
28543 + * Sets dwc_otg_hcd_urb parameters.
28544 + *
28545 + * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function.
28546 + * @param urb_handle Unique handle for request, this will be passed back
28547 + * to function driver in completion callback.
28548 + * @param buf The buffer for the data
28549 + * @param dma The DMA buffer for the data
28550 + * @param buflen Transfer length
28551 + * @param sp Buffer for setup data
28552 + * @param sp_dma DMA address of setup data buffer
28553 + * @param flags Transfer flags
28554 + * @param interval Polling interval for interrupt or isochronous transfers.
28555 + */
28556 +extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb,
28557 +                                      void *urb_handle, void *buf,
28558 +                                      dwc_dma_t dma, uint32_t buflen, void *sp,
28559 +                                      dwc_dma_t sp_dma, uint32_t flags,
28560 +                                      uint16_t interval);
28561 +
28562 +/** Gets status from dwc_otg_hcd_urb
28563 + *
28564 + * @param dwc_otg_urb DWC_OTG URB
28565 + */
28566 +extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb);
28567 +
28568 +/** Gets actual length from dwc_otg_hcd_urb
28569 + *
28570 + * @param dwc_otg_urb DWC_OTG URB
28571 + */
28572 +extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *
28573 +                                                 dwc_otg_urb);
28574 +
28575 +/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs
28576 + *
28577 + * @param dwc_otg_urb DWC_OTG URB
28578 + */
28579 +extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *
28580 +                                               dwc_otg_urb);
28581 +
28582 +/** Set ISOC descriptor offset and length
28583 + *
28584 + * @param dwc_otg_urb DWC_OTG URB
28585 + * @param desc_num ISOC descriptor number
28586 + * @param offset Offset from beginig of buffer.
28587 + * @param length Transaction length
28588 + */
28589 +extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
28590 +                                               int desc_num, uint32_t offset,
28591 +                                               uint32_t length);
28592 +
28593 +/** Get status of ISOC descriptor, specified by desc_num
28594 + *
28595 + * @param dwc_otg_urb DWC_OTG URB
28596 + * @param desc_num ISOC descriptor number 
28597 + */
28598 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *
28599 +                                                   dwc_otg_urb, int desc_num);
28600 +
28601 +/** Get actual length of ISOC descriptor, specified by desc_num
28602 + *
28603 + * @param dwc_otg_urb DWC_OTG URB
28604 + * @param desc_num ISOC descriptor number
28605 + */
28606 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
28607 +                                                          dwc_otg_urb,
28608 +                                                          int desc_num);
28609 +
28610 +/** Queue URB. After transfer is completes, the complete callback will be called with the URB status
28611 + *
28612 + * @param dwc_otg_hcd The HCD
28613 + * @param dwc_otg_urb DWC_OTG URB
28614 + * @param ep_handle Out parameter for returning endpoint handle
28615 + *
28616 + * Returns -DWC_E_NO_DEVICE if no device is connected.
28617 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
28618 + * Returns 0 on success.
28619 + */
28620 +extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd,
28621 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb,
28622 +                                  void **ep_handle);
28623 +
28624 +/** De-queue the specified URB
28625 + *
28626 + * @param dwc_otg_hcd The HCD
28627 + * @param dwc_otg_urb DWC_OTG URB
28628 + */
28629 +extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd,
28630 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb);
28631 +
28632 +/** Frees resources in the DWC_otg controller related to a given endpoint.
28633 + * Any URBs for the endpoint must already be dequeued.
28634 + *
28635 + * @param hcd The HCD
28636 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
28637 + * @param retry Number of retries if there are queued transfers.
28638 + *
28639 + * Returns -DWC_E_INVALID if invalid arguments are passed.
28640 + * Returns 0 on success
28641 + */
28642 +extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
28643 +                                       int retry);
28644 +
28645 +/** Returns 1 if status of specified port is changed and 0 otherwise.
28646 + *
28647 + * @param hcd The HCD
28648 + * @param port Port number
28649 + */
28650 +extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port);
28651 +
28652 +/** Call this function to check if bandwidth was allocated for specified endpoint.
28653 + * Only for ISOC and INTERRUPT endpoints.
28654 + *
28655 + * @param hcd The HCD
28656 + * @param ep_handle Endpoint handle
28657 + */
28658 +extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd,
28659 +                                             void *ep_handle);
28660 +
28661 +/** Call this function to check if bandwidth was freed for specified endpoint.
28662 + *
28663 + * @param hcd The HCD
28664 + * @param ep_handle Endpoint handle
28665 + */
28666 +extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle);
28667 +
28668 +/** Returns bandwidth allocated for specified endpoint in microseconds.
28669 + * Only for ISOC and INTERRUPT endpoints.
28670 + *
28671 + * @param hcd The HCD
28672 + * @param ep_handle Endpoint handle
28673 + */
28674 +extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd,
28675 +                                           void *ep_handle);
28676 +
28677 +/** @} */
28678 +
28679 +#endif                         /* __DWC_HCD_IF_H__ */
28680 +#endif                         /* DWC_DEVICE_ONLY */
28681 --- /dev/null
28682 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
28683 @@ -0,0 +1,2065 @@
28684 +/* ==========================================================================
28685 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
28686 + * $Revision: #77 $
28687 + * $Date: 2009/04/21 $
28688 + * $Change: 1237475 $
28689 + *
28690 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
28691 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
28692 + * otherwise expressly agreed to in writing between Synopsys and you.
28693 + *
28694 + * The Software IS NOT an item of Licensed Software or Licensed Product under
28695 + * any End User Software License Agreement or Agreement for Licensed Product
28696 + * with Synopsys or any supplement thereto. You are permitted to use and
28697 + * redistribute this Software in source and binary forms, with or without
28698 + * modification, provided that redistributions of source code must retain this
28699 + * notice. You may not view, use, disclose, copy or distribute this file or
28700 + * any information contained herein except pursuant to this license grant from
28701 + * Synopsys. If you do not agree with this notice, including the disclaimer
28702 + * below, then you are not authorized to use the Software.
28703 + *
28704 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
28705 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28706 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28707 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
28708 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28709 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28710 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28711 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28712 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28713 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28714 + * DAMAGE.
28715 + * ========================================================================== */
28716 +#ifndef DWC_DEVICE_ONLY
28717 +
28718 +#include "dwc_otg_hcd.h"
28719 +#include "dwc_otg_regs.h"
28720 +
28721 +/** @file
28722 + * This file contains the implementation of the HCD Interrupt handlers.
28723 + */
28724 +
28725 +/** This function handles interrupts for the HCD. */
28726 +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
28727 +{
28728 +       int retval = 0;
28729 +
28730 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
28731 +       gintsts_data_t gintsts;
28732 +#ifdef DEBUG
28733 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
28734 +
28735 +        //GRAYG: debugging
28736 +        if (NULL == global_regs) {
28737 +                DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
28738 +                            "core_if=%p\n",
28739 +                            dwc_otg_hcd, global_regs);
28740 +                return retval;
28741 +        }
28742 +#endif
28743 +
28744 +       /* Check if HOST Mode */
28745 +       if (dwc_otg_is_host_mode(core_if)) {
28746 +               gintsts.d32 = dwc_otg_read_core_intr(core_if);
28747 +               if (!gintsts.d32) {
28748 +                       return 0;
28749 +               }
28750 +#ifdef DEBUG
28751 +               /* Don't print debug message in the interrupt handler on SOF */
28752 +#ifndef DEBUG_SOF
28753 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
28754 +#endif
28755 +                       DWC_DEBUGPL(DBG_HCD, "\n");
28756 +#endif
28757 +
28758 +#ifdef DEBUG
28759 +#ifndef DEBUG_SOF
28760 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
28761 +#endif
28762 +                       DWC_DEBUGPL(DBG_HCD,
28763 +                                   "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
28764 +                                   gintsts.d32, core_if);
28765 +#endif
28766 +
28767 +               if (gintsts.b.sofintr) {
28768 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
28769 +               }
28770 +               if (gintsts.b.rxstsqlvl) {
28771 +                       retval |=
28772 +                           dwc_otg_hcd_handle_rx_status_q_level_intr
28773 +                           (dwc_otg_hcd);
28774 +               }
28775 +               if (gintsts.b.nptxfempty) {
28776 +                       retval |=
28777 +                           dwc_otg_hcd_handle_np_tx_fifo_empty_intr
28778 +                           (dwc_otg_hcd);
28779 +               }
28780 +               if (gintsts.b.i2cintr) {
28781 +                       /** @todo Implement i2cintr handler. */
28782 +               }
28783 +               if (gintsts.b.portintr) {
28784 +                       retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
28785 +               }
28786 +               if (gintsts.b.hcintr) {
28787 +                       retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
28788 +               }
28789 +               if (gintsts.b.ptxfempty) {
28790 +                       retval |=
28791 +                           dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
28792 +                           (dwc_otg_hcd);
28793 +               }
28794 +#ifdef DEBUG
28795 +#ifndef DEBUG_SOF
28796 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
28797 +#endif
28798 +               {
28799 +                       DWC_DEBUGPL(DBG_HCD,
28800 +                                   "DWC OTG HCD Finished Servicing Interrupts\n");
28801 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
28802 +                                   dwc_read_reg32(&global_regs->gintsts));
28803 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
28804 +                                   dwc_read_reg32(&global_regs->gintmsk));
28805 +               }
28806 +#endif
28807 +
28808 +#ifdef DEBUG
28809 +#ifndef DEBUG_SOF
28810 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
28811 +#endif
28812 +                       DWC_DEBUGPL(DBG_HCD, "\n");
28813 +#endif
28814 +
28815 +       }
28816 +
28817 +       return retval;
28818 +}
28819 +
28820 +#ifdef DWC_TRACK_MISSED_SOFS
28821 +#warning Compiling code to track missed SOFs
28822 +#define FRAME_NUM_ARRAY_SIZE 1000
28823 +/**
28824 + * This function is for debug only.
28825 + */
28826 +static inline void track_missed_sofs(uint16_t curr_frame_number)
28827 +{
28828 +       static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
28829 +       static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
28830 +       static int frame_num_idx = 0;
28831 +       static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
28832 +       static int dumped_frame_num_array = 0;
28833 +
28834 +       if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
28835 +               if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
28836 +                   curr_frame_number) {
28837 +                       frame_num_array[frame_num_idx] = curr_frame_number;
28838 +                       last_frame_num_array[frame_num_idx++] = last_frame_num;
28839 +               }
28840 +       } else if (!dumped_frame_num_array) {
28841 +               int i;
28842 +               DWC_PRINTF("Frame     Last Frame\n");
28843 +               DWC_PRINTF("-----     ----------\n");
28844 +               for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
28845 +                       DWC_PRINTF("0x%04x    0x%04x\n",
28846 +                                  frame_num_array[i], last_frame_num_array[i]);
28847 +               }
28848 +               dumped_frame_num_array = 1;
28849 +       }
28850 +       last_frame_num = curr_frame_number;
28851 +}
28852 +#endif
28853 +
28854 +/**
28855 + * Handles the start-of-frame interrupt in host mode. Non-periodic
28856 + * transactions may be queued to the DWC_otg controller for the current
28857 + * (micro)frame. Periodic transactions may be queued to the controller for the
28858 + * next (micro)frame.
28859 + */
28860 +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
28861 +{
28862 +       hfnum_data_t hfnum;
28863 +       dwc_list_link_t *qh_entry;
28864 +       dwc_otg_qh_t *qh;
28865 +       dwc_otg_transaction_type_e tr_type;
28866 +       gintsts_data_t gintsts = {.d32 = 0 };
28867 +
28868 +       hfnum.d32 =
28869 +           dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum);
28870 +
28871 +#ifdef DEBUG_SOF
28872 +       DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
28873 +#endif
28874 +       hcd->frame_number = hfnum.b.frnum;
28875 +
28876 +#ifdef DEBUG
28877 +       hcd->frrem_accum += hfnum.b.frrem;
28878 +       hcd->frrem_samples++;
28879 +#endif
28880 +
28881 +#ifdef DWC_TRACK_MISSED_SOFS
28882 +       track_missed_sofs(hcd->frame_number);
28883 +#endif
28884 +       /* Determine whether any periodic QHs should be executed. */
28885 +       qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
28886 +       while (qh_entry != &hcd->periodic_sched_inactive) {
28887 +               qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
28888 +               qh_entry = qh_entry->next;
28889 +               if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
28890 +                       /*
28891 +                        * Move QH to the ready list to be executed next
28892 +                        * (micro)frame.
28893 +                        */
28894 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
28895 +                                          &qh->qh_list_entry);
28896 +               }
28897 +       }
28898 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
28899 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
28900 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
28901 +       }
28902 +
28903 +       /* Clear interrupt */
28904 +       gintsts.b.sofintr = 1;
28905 +       dwc_write_reg32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
28906 +
28907 +       return 1;
28908 +}
28909 +
28910 +/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at
28911 + * least one packet in the Rx FIFO.  The packets are moved from the FIFO to
28912 + * memory if the DWC_otg controller is operating in Slave mode. */
28913 +int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
28914 +{
28915 +       host_grxsts_data_t grxsts;
28916 +       dwc_hc_t *hc = NULL;
28917 +
28918 +       DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
28919 +
28920 +       grxsts.d32 =
28921 +           dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
28922 +
28923 +       hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
28924 +
28925 +       /* Packet Status */
28926 +       DWC_DEBUGPL(DBG_HCDV, "    Ch num = %d\n", grxsts.b.chnum);
28927 +       DWC_DEBUGPL(DBG_HCDV, "    Count = %d\n", grxsts.b.bcnt);
28928 +       DWC_DEBUGPL(DBG_HCDV, "    DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
28929 +                   hc->data_pid_start);
28930 +       DWC_DEBUGPL(DBG_HCDV, "    PStatus = %d\n", grxsts.b.pktsts);
28931 +
28932 +       switch (grxsts.b.pktsts) {
28933 +       case DWC_GRXSTS_PKTSTS_IN:
28934 +               /* Read the data into the host buffer. */
28935 +               if (grxsts.b.bcnt > 0) {
28936 +                       dwc_otg_read_packet(dwc_otg_hcd->core_if,
28937 +                                           hc->xfer_buff, grxsts.b.bcnt);
28938 +
28939 +                       /* Update the HC fields for the next packet received. */
28940 +                       hc->xfer_count += grxsts.b.bcnt;
28941 +                       hc->xfer_buff += grxsts.b.bcnt;
28942 +               }
28943 +
28944 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
28945 +       case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
28946 +       case DWC_GRXSTS_PKTSTS_CH_HALTED:
28947 +               /* Handled in interrupt, just ignore data */
28948 +               break;
28949 +       default:
28950 +               DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
28951 +                         grxsts.b.pktsts);
28952 +               break;
28953 +       }
28954 +
28955 +       return 1;
28956 +}
28957 +
28958 +/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
28959 + * data packets may be written to the FIFO for OUT transfers. More requests
28960 + * may be written to the non-periodic request queue for IN transfers. This
28961 + * interrupt is enabled only in Slave mode. */
28962 +int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
28963 +{
28964 +       DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
28965 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
28966 +                                      DWC_OTG_TRANSACTION_NON_PERIODIC);
28967 +       return 1;
28968 +}
28969 +
28970 +/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data
28971 + * packets may be written to the FIFO for OUT transfers. More requests may be
28972 + * written to the periodic request queue for IN transfers. This interrupt is
28973 + * enabled only in Slave mode. */
28974 +int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
28975 +{
28976 +       DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
28977 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
28978 +                                      DWC_OTG_TRANSACTION_PERIODIC);
28979 +       return 1;
28980 +}
28981 +
28982 +/** There are multiple conditions that can cause a port interrupt. This function
28983 + * determines which interrupt conditions have occurred and handles them
28984 + * appropriately. */
28985 +int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
28986 +{
28987 +       int retval = 0;
28988 +       hprt0_data_t hprt0;
28989 +       hprt0_data_t hprt0_modify;
28990 +
28991 +       hprt0.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0);
28992 +       hprt0_modify.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0);
28993 +
28994 +       /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
28995 +        * GINTSTS */
28996 +
28997 +       hprt0_modify.b.prtena = 0;
28998 +       hprt0_modify.b.prtconndet = 0;
28999 +       hprt0_modify.b.prtenchng = 0;
29000 +       hprt0_modify.b.prtovrcurrchng = 0;
29001 +
29002 +       /* Port Connect Detected
29003 +        * Set flag and clear if detected */
29004 +       if (hprt0.b.prtconndet) {
29005 +               DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
29006 +                           "Port Connect Detected--\n", hprt0.d32);
29007 +               dwc_otg_hcd->flags.b.port_connect_status_change = 1;
29008 +               dwc_otg_hcd->flags.b.port_connect_status = 1;
29009 +               hprt0_modify.b.prtconndet = 1;
29010 +
29011 +               /* B-Device has connected, Delete the connection timer. */
29012 +               DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
29013 +
29014 +               /* The Hub driver asserts a reset when it sees port connect
29015 +                * status change flag */
29016 +               retval |= 1;
29017 +       }
29018 +
29019 +       /* Port Enable Changed
29020 +        * Clear if detected - Set internal flag if disabled */
29021 +       if (hprt0.b.prtenchng) {
29022 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
29023 +                           "Port Enable Changed--\n", hprt0.d32);
29024 +               hprt0_modify.b.prtenchng = 1;
29025 +               if (hprt0.b.prtena == 1) {
29026 +                       int do_reset = 0;
29027 +                       dwc_otg_core_params_t *params =
29028 +                           dwc_otg_hcd->core_if->core_params;
29029 +                       dwc_otg_core_global_regs_t *global_regs =
29030 +                           dwc_otg_hcd->core_if->core_global_regs;
29031 +                       dwc_otg_host_if_t *host_if =
29032 +                           dwc_otg_hcd->core_if->host_if;
29033 +
29034 +                       /* Check if we need to adjust the PHY clock speed for
29035 +                        * low power and adjust it */
29036 +                       if (params->host_support_fs_ls_low_power) {
29037 +                               gusbcfg_data_t usbcfg;
29038 +
29039 +                               usbcfg.d32 =
29040 +                                   dwc_read_reg32(&global_regs->gusbcfg);
29041 +
29042 +                               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
29043 +                                   || hprt0.b.prtspd ==
29044 +                                   DWC_HPRT0_PRTSPD_FULL_SPEED) {
29045 +                                       /*
29046 +                                        * Low power
29047 +                                        */
29048 +                                       hcfg_data_t hcfg;
29049 +                                       if (usbcfg.b.phylpwrclksel == 0) {
29050 +                                               /* Set PHY low power clock select for FS/LS devices */
29051 +                                               usbcfg.b.phylpwrclksel = 1;
29052 +                                               dwc_write_reg32(&global_regs->
29053 +                                                               gusbcfg,
29054 +                                                               usbcfg.d32);
29055 +                                               do_reset = 1;
29056 +                                       }
29057 +
29058 +                                       hcfg.d32 =
29059 +                                           dwc_read_reg32(&host_if->
29060 +                                                          host_global_regs->hcfg);
29061 +
29062 +                                       if (hprt0.b.prtspd ==
29063 +                                           DWC_HPRT0_PRTSPD_LOW_SPEED
29064 +                                           && params->
29065 +                                           host_ls_low_power_phy_clk ==
29066 +                                           DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
29067 +                                       {
29068 +                                               /* 6 MHZ */
29069 +                                               DWC_DEBUGPL(DBG_CIL,
29070 +                                                           "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
29071 +                                               if (hcfg.b.fslspclksel !=
29072 +                                                   DWC_HCFG_6_MHZ) {
29073 +                                                       hcfg.b.fslspclksel =
29074 +                                                           DWC_HCFG_6_MHZ;
29075 +                                                       dwc_write_reg32
29076 +                                                           (&host_if->
29077 +                                                            host_global_regs->
29078 +                                                            hcfg, hcfg.d32);
29079 +                                                       do_reset = 1;
29080 +                                               }
29081 +                                       } else {
29082 +                                               /* 48 MHZ */
29083 +                                               DWC_DEBUGPL(DBG_CIL,
29084 +                                                           "FS_PHY programming HCFG to 48 MHz ()\n");
29085 +                                               if (hcfg.b.fslspclksel !=
29086 +                                                   DWC_HCFG_48_MHZ) {
29087 +                                                       hcfg.b.fslspclksel =
29088 +                                                           DWC_HCFG_48_MHZ;
29089 +                                                       dwc_write_reg32
29090 +                                                           (&host_if->
29091 +                                                            host_global_regs->
29092 +                                                            hcfg, hcfg.d32);
29093 +                                                       do_reset = 1;
29094 +                                               }
29095 +                                       }
29096 +                               } else {
29097 +                                       /*
29098 +                                        * Not low power
29099 +                                        */
29100 +                                       if (usbcfg.b.phylpwrclksel == 1) {
29101 +                                               usbcfg.b.phylpwrclksel = 0;
29102 +                                               dwc_write_reg32(&global_regs->
29103 +                                                               gusbcfg,
29104 +                                                               usbcfg.d32);
29105 +                                               do_reset = 1;
29106 +                                       }
29107 +                               }
29108 +
29109 +                               if (do_reset) {
29110 +                                       DWC_TASK_SCHEDULE(dwc_otg_hcd->
29111 +                                                         reset_tasklet);
29112 +                               }
29113 +                       }
29114 +
29115 +                       if (!do_reset) {
29116 +                               /* Port has been enabled set the reset change flag */
29117 +                               dwc_otg_hcd->flags.b.port_reset_change = 1;
29118 +                       }
29119 +               } else {
29120 +                       dwc_otg_hcd->flags.b.port_enable_change = 1;
29121 +               }
29122 +               retval |= 1;
29123 +       }
29124 +
29125 +       /** Overcurrent Change Interrupt */
29126 +       if (hprt0.b.prtovrcurrchng) {
29127 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
29128 +                           "Port Overcurrent Changed--\n", hprt0.d32);
29129 +               dwc_otg_hcd->flags.b.port_over_current_change = 1;
29130 +               hprt0_modify.b.prtovrcurrchng = 1;
29131 +               retval |= 1;
29132 +       }
29133 +
29134 +       /* Clear Port Interrupts */
29135 +       dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
29136 +
29137 +       return retval;
29138 +}
29139 +
29140 +/** This interrupt indicates that one or more host channels has a pending
29141 + * interrupt. There are multiple conditions that can cause each host channel
29142 + * interrupt. This function determines which conditions have occurred for each
29143 + * host channel interrupt and handles them appropriately. */
29144 +int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
29145 +{
29146 +       int i;
29147 +       int retval = 0;
29148 +       haint_data_t haint;
29149 +
29150 +       /* Clear appropriate bits in HCINTn to clear the interrupt bit in
29151 +        * GINTSTS */
29152 +
29153 +       haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
29154 +
29155 +       for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
29156 +               if (haint.b2.chint & (1 << i)) {
29157 +                       retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
29158 +               }
29159 +       }
29160 +
29161 +       return retval;
29162 +}
29163 +
29164 +
29165 +
29166 +/**
29167 + * Gets the actual length of a transfer after the transfer halts. _halt_status
29168 + * holds the reason for the halt.
29169 + *
29170 + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,
29171 + * *short_read is set to 1 upon return if less than the requested
29172 + * number of bytes were transferred. Otherwise, *short_read is set to 0 upon
29173 + * return. short_read may also be NULL on entry, in which case it remains
29174 + * unchanged.
29175 + */
29176 +static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
29177 +                                      dwc_otg_hc_regs_t * hc_regs,
29178 +                                      dwc_otg_qtd_t * qtd,
29179 +                                      dwc_otg_halt_status_e halt_status,
29180 +                                      int *short_read)
29181 +{
29182 +       hctsiz_data_t hctsiz;
29183 +       uint32_t length;
29184 +
29185 +       if (short_read != NULL) {
29186 +               *short_read = 0;
29187 +       }
29188 +       hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
29189 +
29190 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
29191 +               if (hc->ep_is_in) {
29192 +                       length = hc->xfer_len - hctsiz.b.xfersize;
29193 +                       if (short_read != NULL) {
29194 +                               *short_read = (hctsiz.b.xfersize != 0);
29195 +                       }
29196 +               } else if (hc->qh->do_split) {
29197 +                       length = qtd->ssplit_out_xfer_count;
29198 +               } else {
29199 +                       length = hc->xfer_len;
29200 +               }
29201 +       } else {
29202 +               /*
29203 +                * Must use the hctsiz.pktcnt field to determine how much data
29204 +                * has been transferred. This field reflects the number of
29205 +                * packets that have been transferred via the USB. This is
29206 +                * always an integral number of packets if the transfer was
29207 +                * halted before its normal completion. (Can't use the
29208 +                * hctsiz.xfersize field because that reflects the number of
29209 +                * bytes transferred via the AHB, not the USB).
29210 +                */
29211 +               length =
29212 +                   (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
29213 +       }
29214 +
29215 +       return length;
29216 +}
29217 +
29218 +/**
29219 + * Updates the state of the URB after a Transfer Complete interrupt on the
29220 + * host channel. Updates the actual_length field of the URB based on the
29221 + * number of bytes transferred via the host channel. Sets the URB status
29222 + * if the data transfer is finished.
29223 + *
29224 + * @return 1 if the data transfer specified by the URB is completely finished,
29225 + * 0 otherwise.
29226 + */
29227 +static int update_urb_state_xfer_comp(dwc_hc_t * hc,
29228 +                                     dwc_otg_hc_regs_t * hc_regs,
29229 +                                     dwc_otg_hcd_urb_t * urb,
29230 +                                     dwc_otg_qtd_t * qtd)
29231 +{
29232 +       int xfer_done = 0;
29233 +       int short_read = 0;
29234 +
29235 +       int xfer_length;
29236 +
29237 +       xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,                                               
29238 +                                                    DWC_OTG_HC_XFER_COMPLETE,
29239 +                                                    &short_read);
29240 +
29241 +
29242 +       /* non DWORD-aligned buffer case handling. */
29243 +       if (hc->align_buff && xfer_length && hc->ep_is_in) {
29244 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, xfer_length);
29245 +       }
29246 +
29247 +       urb->actual_length += xfer_length;
29248 +
29249 +       if(xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
29250 +          (urb->flags & URB_SEND_ZERO_PACKET) && (urb->actual_length == urb->length) &&
29251 +          !(urb->length % hc->max_packet)) {
29252 +               xfer_done = 0;
29253 +       } else if (short_read || urb->actual_length == urb->length) {
29254 +               xfer_done = 1;
29255 +               urb->status = 0;
29256 +       }
29257 +       
29258 +#ifdef DEBUG
29259 +       {
29260 +               hctsiz_data_t hctsiz;
29261 +               hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
29262 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
29263 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
29264 +                           hc->hc_num);
29265 +               DWC_DEBUGPL(DBG_HCDV, "  hc->xfer_len %d\n", hc->xfer_len);
29266 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.xfersize %d\n",
29267 +                           hctsiz.b.xfersize);
29268 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
29269 +                           urb->length);
29270 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
29271 +                           urb->actual_length);
29272 +               DWC_DEBUGPL(DBG_HCDV, "  short_read %d, xfer_done %d\n",
29273 +                           short_read, xfer_done);
29274 +       }
29275 +#endif
29276 +
29277 +       return xfer_done;
29278 +}
29279 +
29280 +/*
29281 + * Save the starting data toggle for the next transfer. The data toggle is
29282 + * saved in the QH for non-control transfers and it's saved in the QTD for
29283 + * control transfers.
29284 + */
29285 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
29286 +                            dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
29287 +{
29288 +       hctsiz_data_t hctsiz;
29289 +       hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
29290 +
29291 +       if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
29292 +               dwc_otg_qh_t *qh = hc->qh;
29293 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
29294 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
29295 +               } else {
29296 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA1;
29297 +               }
29298 +       } else {
29299 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
29300 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
29301 +               } else {
29302 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
29303 +               }
29304 +       }
29305 +}
29306 +
29307 +/**
29308 + * Updates the state of an Isochronous URB when the transfer is stopped for
29309 + * any reason. The fields of the current entry in the frame descriptor array
29310 + * are set based on the transfer state and the input _halt_status. Completes
29311 + * the Isochronous URB if all the URB frames have been completed.
29312 + *
29313 + * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be
29314 + * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.
29315 + */
29316 +static dwc_otg_halt_status_e
29317 +update_isoc_urb_state(dwc_otg_hcd_t * hcd,
29318 +                     dwc_hc_t * hc,
29319 +                     dwc_otg_hc_regs_t * hc_regs,
29320 +                     dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
29321 +{
29322 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
29323 +       dwc_otg_halt_status_e ret_val = halt_status;
29324 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
29325 +
29326 +       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
29327 +       switch (halt_status) {
29328 +       case DWC_OTG_HC_XFER_COMPLETE:
29329 +               frame_desc->status = 0;
29330 +               frame_desc->actual_length =
29331 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
29332 +                   
29333 +               /* non DWORD-aligned buffer case handling. */
29334 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
29335 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, 
29336 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
29337 +               }
29338 +               
29339 +               break;
29340 +       case DWC_OTG_HC_XFER_FRAME_OVERRUN:
29341 +               urb->error_count++;
29342 +               if (hc->ep_is_in) {
29343 +                       frame_desc->status = -DWC_E_NO_STREAM_RES;
29344 +               } else {
29345 +                       frame_desc->status = -DWC_E_COMMUNICATION;
29346 +               }
29347 +               frame_desc->actual_length = 0;
29348 +               break;
29349 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
29350 +               urb->error_count++;
29351 +               frame_desc->status = -DWC_E_OVERFLOW;
29352 +               /* Don't need to update actual_length in this case. */
29353 +               break;
29354 +       case DWC_OTG_HC_XFER_XACT_ERR:
29355 +               urb->error_count++;
29356 +               frame_desc->status = -DWC_E_PROTOCOL;
29357 +               frame_desc->actual_length =
29358 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
29359 +               
29360 +               /* non DWORD-aligned buffer case handling. */
29361 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
29362 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, 
29363 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
29364 +               }
29365 +               /* Skip whole frame */
29366 +               if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && 
29367 +                               hc->ep_is_in && hcd->core_if->dma_enable) {
29368 +                       qtd->complete_split = 0;
29369 +                       qtd->isoc_split_offset = 0;
29370 +               }
29371 +                       
29372 +               break;
29373 +       default:
29374 +               DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
29375 +               break;
29376 +       }
29377 +       if (++qtd->isoc_frame_index == urb->packet_count) {
29378 +               /*
29379 +                * urb->status is not used for isoc transfers.
29380 +                * The individual frame_desc statuses are used instead.
29381 +                */
29382 +               hcd->fops->complete(hcd, urb->priv, urb, 0);
29383 +               ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
29384 +       } else {
29385 +               ret_val = DWC_OTG_HC_XFER_COMPLETE;
29386 +       }
29387 +       return ret_val;
29388 +}
29389 +
29390 +/**
29391 + * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
29392 + * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
29393 + * still linked to the QH, the QH is added to the end of the inactive
29394 + * non-periodic schedule. For periodic QHs, removes the QH from the periodic
29395 + * schedule if no more QTDs are linked to the QH.
29396 + */
29397 +static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
29398 +{
29399 +       int continue_split = 0;
29400 +       dwc_otg_qtd_t *qtd;
29401 +
29402 +       DWC_DEBUGPL(DBG_HCDV, "  %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
29403 +
29404 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
29405 +
29406 +       if (qtd->complete_split) {
29407 +               continue_split = 1;
29408 +       } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
29409 +                  qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
29410 +               continue_split = 1;
29411 +       }
29412 +
29413 +       if (free_qtd) {
29414 +               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
29415 +               continue_split = 0;
29416 +       }
29417 +
29418 +       qh->channel = NULL;
29419 +       dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
29420 +}
29421 +
29422 +/**
29423 + * Releases a host channel for use by other transfers. Attempts to select and
29424 + * queue more transactions since at least one host channel is available.
29425 + *
29426 + * @param hcd The HCD state structure.
29427 + * @param hc The host channel to release.
29428 + * @param qtd The QTD associated with the host channel. This QTD may be freed
29429 + * if the transfer is complete or an error has occurred.
29430 + * @param halt_status Reason the channel is being released. This status
29431 + * determines the actions taken by this function.
29432 + */
29433 +static void release_channel(dwc_otg_hcd_t * hcd,
29434 +                           dwc_hc_t * hc,
29435 +                           dwc_otg_qtd_t * qtd,
29436 +                           dwc_otg_halt_status_e halt_status)
29437 +{
29438 +       dwc_otg_transaction_type_e tr_type;
29439 +       int free_qtd;
29440 +
29441 +       DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d, xfer_len %d\n",
29442 +                   __func__, hc->hc_num, halt_status, hc->xfer_len);
29443 +
29444 +#ifdef HW2937_WORKAROUND
29445 +       if (hcd->hw2937_assigned_channels & (1<<hc->hc_num))
29446 +       {
29447 +               if ((hcd->hw2937_assigned_channels &= ~(1<<hc->hc_num)) == 0)
29448 +                       hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IDLE;
29449 +               DWC_DEBUGPL(DBG_HW2937, " release %d, hw2937_ac -> %x\n", hc->hc_num, hcd->hw2937_assigned_channels);
29450 +       }
29451 +       else
29452 +       {
29453 +               DWC_DEBUGPL(DBG_ANY, " Unexpected release %d (hw2937_ac = %x)\n", hc->hc_num, hcd->hw2937_assigned_channels);
29454 +       }
29455 +#endif
29456 +
29457 +       switch (halt_status) {
29458 +       case DWC_OTG_HC_XFER_URB_COMPLETE:
29459 +               free_qtd = 1;
29460 +               break;
29461 +       case DWC_OTG_HC_XFER_AHB_ERR:
29462 +       case DWC_OTG_HC_XFER_STALL:
29463 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
29464 +               free_qtd = 1;
29465 +               break;
29466 +       case DWC_OTG_HC_XFER_XACT_ERR:
29467 +               if (qtd->error_count >= 3) {
29468 +                       DWC_DEBUGPL(DBG_HCDV,
29469 +                                   "  Complete URB with transaction error\n");
29470 +                       free_qtd = 1;
29471 +                       qtd->urb->status = -DWC_E_PROTOCOL;
29472 +                       hcd->fops->complete(hcd, qtd->urb->priv,
29473 +                                           qtd->urb, -DWC_E_PROTOCOL);
29474 +               } else {
29475 +                       free_qtd = 0;
29476 +               }
29477 +               break;
29478 +       case DWC_OTG_HC_XFER_URB_DEQUEUE:
29479 +               /*
29480 +                * The QTD has already been removed and the QH has been
29481 +                * deactivated. Don't want to do anything except release the
29482 +                * host channel and try to queue more transfers.
29483 +                */
29484 +               goto cleanup;
29485 +       case DWC_OTG_HC_XFER_NO_HALT_STATUS:
29486 +               free_qtd = 0;
29487 +               break;
29488 +       default:
29489 +               free_qtd = 0;
29490 +               break;
29491 +       }
29492 +
29493 +       deactivate_qh(hcd, hc->qh, free_qtd);
29494 +
29495 +      cleanup:
29496 +       /*
29497 +        * Release the host channel for use by other transfers. The cleanup
29498 +        * function clears the channel interrupt enables and conditions, so
29499 +        * there's no need to clear the Channel Halted interrupt separately.
29500 +        */
29501 +       dwc_otg_hc_cleanup(hcd->core_if, hc);
29502 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
29503 +
29504 +       switch (hc->ep_type) {
29505 +       case DWC_OTG_EP_TYPE_CONTROL:
29506 +       case DWC_OTG_EP_TYPE_BULK:
29507 +               hcd->non_periodic_channels--;
29508 +               break;
29509 +
29510 +       default:
29511 +               /*
29512 +                * Don't release reservations for periodic channels here.
29513 +                * That's done when a periodic transfer is descheduled (i.e.
29514 +                * when the QH is removed from the periodic schedule).
29515 +                */
29516 +               break;
29517 +       }
29518 +
29519 +       /* Try to queue more transfers now that there's a free channel. */
29520 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
29521 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
29522 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
29523 +       }
29524 +}
29525 +
29526 +
29527 +/**
29528 + * Halts a host channel. If the channel cannot be halted immediately because
29529 + * the request queue is full, this function ensures that the FIFO empty
29530 + * interrupt for the appropriate queue is enabled so that the halt request can
29531 + * be queued when there is space in the request queue.
29532 + *
29533 + * This function may also be called in DMA mode. In that case, the channel is
29534 + * simply released since the core always halts the channel automatically in
29535 + * DMA mode.
29536 + */
29537 +static void halt_channel(dwc_otg_hcd_t * hcd,
29538 +                        dwc_hc_t * hc,
29539 +                        dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
29540 +{
29541 +       if (hcd->core_if->dma_enable) {
29542 +               release_channel(hcd, hc, qtd, halt_status);
29543 +               return;
29544 +       }
29545 +
29546 +       /* Slave mode processing... */
29547 +       dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
29548 +
29549 +       if (hc->halt_on_queue) {
29550 +               gintmsk_data_t gintmsk = {.d32 = 0 };
29551 +               dwc_otg_core_global_regs_t *global_regs;
29552 +               global_regs = hcd->core_if->core_global_regs;
29553 +
29554 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
29555 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
29556 +                       /*
29557 +                        * Make sure the Non-periodic Tx FIFO empty interrupt
29558 +                        * is enabled so that the non-periodic schedule will
29559 +                        * be processed.
29560 +                        */
29561 +                       gintmsk.b.nptxfempty = 1;
29562 +                       dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32);
29563 +               } else {
29564 +                       /*
29565 +                        * Move the QH from the periodic queued schedule to
29566 +                        * the periodic assigned schedule. This allows the
29567 +                        * halt to be queued when the periodic schedule is
29568 +                        * processed.
29569 +                        */
29570 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
29571 +                                          &hc->qh->qh_list_entry);
29572 +
29573 +                       /*
29574 +                        * Make sure the Periodic Tx FIFO Empty interrupt is
29575 +                        * enabled so that the periodic schedule will be
29576 +                        * processed.
29577 +                        */
29578 +                       gintmsk.b.ptxfempty = 1;
29579 +                       dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32);
29580 +               }
29581 +       }
29582 +}
29583 +
29584 +/**
29585 + * Performs common cleanup for non-periodic transfers after a Transfer
29586 + * Complete interrupt. This function should be called after any endpoint type
29587 + * specific handling is finished to release the host channel.
29588 + */
29589 +static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
29590 +                                      dwc_hc_t * hc,
29591 +                                      dwc_otg_hc_regs_t * hc_regs,
29592 +                                      dwc_otg_qtd_t * qtd,
29593 +                                      dwc_otg_halt_status_e halt_status)
29594 +{
29595 +       hcint_data_t hcint;
29596 +
29597 +       qtd->error_count = 0;
29598 +
29599 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
29600 +       if (hcint.b.nyet) {
29601 +               /*
29602 +                * Got a NYET on the last transaction of the transfer. This
29603 +                * means that the endpoint should be in the PING state at the
29604 +                * beginning of the next transfer.
29605 +                */
29606 +               hc->qh->ping_state = 1;
29607 +               clear_hc_int(hc_regs, nyet);
29608 +       }
29609 +
29610 +       /*
29611 +        * Always halt and release the host channel to make it available for
29612 +        * more transfers. There may still be more phases for a control
29613 +        * transfer or more data packets for a bulk transfer at this point,
29614 +        * but the host channel is still halted. A channel will be reassigned
29615 +        * to the transfer when the non-periodic schedule is processed after
29616 +        * the channel is released. This allows transactions to be queued
29617 +        * properly via dwc_otg_hcd_queue_transactions, which also enables the
29618 +        * Tx FIFO Empty interrupt if necessary.
29619 +        */
29620 +       if (hc->ep_is_in) {
29621 +               /*
29622 +                * IN transfers in Slave mode require an explicit disable to
29623 +                * halt the channel. (In DMA mode, this call simply releases
29624 +                * the channel.)
29625 +                */
29626 +               halt_channel(hcd, hc, qtd, halt_status);
29627 +       } else {
29628 +               /*
29629 +                * The channel is automatically disabled by the core for OUT
29630 +                * transfers in Slave mode.
29631 +                */
29632 +               release_channel(hcd, hc, qtd, halt_status);
29633 +       }
29634 +}
29635 +
29636 +/**
29637 + * Performs common cleanup for periodic transfers after a Transfer Complete
29638 + * interrupt. This function should be called after any endpoint type specific
29639 + * handling is finished to release the host channel.
29640 + */
29641 +static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
29642 +                                  dwc_hc_t * hc,
29643 +                                  dwc_otg_hc_regs_t * hc_regs,
29644 +                                  dwc_otg_qtd_t * qtd,
29645 +                                  dwc_otg_halt_status_e halt_status)
29646 +{
29647 +       hctsiz_data_t hctsiz;
29648 +       qtd->error_count = 0;
29649 +
29650 +       hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
29651 +       if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
29652 +               /* Core halts channel in these cases. */
29653 +               release_channel(hcd, hc, qtd, halt_status);
29654 +       } else {
29655 +               /* Flush any outstanding requests from the Tx queue. */
29656 +               halt_channel(hcd, hc, qtd, halt_status);
29657 +       }
29658 +}
29659 +
29660 +static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
29661 +                                            dwc_hc_t * hc,
29662 +                                            dwc_otg_hc_regs_t * hc_regs,
29663 +                                            dwc_otg_qtd_t * qtd)
29664 +{
29665 +       uint32_t len;   
29666 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
29667 +       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
29668 +                               
29669 +       len = get_actual_xfer_length(hc, hc_regs, qtd,
29670 +                                    DWC_OTG_HC_XFER_COMPLETE,
29671 +                                    NULL);
29672 +                    
29673 +       if (!len) {
29674 +               qtd->complete_split = 0;
29675 +               qtd->isoc_split_offset = 0;
29676 +               return 0;
29677 +       }
29678 +       frame_desc->actual_length += len;
29679 +       
29680 +       if (hc->align_buff && len)
29681 +               dwc_memcpy(qtd->urb->buf + frame_desc->offset + qtd->isoc_split_offset, 
29682 +                                                               hc->qh->dw_align_buf, 
29683 +                                                               len);
29684 +       qtd->isoc_split_offset += len;
29685 +       
29686 +       if (frame_desc->length == frame_desc->actual_length) {
29687 +               frame_desc->status = 0;
29688 +               qtd->isoc_frame_index++;
29689 +               qtd->complete_split = 0;
29690 +               qtd->isoc_split_offset = 0;
29691 +       }
29692 +                       
29693 +       if (qtd->isoc_frame_index == qtd->urb->packet_count) {
29694 +               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
29695 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
29696 +       } else {
29697 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
29698 +       }
29699 +       
29700 +       return 1; /* Indicates that channel released */
29701 +}
29702 +/**
29703 + * Handles a host channel Transfer Complete interrupt. This handler may be
29704 + * called in either DMA mode or Slave mode.
29705 + */
29706 +static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
29707 +                                      dwc_hc_t * hc,
29708 +                                      dwc_otg_hc_regs_t * hc_regs,
29709 +                                      dwc_otg_qtd_t * qtd)
29710 +{
29711 +       int urb_xfer_done;
29712 +       dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
29713 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
29714 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
29715 +
29716 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
29717 +                   "Transfer Complete--\n", hc->hc_num);
29718 +
29719 +       if (hcd->core_if->dma_desc_enable) {
29720 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
29721 +               if (pipe_type == UE_ISOCHRONOUS) {
29722 +                       /* Do not disable the interrupt, just clear it */       
29723 +                       clear_hc_int(hc_regs, xfercomp);
29724 +                       return 1;
29725 +               }
29726 +               goto handle_xfercomp_done;
29727 +       }
29728 +
29729 +       /*
29730 +        * Handle xfer complete on CSPLIT.
29731 +        */
29732 +
29733 +       if (hc->qh->do_split) {
29734 +               if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in && hcd->core_if->dma_enable) {
29735 +                       if (qtd->complete_split && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, qtd))
29736 +                               goto handle_xfercomp_done;
29737 +               }
29738 +               else {
29739 +                        qtd->complete_split = 0;
29740 +                }
29741 +       }
29742 +
29743 +       /* Update the QTD and URB states. */
29744 +       switch (pipe_type) {
29745 +       case UE_CONTROL:
29746 +               switch (qtd->control_phase) {
29747 +               case DWC_OTG_CONTROL_SETUP:
29748 +                       if (urb->length > 0) {
29749 +                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
29750 +                       } else {
29751 +                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
29752 +                       }
29753 +                       DWC_DEBUGPL(DBG_HCDV,
29754 +                                   "  Control setup transaction done\n");
29755 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
29756 +                       break;
29757 +               case DWC_OTG_CONTROL_DATA:{
29758 +                               urb_xfer_done =
29759 +                                   update_urb_state_xfer_comp(hc, hc_regs, urb,
29760 +                                                              qtd);
29761 +                               if (urb_xfer_done) {
29762 +                                       qtd->control_phase =
29763 +                                           DWC_OTG_CONTROL_STATUS;
29764 +                                       DWC_DEBUGPL(DBG_HCDV,
29765 +                                                   "  Control data transfer done\n");
29766 +                               } else {
29767 +                                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
29768 +                               }
29769 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
29770 +                               break;
29771 +                       }
29772 +               case DWC_OTG_CONTROL_STATUS:
29773 +                       DWC_DEBUGPL(DBG_HCDV, "  Control transfer complete\n");
29774 +                       if (urb->status == -DWC_E_IN_PROGRESS) {
29775 +                               urb->status = 0;
29776 +                       }
29777 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
29778 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
29779 +                       break;
29780 +               }
29781 +
29782 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
29783 +               break;
29784 +       case UE_BULK:
29785 +               DWC_DEBUGPL(DBG_HCDV, "  Bulk transfer complete\n");
29786 +               urb_xfer_done =
29787 +                   update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
29788 +               if (urb_xfer_done) {
29789 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
29790 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
29791 +               } else {
29792 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
29793 +               }
29794 +
29795 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
29796 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
29797 +               break;
29798 +       case UE_INTERRUPT:
29799 +               DWC_DEBUGPL(DBG_HCDV, "  Interrupt transfer complete\n");
29800 +               update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
29801 +
29802 +               /*
29803 +                * Interrupt URB is done on the first transfer complete
29804 +                * interrupt.
29805 +                */
29806 +               hcd->fops->complete(hcd, urb->priv, urb, urb->status);
29807 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
29808 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd,
29809 +                                      DWC_OTG_HC_XFER_URB_COMPLETE);
29810 +               break;
29811 +       case UE_ISOCHRONOUS:
29812 +               DWC_DEBUGPL(DBG_HCDV, "  Isochronous transfer complete\n");
29813 +               if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
29814 +                       halt_status =
29815 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
29816 +                                                 DWC_OTG_HC_XFER_COMPLETE);
29817 +               }
29818 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
29819 +               break;
29820 +       }
29821 +
29822 +handle_xfercomp_done:
29823 +       disable_hc_int(hc_regs, xfercompl);
29824 +
29825 +       return 1;
29826 +}
29827 +
29828 +/**
29829 + * Handles a host channel STALL interrupt. This handler may be called in
29830 + * either DMA mode or Slave mode.
29831 + */
29832 +static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
29833 +                                   dwc_hc_t * hc,
29834 +                                   dwc_otg_hc_regs_t * hc_regs,
29835 +                                   dwc_otg_qtd_t * qtd)
29836 +{
29837 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
29838 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
29839 +
29840 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
29841 +                   "STALL Received--\n", hc->hc_num);
29842 +
29843 +       if (hcd->core_if->dma_desc_enable) {
29844 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
29845 +               goto handle_stall_done;
29846 +       }
29847 +
29848 +       if (pipe_type == UE_CONTROL) {
29849 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
29850 +       }
29851 +
29852 +       if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
29853 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
29854 +               /*
29855 +                * USB protocol requires resetting the data toggle for bulk
29856 +                * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
29857 +                * setup command is issued to the endpoint. Anticipate the
29858 +                * CLEAR_FEATURE command since a STALL has occurred and reset
29859 +                * the data toggle now.
29860 +                */
29861 +               hc->qh->data_toggle = 0;
29862 +       }
29863 +
29864 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
29865 +
29866 +handle_stall_done:
29867 +       disable_hc_int(hc_regs, stall);
29868 +
29869 +       return 1;
29870 +}
29871 +
29872 +/*
29873 + * Updates the state of the URB when a transfer has been stopped due to an
29874 + * abnormal condition before the transfer completes. Modifies the
29875 + * actual_length field of the URB to reflect the number of bytes that have
29876 + * actually been transferred via the host channel.
29877 + */
29878 +static void update_urb_state_xfer_intr(dwc_hc_t * hc,
29879 +                                      dwc_otg_hc_regs_t * hc_regs,
29880 +                                      dwc_otg_hcd_urb_t * urb,
29881 +                                      dwc_otg_qtd_t * qtd,
29882 +                                      dwc_otg_halt_status_e halt_status)
29883 +{
29884 +       uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
29885 +                                                           halt_status, NULL);
29886 +       /* non DWORD-aligned buffer case handling. */
29887 +       if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
29888 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, bytes_transferred);
29889 +       }
29890 +       
29891 +       urb->actual_length += bytes_transferred;
29892 +
29893 +#ifdef DEBUG
29894 +       {
29895 +               hctsiz_data_t hctsiz;
29896 +               hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
29897 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
29898 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
29899 +                           hc->hc_num);
29900 +               DWC_DEBUGPL(DBG_HCDV, "  hc->start_pkt_count %d\n",
29901 +                           hc->start_pkt_count);
29902 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
29903 +               DWC_DEBUGPL(DBG_HCDV, "  hc->max_packet %d\n", hc->max_packet);
29904 +               DWC_DEBUGPL(DBG_HCDV, "  bytes_transferred %d\n",
29905 +                           bytes_transferred);
29906 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
29907 +                           urb->actual_length);
29908 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
29909 +                           urb->length);
29910 +       }
29911 +#endif
29912 +}
29913 +
29914 +/**
29915 + * Handles a host channel NAK interrupt. This handler may be called in either
29916 + * DMA mode or Slave mode.
29917 + */
29918 +static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
29919 +                                 dwc_hc_t * hc,
29920 +                                 dwc_otg_hc_regs_t * hc_regs,
29921 +                                 dwc_otg_qtd_t * qtd)
29922 +{
29923 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
29924 +                   "NAK Received--\n", hc->hc_num);
29925 +
29926 +       /*
29927 +        * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
29928 +        * interrupt.  Re-start the SSPLIT transfer.
29929 +        */
29930 +       if (hc->do_split) {
29931 +               if (hc->complete_split) {
29932 +                       qtd->error_count = 0;
29933 +               }
29934 +               qtd->complete_split = 0;
29935 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
29936 +               goto handle_nak_done;
29937 +       }
29938 +
29939 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
29940 +       case UE_CONTROL:
29941 +       case UE_BULK:
29942 +               if (hcd->core_if->dma_enable && hc->ep_is_in) {
29943 +#ifdef HW2937_WORKAROUND
29944 +                       if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) {
29945 +                               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
29946 +                       }
29947 +#endif
29948 +                       /*
29949 +                        * NAK interrupts are enabled on bulk/control IN
29950 +                        * transfers in DMA mode for the sole purpose of
29951 +                        * resetting the error count after a transaction error
29952 +                        * occurs. The core will continue transferring data.
29953 +                        */
29954 +                       qtd->error_count = 0;
29955 +                       goto handle_nak_done;
29956 +               }
29957 +
29958 +               /*
29959 +                * NAK interrupts normally occur during OUT transfers in DMA
29960 +                * or Slave mode. For IN transfers, more requests will be
29961 +                * queued as request queue space is available.
29962 +                */
29963 +               qtd->error_count = 0;
29964 +
29965 +               if (!hc->qh->ping_state) {
29966 +                       update_urb_state_xfer_intr(hc, hc_regs,
29967 +                                                  qtd->urb, qtd,
29968 +                                                  DWC_OTG_HC_XFER_NAK);
29969 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
29970 +
29971 +                       if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
29972 +                               hc->qh->ping_state = 1;
29973 +                       }
29974 +
29975 +               /*
29976 +                * Halt the channel so the transfer can be re-started from
29977 +                * the appropriate point or the PING protocol will
29978 +                * start/continue.
29979 +                */
29980 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
29981 +               break;
29982 +       case UE_INTERRUPT:
29983 +               qtd->error_count = 0;
29984 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
29985 +               break;
29986 +       case UE_ISOCHRONOUS:
29987 +#ifdef HW2937_WORKAROUND
29988 +               if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) {
29989 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
29990 +                       break;
29991 +               }
29992 +#endif
29993 +               /* Should never get called for isochronous transfers. */
29994 +               DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
29995 +               break;
29996 +       }
29997 +
29998 +      handle_nak_done:
29999 +       disable_hc_int(hc_regs, nak);
30000 +
30001 +       return 1;
30002 +}
30003 +
30004 +/**
30005 + * Handles a host channel ACK interrupt. This interrupt is enabled when
30006 + * performing the PING protocol in Slave mode, when errors occur during
30007 + * either Slave mode or DMA mode, and during Start Split transactions.
30008 + */
30009 +static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
30010 +                                 dwc_hc_t * hc,
30011 +                                 dwc_otg_hc_regs_t * hc_regs,
30012 +                                 dwc_otg_qtd_t * qtd)
30013 +{
30014 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
30015 +                   "ACK Received--\n", hc->hc_num);
30016 +
30017 +       if (hc->do_split) {
30018 +               /*
30019 +                * Handle ACK on SSPLIT.
30020 +                * ACK should not occur in CSPLIT.
30021 +                */
30022 +               if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
30023 +                       qtd->ssplit_out_xfer_count = hc->xfer_len;
30024 +               }
30025 +               if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
30026 +                       /* Don't need complete for isochronous out transfers. */
30027 +                       qtd->complete_split = 1;
30028 +               }
30029 +
30030 +               /* ISOC OUT */
30031 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
30032 +                       switch (hc->xact_pos) {
30033 +                       case DWC_HCSPLIT_XACTPOS_ALL:
30034 +                               break;
30035 +                       case DWC_HCSPLIT_XACTPOS_END:
30036 +                               qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
30037 +                               qtd->isoc_split_offset = 0;
30038 +                               break;
30039 +                       case DWC_HCSPLIT_XACTPOS_BEGIN:
30040 +                       case DWC_HCSPLIT_XACTPOS_MID:
30041 +                               /*
30042 +                                * For BEGIN or MID, calculate the length for
30043 +                                * the next microframe to determine the correct
30044 +                                * SSPLIT token, either MID or END.
30045 +                                */
30046 +                               {
30047 +                                       struct dwc_otg_hcd_iso_packet_desc
30048 +                                           *frame_desc;
30049 +
30050 +                                       frame_desc =
30051 +                                           &qtd->urb->iso_descs[qtd->
30052 +                                                                        isoc_frame_index];
30053 +                                       qtd->isoc_split_offset += 188;
30054 +
30055 +                                       if ((frame_desc->length -
30056 +                                            qtd->isoc_split_offset) <= 188) {
30057 +                                               qtd->isoc_split_pos =
30058 +                                                   DWC_HCSPLIT_XACTPOS_END;
30059 +                                       } else {
30060 +                                               qtd->isoc_split_pos =
30061 +                                                   DWC_HCSPLIT_XACTPOS_MID;
30062 +                                       }
30063 +
30064 +                               }
30065 +                               break;
30066 +                       }
30067 +               } else {
30068 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
30069 +               }
30070 +       } else {
30071 +               qtd->error_count = 0;
30072 +
30073 +               if (hc->qh->ping_state) {
30074 +                       hc->qh->ping_state = 0;
30075 +                       /*
30076 +                        * Halt the channel so the transfer can be re-started
30077 +                        * from the appropriate point. This only happens in
30078 +                        * Slave mode. In DMA mode, the ping_state is cleared
30079 +                        * when the transfer is started because the core
30080 +                        * automatically executes the PING, then the transfer.
30081 +                        */
30082 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
30083 +               }
30084 +#ifdef HW2937_WORKAROUND
30085 +               else if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) {
30086 +                       dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
30087 +                       update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, DWC_OTG_HC_XFER_PAUSE_IN);
30088 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
30089 +                       release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_PAUSE_IN);
30090 +               }
30091 +#endif
30092 +       }
30093 +
30094 +       /*
30095 +        * If the ACK occurred when _not_ in the PING state, let the channel
30096 +        * continue transferring data after clearing the error count.
30097 +        */
30098 +
30099 +       disable_hc_int(hc_regs, ack);
30100 +
30101 +       return 1;
30102 +}
30103 +
30104 +/**
30105 + * Handles a host channel NYET interrupt. This interrupt should only occur on
30106 + * Bulk and Control OUT endpoints and for complete split transactions. If a
30107 + * NYET occurs at the same time as a Transfer Complete interrupt, it is
30108 + * handled in the xfercomp interrupt handler, not here. This handler may be
30109 + * called in either DMA mode or Slave mode.
30110 + */
30111 +static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
30112 +                                  dwc_hc_t * hc,
30113 +                                  dwc_otg_hc_regs_t * hc_regs,
30114 +                                  dwc_otg_qtd_t * qtd)
30115 +{
30116 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
30117 +                   "NYET Received--\n", hc->hc_num);
30118 +
30119 +       /*
30120 +        * NYET on CSPLIT
30121 +        * re-do the CSPLIT immediately on non-periodic
30122 +        */
30123 +       if (hc->do_split && hc->complete_split) {
30124 +               if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hcd->core_if->dma_enable) {        
30125 +                       qtd->complete_split = 0;
30126 +                       qtd->isoc_split_offset = 0;
30127 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
30128 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
30129 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);    
30130 +                       }
30131 +                       else
30132 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);  
30133 +                       goto handle_nyet_done;
30134 +               }
30135 +               
30136 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
30137 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
30138 +                       int frnum = dwc_otg_hcd_get_frame_number(hcd);
30139 +
30140 +                       if (dwc_full_frame_num(frnum) !=
30141 +                           dwc_full_frame_num(hc->qh->sched_frame)) {
30142 +                               /*
30143 +                                * No longer in the same full speed frame.
30144 +                                * Treat this as a transaction error.
30145 +                                */
30146 +#if 0
30147 +                               /** @todo Fix system performance so this can
30148 +                                * be treated as an error. Right now complete
30149 +                                * splits cannot be scheduled precisely enough
30150 +                                * due to other system activity, so this error
30151 +                                * occurs regularly in Slave mode.
30152 +                                */
30153 +                               qtd->error_count++;
30154 +#endif
30155 +                               qtd->complete_split = 0;
30156 +                               halt_channel(hcd, hc, qtd,
30157 +                                            DWC_OTG_HC_XFER_XACT_ERR);
30158 +                               /** @todo add support for isoc release */
30159 +                               goto handle_nyet_done;
30160 +                       }
30161 +               }
30162 +
30163 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
30164 +               goto handle_nyet_done;
30165 +       }
30166 +
30167 +       hc->qh->ping_state = 1;
30168 +       qtd->error_count = 0;
30169 +
30170 +       update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
30171 +                                  DWC_OTG_HC_XFER_NYET);
30172 +       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
30173 +
30174 +       /*
30175 +        * Halt the channel and re-start the transfer so the PING
30176 +        * protocol will start.
30177 +        */
30178 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
30179 +
30180 +      handle_nyet_done:
30181 +       disable_hc_int(hc_regs, nyet);
30182 +       return 1;
30183 +}
30184 +
30185 +/**
30186 + * Handles a host channel babble interrupt. This handler may be called in
30187 + * either DMA mode or Slave mode.
30188 + */
30189 +static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
30190 +                                    dwc_hc_t * hc,
30191 +                                    dwc_otg_hc_regs_t * hc_regs,
30192 +                                    dwc_otg_qtd_t * qtd)
30193 +{
30194 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
30195 +                   "Babble Error--\n", hc->hc_num);
30196 +       
30197 +       if (hcd->core_if->dma_desc_enable) {
30198 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_BABBLE_ERR);
30199 +               goto handle_babble_done;
30200 +       }
30201 +
30202 +       if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
30203 +               hcd->fops->complete(hcd, qtd->urb->priv,
30204 +                                   qtd->urb, -DWC_E_OVERFLOW);
30205 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
30206 +       } else {
30207 +               dwc_otg_halt_status_e halt_status;
30208 +               halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
30209 +                                                   DWC_OTG_HC_XFER_BABBLE_ERR);
30210 +               halt_channel(hcd, hc, qtd, halt_status);
30211 +       }
30212 +       
30213 +handle_babble_done:
30214 +       disable_hc_int(hc_regs, bblerr);
30215 +       return 1;
30216 +}
30217 +
30218 +/**
30219 + * Handles a host channel AHB error interrupt. This handler is only called in
30220 + * DMA mode.
30221 + */
30222 +static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
30223 +                                    dwc_hc_t * hc,
30224 +                                    dwc_otg_hc_regs_t * hc_regs,
30225 +                                    dwc_otg_qtd_t * qtd)
30226 +{
30227 +       hcchar_data_t hcchar;
30228 +       hcsplt_data_t hcsplt;
30229 +       hctsiz_data_t hctsiz;
30230 +       uint32_t hcdma;
30231 +       char *pipetype, *speed;
30232 +
30233 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
30234 +
30235 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
30236 +                   "AHB Error--\n", hc->hc_num);
30237 +
30238 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
30239 +       hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt);
30240 +       hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
30241 +       hcdma = dwc_read_reg32(&hc_regs->hcdma);
30242 +
30243 +       DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
30244 +       DWC_ERROR("  hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
30245 +       DWC_ERROR("  hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
30246 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
30247 +       DWC_ERROR("  Device address: %d\n",
30248 +                 dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
30249 +       DWC_ERROR("  Endpoint: %d, %s\n",
30250 +                 dwc_otg_hcd_get_ep_num(&urb->pipe_info),
30251 +                 (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
30252 +       
30253 +
30254 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
30255 +case UE_CONTROL:
30256 +               pipetype = "CONTROL"; 
30257 +               break; 
30258 +       case UE_BULK:
30259 +               pipetype = "BULK"; 
30260 +               break; 
30261 +       case UE_INTERRUPT:
30262 +               pipetype = "INTERRUPT"; 
30263 +               break; 
30264 +       case UE_ISOCHRONOUS:
30265 +               pipetype = "ISOCHRONOUS"; 
30266 +               break; 
30267 +       default:
30268 +               pipetype = "UNKNOWN"; 
30269 +               break;
30270 +       }
30271 +       
30272 +       DWC_ERROR("  Endpoint type: %s\n", pipetype);
30273 +
30274 +       switch (hc->speed) {
30275 +       case DWC_OTG_EP_SPEED_HIGH:
30276 +               speed = "HIGH"; 
30277 +               break; 
30278 +       case DWC_OTG_EP_SPEED_FULL:
30279 +               speed = "FULL"; 
30280 +               break; 
30281 +       case DWC_OTG_EP_SPEED_LOW:
30282 +               speed = "LOW"; 
30283 +               break; 
30284 +       default:
30285 +               speed = "UNKNOWN"; 
30286 +               break;
30287 +       };      
30288 +
30289 +       DWC_ERROR("  Speed: %s\n", speed);
30290 +       
30291 +       DWC_ERROR("  Max packet size: %d\n",
30292 +                 dwc_otg_hcd_get_mps(&urb->pipe_info));
30293 +       DWC_ERROR("  Data buffer length: %d\n", urb->length);
30294 +       DWC_ERROR("  Transfer buffer: %p, Transfer DMA: %p\n",
30295 +                 urb->buf, (void *)urb->dma);
30296 +       DWC_ERROR("  Setup buffer: %p, Setup DMA: %p\n",
30297 +                 urb->setup_packet, (void *)urb->setup_dma);
30298 +       DWC_ERROR("  Interval: %d\n", urb->interval);
30299 +
30300 +       /* Core haltes the channel for Descriptor DMA mode */
30301 +       if (hcd->core_if->dma_desc_enable) {
30302 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_AHB_ERR);
30303 +               goto handle_ahberr_done;
30304 +       }
30305 +
30306 +       hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
30307 +
30308 +       /*
30309 +        * Force a channel halt. Don't call halt_channel because that won't
30310 +        * write to the HCCHARn register in DMA mode to force the halt.
30311 +        */
30312 +       dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
30313 +handle_ahberr_done:
30314 +       disable_hc_int(hc_regs, ahberr);
30315 +       return 1;
30316 +}
30317 +
30318 +/**
30319 + * Handles a host channel transaction error interrupt. This handler may be
30320 + * called in either DMA mode or Slave mode.
30321 + */
30322 +static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
30323 +                                     dwc_hc_t * hc,
30324 +                                     dwc_otg_hc_regs_t * hc_regs,
30325 +                                     dwc_otg_qtd_t * qtd)
30326 +{
30327 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
30328 +                   "Transaction Error--\n", hc->hc_num);
30329 +
30330 +       if (hcd->core_if->dma_desc_enable) {
30331 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_XACT_ERR);
30332 +               goto handle_xacterr_done;
30333 +       }
30334 +
30335 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
30336 +       case UE_CONTROL:
30337 +       case UE_BULK:
30338 +               qtd->error_count++;
30339 +               if (!hc->qh->ping_state) {
30340 +
30341 +                       update_urb_state_xfer_intr(hc, hc_regs,
30342 +                                                  qtd->urb, qtd,
30343 +                                                  DWC_OTG_HC_XFER_XACT_ERR);
30344 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
30345 +                       if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
30346 +                               hc->qh->ping_state = 1;
30347 +                       }
30348 +               }
30349 +
30350 +               /*
30351 +                * Halt the channel so the transfer can be re-started from
30352 +                * the appropriate point or the PING protocol will start.
30353 +                */
30354 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
30355 +               break;
30356 +       case UE_INTERRUPT:
30357 +               qtd->error_count++;
30358 +               if (hc->do_split && hc->complete_split) {
30359 +                       qtd->complete_split = 0;
30360 +               }
30361 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
30362 +               break;
30363 +       case UE_ISOCHRONOUS:
30364 +               {
30365 +                       dwc_otg_halt_status_e halt_status;
30366 +                       halt_status =
30367 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
30368 +                                                 DWC_OTG_HC_XFER_XACT_ERR);
30369 +
30370 +                       halt_channel(hcd, hc, qtd, halt_status);
30371 +               }
30372 +               break;
30373 +       }
30374 +handle_xacterr_done:
30375 +       disable_hc_int(hc_regs, xacterr);
30376 +
30377 +       return 1;
30378 +}
30379 +
30380 +/**
30381 + * Handles a host channel frame overrun interrupt. This handler may be called
30382 + * in either DMA mode or Slave mode.
30383 + */
30384 +static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
30385 +                                      dwc_hc_t * hc,
30386 +                                      dwc_otg_hc_regs_t * hc_regs,
30387 +                                      dwc_otg_qtd_t * qtd)
30388 +{
30389 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
30390 +                   "Frame Overrun--\n", hc->hc_num);
30391 +
30392 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
30393 +       case UE_CONTROL:
30394 +       case UE_BULK:
30395 +               break;
30396 +       case UE_INTERRUPT:
30397 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
30398 +               break;
30399 +       case UE_ISOCHRONOUS:
30400 +               {
30401 +                       dwc_otg_halt_status_e halt_status;
30402 +                       halt_status =
30403 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
30404 +                                                 DWC_OTG_HC_XFER_FRAME_OVERRUN);
30405 +
30406 +                       halt_channel(hcd, hc, qtd, halt_status);
30407 +               }
30408 +               break;
30409 +       }
30410 +
30411 +       disable_hc_int(hc_regs, frmovrun);
30412 +
30413 +       return 1;
30414 +}
30415 +
30416 +/**
30417 + * Handles a host channel data toggle error interrupt. This handler may be
30418 + * called in either DMA mode or Slave mode.
30419 + */
30420 +static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
30421 +                                        dwc_hc_t * hc,
30422 +                                        dwc_otg_hc_regs_t * hc_regs,
30423 +                                        dwc_otg_qtd_t * qtd)
30424 +{
30425 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
30426 +                   "Data Toggle Error--\n", hc->hc_num);
30427 +
30428 +       if (hc->ep_is_in) {
30429 +               qtd->error_count = 0;
30430 +       } else {
30431 +               DWC_ERROR("Data Toggle Error on OUT transfer,"
30432 +                         "channel %d\n", hc->hc_num);
30433 +       }
30434 +
30435 +       disable_hc_int(hc_regs, datatglerr);
30436 +
30437 +       return 1;
30438 +}
30439 +
30440 +#ifdef DEBUG
30441 +/**
30442 + * This function is for debug only. It checks that a valid halt status is set
30443 + * and that HCCHARn.chdis is clear. If there's a problem, corrective action is
30444 + * taken and a warning is issued.
30445 + * @return 1 if halt status is ok, 0 otherwise.
30446 + */
30447 +static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
30448 +                                dwc_hc_t * hc,
30449 +                                dwc_otg_hc_regs_t * hc_regs,
30450 +                                dwc_otg_qtd_t * qtd)
30451 +{
30452 +       hcchar_data_t hcchar;
30453 +       hctsiz_data_t hctsiz;
30454 +       hcint_data_t hcint;
30455 +       hcintmsk_data_t hcintmsk;
30456 +       hcsplt_data_t hcsplt;
30457 +
30458 +       if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
30459 +               /*
30460 +                * This code is here only as a check. This condition should
30461 +                * never happen. Ignore the halt if it does occur.
30462 +                */
30463 +               hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
30464 +               hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
30465 +               hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
30466 +               hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk);
30467 +               hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt);
30468 +               DWC_WARN
30469 +                   ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
30470 +                    "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
30471 +                    "hcint 0x%08x, hcintmsk 0x%08x, "
30472 +                    "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
30473 +                    hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
30474 +                    hcintmsk.d32, hcsplt.d32, qtd->complete_split);
30475 +
30476 +               DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
30477 +                        __func__, hc->hc_num);
30478 +               DWC_WARN("\n");
30479 +               clear_hc_int(hc_regs, chhltd);
30480 +               return 0;
30481 +       }
30482 +
30483 +       /*
30484 +        * This code is here only as a check. hcchar.chdis should
30485 +        * never be set when the halt interrupt occurs. Halt the
30486 +        * channel again if it does occur.
30487 +        */
30488 +       hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
30489 +       if (hcchar.b.chdis) {
30490 +               DWC_WARN("%s: hcchar.chdis set unexpectedly, "
30491 +                        "hcchar 0x%08x, trying to halt again\n",
30492 +                        __func__, hcchar.d32);
30493 +               clear_hc_int(hc_regs, chhltd);
30494 +               hc->halt_pending = 0;
30495 +               halt_channel(hcd, hc, qtd, hc->halt_status);
30496 +               return 0;
30497 +       }
30498 +
30499 +       return 1;
30500 +}
30501 +#endif
30502 +
30503 +/**
30504 + * Handles a host Channel Halted interrupt in DMA mode. This handler
30505 + * determines the reason the channel halted and proceeds accordingly.
30506 + */
30507 +static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
30508 +                                     dwc_hc_t * hc,
30509 +                                     dwc_otg_hc_regs_t * hc_regs,
30510 +                                     dwc_otg_qtd_t * qtd)
30511 +{
30512 +       hcint_data_t hcint;
30513 +       hcintmsk_data_t hcintmsk;
30514 +       int out_nak_enh = 0;
30515 +
30516 +       /* For core with OUT NAK enhancement, the flow for high-
30517 +        * speed CONTROL/BULK OUT is handled a little differently.
30518 +        */
30519 +       if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
30520 +               if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
30521 +                   (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
30522 +                    hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
30523 +                       out_nak_enh = 1;
30524 +               }
30525 +       }
30526 +
30527 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
30528 +           (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR && !hcd->core_if->dma_desc_enable)) {
30529 +               /*
30530 +                * Just release the channel. A dequeue can happen on a
30531 +                * transfer timeout. In the case of an AHB Error, the channel
30532 +                * was forced to halt because there's no way to gracefully
30533 +                * recover.
30534 +                */
30535 +               if (hcd->core_if->dma_desc_enable)
30536 +                       dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, hc->halt_status);
30537 +               else
30538 +                       release_channel(hcd, hc, qtd, hc->halt_status);
30539 +               return;
30540 +       }
30541 +
30542 +       /* Read the HCINTn register to determine the cause for the halt. */
30543 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
30544 +       hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk);
30545 +
30546 +       if (hcint.b.xfercomp) {
30547 +               /** @todo This is here because of a possible hardware bug.  Spec
30548 +                * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
30549 +                * interrupt w/ACK bit set should occur, but I only see the
30550 +                * XFERCOMP bit, even with it masked out.  This is a workaround
30551 +                * for that behavior.  Should fix this when hardware is fixed.
30552 +                */
30553 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
30554 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
30555 +               }
30556 +               handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
30557 +       } else if (hcint.b.stall) {
30558 +               handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
30559 +       } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
30560 +               if (out_nak_enh) {
30561 +                       if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
30562 +                               DWC_DEBUG("XactErr with NYET/NAK/ACK\n");
30563 +                               qtd->error_count = 0;
30564 +                       } else {
30565 +                               DWC_DEBUG("XactErr without NYET/NAK/ACK\n");
30566 +                       }
30567 +               }
30568 +
30569 +               /*
30570 +                * Must handle xacterr before nak or ack. Could get a xacterr
30571 +                * at the same time as either of these on a BULK/CONTROL OUT
30572 +                * that started with a PING. The xacterr takes precedence.
30573 +                */
30574 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
30575 +       } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
30576 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
30577 +       } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {    
30578 +               handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
30579 +       } else if (hcint.b.bblerr) {
30580 +               handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
30581 +       } else if (hcint.b.frmovrun) {
30582 +               handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
30583 +       } else if (!out_nak_enh) {
30584 +               if (hcint.b.nyet) {
30585 +                       /*
30586 +                        * Must handle nyet before nak or ack. Could get a nyet at the
30587 +                        * same time as either of those on a BULK/CONTROL OUT that
30588 +                        * started with a PING. The nyet takes precedence.
30589 +                        */
30590 +                       handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
30591 +               } else if (hcint.b.nak && !hcintmsk.b.nak) {
30592 +                       /*
30593 +                        * If nak is not masked, it's because a non-split IN transfer
30594 +                        * is in an error state. In that case, the nak is handled by
30595 +                        * the nak interrupt handler, not here. Handle nak here for
30596 +                        * BULK/CONTROL OUT transfers, which halt on a NAK to allow
30597 +                        * rewinding the buffer pointer.
30598 +                        */
30599 +                       handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
30600 +               } else if (hcint.b.ack && !hcintmsk.b.ack) {
30601 +                       /*
30602 +                        * If ack is not masked, it's because a non-split IN transfer
30603 +                        * is in an error state. In that case, the ack is handled by
30604 +                        * the ack interrupt handler, not here. Handle ack here for
30605 +                        * split transfers. Start splits halt on ACK.
30606 +                        */
30607 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
30608 +               } else {
30609 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
30610 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
30611 +                               /*
30612 +                                * A periodic transfer halted with no other channel
30613 +                                * interrupts set. Assume it was halted by the core
30614 +                                * because it could not be completed in its scheduled
30615 +                                * (micro)frame.
30616 +                                */
30617 +#ifdef DEBUG
30618 +                               DWC_PRINTF
30619 +                                   ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
30620 +                                    __func__, hc->hc_num);
30621 +#endif
30622 +                               halt_channel(hcd, hc, qtd,
30623 +                                            DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
30624 +                       } else {
30625 +                               DWC_ERROR
30626 +                                   ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
30627 +                                    "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
30628 +                                    __func__, hc->hc_num, hcint.d32,
30629 +                                    dwc_read_reg32(&hcd->core_if->
30630 +                                                   core_global_regs->gintsts));
30631 +                       }
30632 +       
30633 +               }
30634 +       } else {
30635 +               DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
30636 +                          hcint.d32);
30637 +       }
30638 +}
30639 +
30640 +/**
30641 + * Handles a host channel Channel Halted interrupt.
30642 + *
30643 + * In slave mode, this handler is called only when the driver specifically
30644 + * requests a halt. This occurs during handling other host channel interrupts
30645 + * (e.g. nak, xacterr, stall, nyet, etc.).
30646 + *
30647 + * In DMA mode, this is the interrupt that occurs when the core has finished
30648 + * processing a transfer on a channel. Other host channel interrupts (except
30649 + * ahberr) are disabled in DMA mode.
30650 + */
30651 +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
30652 +                                    dwc_hc_t * hc,
30653 +                                    dwc_otg_hc_regs_t * hc_regs,
30654 +                                    dwc_otg_qtd_t * qtd)
30655 +{
30656 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
30657 +                   "Channel Halted--\n", hc->hc_num);
30658 +
30659 +       if (hcd->core_if->dma_enable) {
30660 +               handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
30661 +       } else {
30662 +#ifdef DEBUG
30663 +               if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
30664 +                       return 1;
30665 +               }
30666 +#endif
30667 +               release_channel(hcd, hc, qtd, hc->halt_status);
30668 +       }
30669 +
30670 +       return 1;
30671 +}
30672 +
30673 +/** Handles interrupt for a specific Host Channel */
30674 +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
30675 +{
30676 +       int retval = 0;
30677 +       hcint_data_t hcint;
30678 +       hcintmsk_data_t hcintmsk;
30679 +       dwc_hc_t *hc;
30680 +       dwc_otg_hc_regs_t *hc_regs;
30681 +       dwc_otg_qtd_t *qtd;
30682 +
30683 +       DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
30684 +
30685 +       hc = dwc_otg_hcd->hc_ptr_array[num];
30686 +       hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
30687 +       qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
30688 +
30689 +       hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
30690 +       hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk);
30691 +       DWC_DEBUGPL(DBG_HCDV,
30692 +                   "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
30693 +                   hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
30694 +       hcint.d32 = hcint.d32 & hcintmsk.d32;
30695 +
30696 +       if (!dwc_otg_hcd->core_if->dma_enable) {
30697 +               if (hcint.b.chhltd && hcint.d32 != 0x2) {
30698 +                       hcint.b.chhltd = 0;
30699 +               }
30700 +       }
30701 +
30702 +       if (hcint.b.xfercomp) {
30703 +               retval |=
30704 +                   handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30705 +               /*
30706 +                * If NYET occurred at same time as Xfer Complete, the NYET is
30707 +                * handled by the Xfer Complete interrupt handler. Don't want
30708 +                * to call the NYET interrupt handler in this case.
30709 +                */
30710 +               hcint.b.nyet = 0;
30711 +       }
30712 +       if (hcint.b.chhltd) {
30713 +               retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30714 +       }
30715 +       if (hcint.b.ahberr) {
30716 +               retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30717 +       }
30718 +       if (hcint.b.stall) {
30719 +               retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30720 +       }
30721 +       if (hcint.b.nak) {
30722 +               retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30723 +       }
30724 +       if (hcint.b.ack) {
30725 +               retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30726 +       }
30727 +       if (hcint.b.nyet) {
30728 +               retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30729 +       }
30730 +       if (hcint.b.xacterr) {
30731 +               retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30732 +       }
30733 +       if (hcint.b.bblerr) {
30734 +               retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30735 +       }
30736 +       if (hcint.b.frmovrun) {
30737 +               retval |=
30738 +                   handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30739 +       }
30740 +       if (hcint.b.datatglerr) {
30741 +               retval |=
30742 +                   handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
30743 +       }
30744 +
30745 +       return retval;
30746 +}
30747 +
30748 +#endif                         /* DWC_DEVICE_ONLY */
30749 --- /dev/null
30750 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
30751 @@ -0,0 +1,840 @@
30752 +/* ==========================================================================
30753 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
30754 + * $Revision: #11 $
30755 + * $Date: 2009/04/21 $
30756 + * $Change: 1237476 $
30757 + *
30758 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
30759 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
30760 + * otherwise expressly agreed to in writing between Synopsys and you.
30761 + *
30762 + * The Software IS NOT an item of Licensed Software or Licensed Product under
30763 + * any End User Software License Agreement or Agreement for Licensed Product
30764 + * with Synopsys or any supplement thereto. You are permitted to use and
30765 + * redistribute this Software in source and binary forms, with or without
30766 + * modification, provided that redistributions of source code must retain this
30767 + * notice. You may not view, use, disclose, copy or distribute this file or
30768 + * any information contained herein except pursuant to this license grant from
30769 + * Synopsys. If you do not agree with this notice, including the disclaimer
30770 + * below, then you are not authorized to use the Software.
30771 + *
30772 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
30773 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30774 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30775 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
30776 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30777 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30778 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30779 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30780 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30781 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30782 + * DAMAGE.
30783 + * ========================================================================== */
30784 +#ifndef DWC_DEVICE_ONLY
30785 +
30786 +/**
30787 + * @file
30788 + *
30789 + * This file contains the implementation of the HCD. In Linux, the HCD
30790 + * implements the hc_driver API.
30791 + */
30792 +#include <linux/kernel.h>
30793 +#include <linux/module.h>
30794 +#include <linux/moduleparam.h>
30795 +#include <linux/init.h>
30796 +#include <linux/device.h>
30797 +#include <linux/errno.h>
30798 +#include <linux/list.h>
30799 +#include <linux/interrupt.h>
30800 +#include <linux/string.h>
30801 +#include <linux/dma-mapping.h>
30802 +#include <linux/version.h>
30803 +#include <asm/io.h>
30804 +
30805 +#ifdef LM_INTERFACE
30806 +//#include <asm/arch/regs-irq.h>
30807 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
30808 +#include <asm/arch/lm.h>
30809 +#include <asm/arch/irqs.h>
30810 +#else
30811 +#include <mach/lm.h>
30812 +#include <mach/irqs.h>
30813 +#endif
30814 +#elif defined(PLATFORM_INTERFACE)
30815 +#include <linux/platform_device.h>
30816 +#endif
30817 +
30818 +#include <linux/usb.h>
30819 +#include <linux/usb/hcd.h>
30820 +
30821 +#include "dwc_otg_hcd_if.h"
30822 +#include "dwc_otg_dbg.h"
30823 +#include "dwc_otg_driver.h"
30824 +
30825 +/**
30826 + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
30827 + * qualified with its direction (possible 32 endpoints per device).
30828 + */
30829 +#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
30830 +                                                    ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
30831 +
30832 +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
30833 +
30834 +/** @name Linux HC Driver API Functions */
30835 +/** @{ */
30836 +/* manage i/o requests, device state */
30837 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
30838 +static int urb_enqueue(struct usb_hcd *hcd,
30839 +                      struct usb_host_endpoint *ep,
30840 +                      struct urb *urb, gfp_t mem_flags);
30841 +
30842 +static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
30843 +#else
30844 +static int urb_enqueue(struct usb_hcd *hcd,
30845 +                      struct urb *urb, gfp_t mem_flags);
30846 +
30847 +static int urb_dequeue(struct usb_hcd *hcd,
30848 +                      struct urb *urb, int status);
30849 +#endif
30850 +
30851 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
30852 +
30853 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
30854 +extern int hcd_start(struct usb_hcd *hcd);
30855 +extern void hcd_stop(struct usb_hcd *hcd);
30856 +static int get_frame_number(struct usb_hcd *hcd);
30857 +extern int hub_status_data(struct usb_hcd *hcd, char *buf);
30858 +extern int hub_control(struct usb_hcd *hcd,
30859 +                      u16 typeReq,
30860 +                      u16 wValue, u16 wIndex, char *buf, u16 wLength);
30861 +
30862 +struct wrapper_priv_data {
30863 +       dwc_otg_hcd_t *dwc_otg_hcd;
30864 +};
30865 +
30866 +/** @} */
30867 +
30868 +static struct hc_driver dwc_otg_hc_driver = {
30869 +
30870 +       .description = dwc_otg_hcd_name,
30871 +       .product_desc = "DWC OTG Controller",
30872 +       .hcd_priv_size = sizeof(struct wrapper_priv_data),
30873 +
30874 +       .irq = dwc_otg_hcd_irq,
30875 +
30876 +       .flags = HCD_MEMORY | HCD_USB2,
30877 +
30878 +       //.reset =              
30879 +       .start = hcd_start,
30880 +       //.suspend =            
30881 +       //.resume =             
30882 +       .stop = hcd_stop,
30883 +
30884 +       .urb_enqueue = urb_enqueue,
30885 +       .urb_dequeue = urb_dequeue,
30886 +       .endpoint_disable = endpoint_disable,
30887 +
30888 +       .get_frame_number = get_frame_number,
30889 +
30890 +       .hub_status_data = hub_status_data,
30891 +       .hub_control = hub_control,
30892 +       //.bus_suspend =                
30893 +       //.bus_resume =         
30894 +};
30895 +
30896 +/** Gets the dwc_otg_hcd from a struct usb_hcd */
30897 +static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
30898 +{
30899 +       struct wrapper_priv_data *p;
30900 +       p = (struct wrapper_priv_data *)(hcd->hcd_priv);
30901 +       return p->dwc_otg_hcd;
30902 +}
30903 +
30904 +/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
30905 +static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
30906 +{
30907 +       return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
30908 +}
30909 +
30910 +/** Gets the usb_host_endpoint associated with an URB. */
30911 +inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
30912 +{
30913 +       struct usb_device *dev = urb->dev;
30914 +       int ep_num = usb_pipeendpoint(urb->pipe);
30915 +
30916 +       if (usb_pipein(urb->pipe))
30917 +               return dev->ep_in[ep_num];
30918 +       else
30919 +               return dev->ep_out[ep_num];
30920 +}
30921 +
30922 +static int _disconnect(dwc_otg_hcd_t * hcd)
30923 +{
30924 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
30925 +
30926 +       usb_hcd->self.is_b_host = 0;
30927 +       return 0;
30928 +}
30929 +
30930 +static int _start(dwc_otg_hcd_t * hcd)
30931 +{
30932 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
30933 +
30934 +       usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
30935 +       hcd_start(usb_hcd);
30936 +
30937 +       return 0;
30938 +}
30939 +
30940 +static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
30941 +                    uint32_t * port_addr)
30942 +{
30943 +   struct urb *urb = (struct urb *)urb_handle;
30944 +#if 1 //GRAYG - temporary
30945 +   if (NULL == urb_handle)
30946 +      DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG
30947 +   if (NULL == urb->dev)
30948 +      DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG
30949 +   if (NULL == port_addr)
30950 +      DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG
30951 +#endif
30952 +   if (urb->dev->tt) {
30953 +        if (NULL == urb->dev->tt->hub) {
30954 +                DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n",
30955 +                           __func__); //GRAYG
30956 +                //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG
30957 +                *hub_addr = 0; //GRAYG
30958 +                // we probably shouldn't have a transaction translator if
30959 +                // there's no associated hub?
30960 +        } else
30961 +                *hub_addr = urb->dev->tt->hub->devnum;
30962 +   } else {
30963 +        *hub_addr = 0;
30964 +   }
30965 +   *port_addr = urb->dev->ttport;
30966 +   return 0;
30967 +}
30968 +
30969 +static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
30970 +{
30971 +       struct urb *urb = (struct urb *)urb_handle;
30972 +       return urb->dev->speed;
30973 +}
30974 +
30975 +static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
30976 +{
30977 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
30978 +       return usb_hcd->self.b_hnp_enable;
30979 +}
30980 +
30981 +static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
30982 +                                  struct urb *urb)
30983 +{
30984 +       hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
30985 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
30986 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
30987 +       } else {
30988 +               hcd_to_bus(hcd)->bandwidth_int_reqs++;
30989 +       }
30990 +}
30991 +
30992 +static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
30993 +                              struct urb *urb)
30994 +{
30995 +       hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
30996 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
30997 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
30998 +       } else {
30999 +               hcd_to_bus(hcd)->bandwidth_int_reqs--;
31000 +       }
31001 +}
31002 +
31003 +/**
31004 + * Sets the final status of an URB and returns it to the device driver. Any
31005 + * required cleanup of the URB is performed.
31006 + */
31007 +static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
31008 +                    dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
31009 +{
31010 +       struct urb *urb = (struct urb *)urb_handle;
31011 +#ifdef DEBUG
31012 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
31013 +               DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
31014 +                          __func__, urb, usb_pipedevice(urb->pipe),
31015 +                          usb_pipeendpoint(urb->pipe),
31016 +                          usb_pipein(urb->pipe) ? "IN" : "OUT", status);
31017 +               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
31018 +                       int i;
31019 +                       for (i = 0; i < urb->number_of_packets; i++) {
31020 +                               DWC_PRINTF("  ISO Desc %d status: %d\n",
31021 +                                          i, urb->iso_frame_desc[i].status);
31022 +                       }
31023 +               }
31024 +       }
31025 +#endif
31026 +
31027 +       urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
31028 +       /* Convert status value. */
31029 +       switch (status) {
31030 +       case -DWC_E_PROTOCOL:
31031 +               status = -EPROTO;
31032 +               break;
31033 +       case -DWC_E_IN_PROGRESS:
31034 +               status = -EINPROGRESS;
31035 +               break;
31036 +       case -DWC_E_PIPE:
31037 +               status = -EPIPE;
31038 +               break;
31039 +       case -DWC_E_IO:
31040 +               status = -EIO;
31041 +               break;
31042 +       case -DWC_E_TIMEOUT:
31043 +               status = -ETIMEDOUT;
31044 +               break;
31045 +       case -DWC_E_OVERFLOW:
31046 +               status = -EOVERFLOW;
31047 +               break;
31048 +       default:
31049 +               if (status) {
31050 +                       DWC_PRINTF("Uknown urb status %d\n", status);
31051 +
31052 +               }
31053 +       }
31054 +
31055 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
31056 +               int i;
31057 +
31058 +               urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
31059 +               for (i = 0; i < urb->number_of_packets; ++i) {
31060 +                       urb->iso_frame_desc[i].actual_length =
31061 +                           dwc_otg_hcd_urb_get_iso_desc_actual_length
31062 +                           (dwc_otg_urb, i);
31063 +                       urb->iso_frame_desc[i].status =
31064 +                           dwc_otg_hcd_urb_get_iso_desc_status
31065 +                           (dwc_otg_urb, i);
31066 +               }
31067 +       }
31068 +
31069 +       urb->status = status;
31070 +       urb->hcpriv = NULL;
31071 +       if (!status) {
31072 +               if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
31073 +                   (urb->actual_length < urb->transfer_buffer_length)) {
31074 +                       urb->status = -EREMOTEIO;
31075 +               }
31076 +       }
31077 +
31078 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
31079 +           (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
31080 +               struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
31081 +               if (ep) {
31082 +                       free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
31083 +                                          dwc_otg_hcd_get_ep_bandwidth(hcd,
31084 +                                                                       ep->
31085 +                                                                       hcpriv),
31086 +                                          urb);
31087 +               }
31088 +       }
31089 +
31090 +       dwc_free(dwc_otg_urb);
31091 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
31092 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
31093 +#else
31094 +       usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
31095 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
31096 +#endif
31097 +       return 0;
31098 +}
31099 +
31100 +static struct dwc_otg_hcd_function_ops hcd_fops = {
31101 +       .start = _start,
31102 +       .disconnect = _disconnect,
31103 +       .hub_info = _hub_info,
31104 +       .speed = _speed,
31105 +       .complete = _complete,
31106 +       .get_b_hnp_enable = _get_b_hnp_enable,
31107 +};
31108 +
31109 +/**
31110 + * Initializes the HCD. This function allocates memory for and initializes the
31111 + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
31112 + * USB bus with the core and calls the hc_driver->start() function. It returns
31113 + * a negative error on failure.
31114 + */
31115 +int hcd_init(
31116 +#ifdef LM_INTERFACE
31117 +       struct lm_device *_dev
31118 +#elif  defined(PCI_INTERFACE)
31119 +       struct pci_dev *_dev
31120 +#elif  defined(PLATFORM_INTERFACE)
31121 +       struct platform_device *_dev
31122 +#endif
31123 +       )
31124 +{
31125 +       struct usb_hcd *hcd = NULL;
31126 +       dwc_otg_hcd_t *dwc_otg_hcd = NULL;
31127 +#ifdef LM_INTERFACE
31128 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
31129 +#elif  defined(PCI_INTERFACE)
31130 +       dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
31131 +#elif  defined(PLATFORM_INTERFACE)
31132 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
31133 +#endif
31134 +
31135 +       int retval = 0;
31136 +        u64 dmamask;
31137 +
31138 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
31139 +
31140 +       /* Set device flags indicating whether the HCD supports DMA. */
31141 +       if (dwc_otg_is_dma_enable(otg_dev->core_if))
31142 +                dmamask = DMA_BIT_MASK(32);
31143 +        else
31144 +                dmamask = 0;
31145 +              
31146 +#if    defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
31147 +        dma_set_mask(&_dev->dev, dmamask);
31148 +        dma_set_coherent_mask(&_dev->dev, dmamask);
31149 +#elif  defined(PCI_INTERFACE)
31150 +        pci_set_dma_mask(_dev, dmamask);
31151 +        pci_set_consistent_dma_mask(_dev, dmamask);
31152 +#endif
31153 +
31154 +       /*
31155 +        * Allocate memory for the base HCD plus the DWC OTG HCD.
31156 +        * Initialize the base HCD.
31157 +        */
31158 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev,
31159 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
31160 +                             _dev->dev.bus_id);
31161 +#else
31162 +                             dev_name(&_dev->dev));
31163 +#endif
31164 +       if (!hcd) {
31165 +               retval = -ENOMEM;
31166 +               goto error1;
31167 +       }
31168 +
31169 +       hcd->regs = otg_dev->base;
31170 +
31171 +       /* Initialize the DWC OTG HCD. */
31172 +       dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
31173 +       if (!dwc_otg_hcd) {
31174 +               goto error2;
31175 +       }
31176 +       ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
31177 +           dwc_otg_hcd;
31178 +       otg_dev->hcd = dwc_otg_hcd;
31179 +
31180 +       if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
31181 +               goto error2;
31182 +       }
31183 +
31184 +       hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
31185 +
31186 +       /*
31187 +        * Finish generic HCD initialization and start the HCD. This function
31188 +        * allocates the DMA buffer pool, registers the USB bus, requests the
31189 +        * IRQ line, and calls hcd_start method.
31190 +        */
31191 +#ifdef PLATFORM_INTERFACE
31192 +       retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED);
31193 +#else
31194 +       retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED);
31195 +#endif
31196 +       if (retval < 0) {
31197 +               goto error2;
31198 +       }
31199 +
31200 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
31201 +       return 0;
31202 +
31203 +      error2:
31204 +       usb_put_hcd(hcd);
31205 +      error1:
31206 +       return retval;
31207 +}
31208 +
31209 +/**
31210 + * Removes the HCD.
31211 + * Frees memory and resources associated with the HCD and deregisters the bus.
31212 + */
31213 +void hcd_remove(
31214 +#ifdef LM_INTERFACE
31215 +       struct lm_device *_dev
31216 +#elif  defined(PCI_INTERFACE)
31217 +       struct pci_dev *_dev
31218 +#elif  defined(PLATFORM_INTERFACE)
31219 +       struct platform_device *_dev
31220 +#endif
31221 +       )
31222 +{
31223 +#ifdef LM_INTERFACE
31224 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
31225 +#elif  defined(PCI_INTERFACE)
31226 +       dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
31227 +#elif  defined(PLATFORM_INTERFACE)
31228 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
31229 +#endif
31230 +
31231 +       dwc_otg_hcd_t *dwc_otg_hcd;
31232 +       struct usb_hcd *hcd;
31233 +
31234 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev);
31235 +
31236 +       if (!otg_dev) {
31237 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
31238 +               return;
31239 +       }
31240 +
31241 +       dwc_otg_hcd = otg_dev->hcd;
31242 +
31243 +       if (!dwc_otg_hcd) {
31244 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
31245 +               return;
31246 +       }
31247 +
31248 +       hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
31249 +
31250 +       if (!hcd) {
31251 +               DWC_DEBUGPL(DBG_ANY,
31252 +                           "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
31253 +                           __func__);
31254 +               return;
31255 +       }
31256 +       usb_remove_hcd(hcd);
31257 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
31258 +       dwc_otg_hcd_remove(dwc_otg_hcd);
31259 +       usb_put_hcd(hcd);
31260 +}
31261 +
31262 +/* =========================================================================
31263 + *  Linux HC Driver Functions
31264 + * ========================================================================= */
31265 +
31266 +/** Initializes the DWC_otg controller and its root hub and prepares it for host
31267 + * mode operation. Activates the root port. Returns 0 on success and a negative
31268 + * error code on failure. */
31269 +int hcd_start(struct usb_hcd *hcd)
31270 +{
31271 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
31272 +       struct usb_bus *bus;
31273 +
31274 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
31275 +       bus = hcd_to_bus(hcd);
31276 +
31277 +       hcd->state = HC_STATE_RUNNING;
31278 +       if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
31279 +               return 0;
31280 +       }
31281 +
31282 +       /* Initialize and connect root hub if one is not already attached */
31283 +       if (bus->root_hub) {
31284 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
31285 +               /* Inform the HUB driver to resume. */
31286 +               usb_hcd_resume_root_hub(hcd);
31287 +       }
31288 +
31289 +       return 0;
31290 +}
31291 +
31292 +/**
31293 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
31294 + * stopped.
31295 + */
31296 +void hcd_stop(struct usb_hcd *hcd)
31297 +{
31298 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
31299 +
31300 +       dwc_otg_hcd_stop(dwc_otg_hcd);
31301 +}
31302 +
31303 +/** Returns the current frame number. */
31304 +static int get_frame_number(struct usb_hcd *hcd)
31305 +{
31306 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
31307 +
31308 +       return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
31309 +}
31310 +
31311 +#ifdef DEBUG
31312 +static void dump_urb_info(struct urb *urb, char *fn_name)
31313 +{
31314 +       DWC_PRINTF("%s, urb %p\n", fn_name, urb);
31315 +       DWC_PRINTF("  Device address: %d\n", usb_pipedevice(urb->pipe));
31316 +       DWC_PRINTF("  Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
31317 +                  (usb_pipein(urb->pipe) ? "IN" : "OUT"));
31318 +       DWC_PRINTF("  Endpoint type: %s\n", ( {
31319 +                                            char *pipetype;
31320 +                                            switch (usb_pipetype(urb->pipe)) {
31321 +case PIPE_CONTROL:
31322 +pipetype = "CONTROL"; break; case PIPE_BULK:
31323 +pipetype = "BULK"; break; case PIPE_INTERRUPT:
31324 +pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
31325 +pipetype = "ISOCHRONOUS"; break; default:
31326 +                                            pipetype = "UNKNOWN"; break;};
31327 +                                            pipetype;}
31328 +                  )) ;
31329 +       DWC_PRINTF("  Speed: %s\n", ( {
31330 +                                    char *speed; switch (urb->dev->speed) {
31331 +case USB_SPEED_HIGH:
31332 +speed = "HIGH"; break; case USB_SPEED_FULL:
31333 +speed = "FULL"; break; case USB_SPEED_LOW:
31334 +speed = "LOW"; break; default:
31335 +                                    speed = "UNKNOWN"; break;};
31336 +                                    speed;}
31337 +                  )) ;
31338 +       DWC_PRINTF("  Max packet size: %d\n",
31339 +                  usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
31340 +       DWC_PRINTF("  Data buffer length: %d\n", urb->transfer_buffer_length);
31341 +       DWC_PRINTF("  Transfer buffer: %p, Transfer DMA: %p\n",
31342 +                  urb->transfer_buffer, (void *)urb->transfer_dma);
31343 +       DWC_PRINTF("  Setup buffer: %p, Setup DMA: %p\n",
31344 +                  urb->setup_packet, (void *)urb->setup_dma);
31345 +       DWC_PRINTF("  Interval: %d\n", urb->interval);
31346 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
31347 +               int i;
31348 +               for (i = 0; i < urb->number_of_packets; i++) {
31349 +                       DWC_PRINTF("  ISO Desc %d:\n", i);
31350 +                       DWC_PRINTF("    offset: %d, length %d\n",
31351 +                                  urb->iso_frame_desc[i].offset,
31352 +                                  urb->iso_frame_desc[i].length);
31353 +               }
31354 +       }
31355 +}
31356 +
31357 +#endif
31358 +
31359 +/** Starts processing a USB transfer request specified by a USB Request Block
31360 + * (URB). mem_flags indicates the type of memory allocation to use while
31361 + * processing this URB. */
31362 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
31363 +static int urb_enqueue(struct usb_hcd *hcd,
31364 +                      struct usb_host_endpoint *ep,
31365 +                      struct urb *urb, gfp_t mem_flags)
31366 +{
31367 +#else
31368 +static int urb_enqueue(struct usb_hcd *hcd,
31369 +                      struct urb *urb,
31370 +                       gfp_t mem_flags)
31371 +{
31372 +        struct usb_host_endpoint *ep = urb->ep;
31373 +#endif
31374 +        void **ref_ep_hcpriv = &ep->hcpriv;
31375 +       int retval = 0;
31376 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
31377 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
31378 +       int i;
31379 +       int alloc_bandwidth = 0;
31380 +       uint8_t ep_type = 0;
31381 +       uint32_t flags = 0;
31382 +       void *buf;
31383 +
31384 +#ifdef DEBUG
31385 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
31386 +               dump_urb_info(urb, "urb_enqueue");
31387 +       }
31388 +#endif
31389 +
31390 +       if (!urb->transfer_buffer && urb->transfer_buffer_length)
31391 +               return -EINVAL;
31392 +
31393 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
31394 +           || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
31395 +               if (!dwc_otg_hcd_is_bandwidth_allocated
31396 +                   (dwc_otg_hcd, ref_ep_hcpriv)) {
31397 +                       alloc_bandwidth = 1;
31398 +               }
31399 +       }
31400 +
31401 +       switch (usb_pipetype(urb->pipe)) {
31402 +       case PIPE_CONTROL:
31403 +               ep_type = USB_ENDPOINT_XFER_CONTROL;
31404 +               break;
31405 +       case PIPE_ISOCHRONOUS:
31406 +               ep_type = USB_ENDPOINT_XFER_ISOC;
31407 +               break;
31408 +       case PIPE_BULK:
31409 +               ep_type = USB_ENDPOINT_XFER_BULK;
31410 +               break;
31411 +       case PIPE_INTERRUPT:
31412 +               ep_type = USB_ENDPOINT_XFER_INT;
31413 +               break;
31414 +       default:
31415 +               DWC_WARN("Wrong ep type\n");
31416 +       }
31417 +
31418 +       dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
31419 +                                           urb->number_of_packets,
31420 +                                           mem_flags == GFP_ATOMIC ? 1 : 0);
31421 +
31422 +        urb->hcpriv = dwc_otg_urb;
31423 +        
31424 +       dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
31425 +                                    usb_pipeendpoint(urb->pipe), ep_type,
31426 +                                    usb_pipein(urb->pipe),
31427 +                                    usb_maxpacket(urb->dev, urb->pipe,
31428 +                                                  !(usb_pipein(urb->pipe))));
31429 +
31430 +       buf = urb->transfer_buffer;
31431 +       if (hcd->self.uses_dma) {
31432 +               /*
31433 +                * Calculate virtual address from physical address,
31434 +                * because some class driver may not fill transfer_buffer.
31435 +                * In Buffer DMA mode virual address is used,
31436 +                * when handling non DWORD aligned buffers.
31437 +                */
31438 +               //buf = phys_to_virt(urb->transfer_dma);
31439 +                // DMA addresses are bus addresses not physical addresses!
31440 +                buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma);
31441 +       }
31442 +       
31443 +       if (!(urb->transfer_flags & URB_NO_INTERRUPT))
31444 +               flags |= URB_GIVEBACK_ASAP;
31445 +       if (urb->transfer_flags & URB_ZERO_PACKET)
31446 +               flags |= URB_SEND_ZERO_PACKET;
31447 +
31448 +       dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
31449 +                                  urb->transfer_dma,
31450 +                                  urb->transfer_buffer_length,
31451 +                                  urb->setup_packet, 
31452 +                                  urb->setup_dma,
31453 +                                  flags,
31454 +                                  urb->interval);
31455 +
31456 +       for (i = 0; i < urb->number_of_packets; ++i) {
31457 +               dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
31458 +                                                   urb->iso_frame_desc[i].
31459 +                                                   offset,
31460 +                                                   urb->iso_frame_desc[i].
31461 +                                                   length);
31462 +       }
31463 +
31464 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
31465 +       retval = usb_hcd_link_urb_to_ep(hcd, urb);
31466 +       if (0 == retval) 
31467 +#endif
31468 +        {
31469 +                retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
31470 +                                                 /*(dwc_otg_qh_t **)*/
31471 +                                                 ref_ep_hcpriv);
31472 +                if (0 == retval) {
31473 +                        if (alloc_bandwidth) {
31474 +                                allocate_bus_bandwidth(hcd,
31475 +                                        dwc_otg_hcd_get_ep_bandwidth(
31476 +                                                dwc_otg_hcd, *ref_ep_hcpriv),
31477 +                                                       urb);
31478 +                        }
31479 +                } else {
31480 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
31481 +                        usb_hcd_unlink_urb_from_ep(hcd, urb);
31482 +#endif
31483 +                        if (retval == -DWC_E_NO_DEVICE) {
31484 +                                retval = -ENODEV;
31485 +                        }
31486 +                }
31487 +        }
31488 +       return retval;
31489 +}
31490 +
31491 +/** Aborts/cancels a USB transfer request. Always returns 0 to indicate
31492 + * success.  */
31493 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
31494 +static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
31495 +#else
31496 +static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
31497 +#endif
31498 +{
31499 +       dwc_otg_hcd_t *dwc_otg_hcd;
31500 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
31501 +
31502 +       dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
31503 +
31504 +#ifdef DEBUG
31505 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
31506 +               dump_urb_info(urb, "urb_dequeue");
31507 +       }
31508 +#endif
31509 +       dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv);
31510 +
31511 +       dwc_free(urb->hcpriv);
31512 +       urb->hcpriv = NULL;
31513 +
31514 +       /* Higher layer software sets URB status. */
31515 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
31516 +       usb_hcd_giveback_urb(hcd, urb);
31517 +#else
31518 +       usb_hcd_unlink_urb_from_ep(hcd, urb);
31519 +       usb_hcd_giveback_urb(hcd, urb, status);
31520 +#endif
31521 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
31522 +               DWC_PRINTF("Called usb_hcd_giveback_urb()\n");
31523 +               DWC_PRINTF("  urb->status = %d\n", urb->status);
31524 +       }
31525 +
31526 +       return 0;
31527 +}
31528 +
31529 +/* Frees resources in the DWC_otg controller related to a given endpoint. Also
31530 + * clears state in the HCD related to the endpoint. Any URBs for the endpoint
31531 + * must already be dequeued. */
31532 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
31533 +{
31534 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
31535 +
31536 +       DWC_DEBUGPL(DBG_HCD,
31537 +                   "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
31538 +                   "endpoint=%d\n", ep->desc.bEndpointAddress,
31539 +                   dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
31540 +       dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
31541 +       ep->hcpriv = NULL;
31542 +}
31543 +
31544 +/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
31545 + * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
31546 + * interrupt.
31547 + *
31548 + * This function is called by the USB core when an interrupt occurs */
31549 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
31550 +{
31551 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
31552 +       int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
31553 +       if (retval != 0) {
31554 +               S3C2410X_CLEAR_EINTPEND();
31555 +       }
31556 +       return IRQ_RETVAL(retval);
31557 +}
31558 +
31559 +/** Creates Status Change bitmap for the root hub and root port. The bitmap is
31560 + * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
31561 + * is the status change indicator for the single root port. Returns 1 if either
31562 + * change indicator is 1, otherwise returns 0. */
31563 +int hub_status_data(struct usb_hcd *hcd, char *buf)
31564 +{
31565 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
31566 +
31567 +       buf[0] = 0;
31568 +       buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
31569 +
31570 +       return (buf[0] != 0);
31571 +}
31572 +
31573 +/** Handles hub class-specific requests. */
31574 +int hub_control(struct usb_hcd *hcd,
31575 +               u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
31576 +{
31577 +       int retval;
31578 +
31579 +       retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
31580 +                                        typeReq, wValue, wIndex, buf, wLength);
31581 +
31582 +       switch (retval) {
31583 +       case -DWC_E_INVALID:
31584 +               retval = -EINVAL;
31585 +               break;
31586 +       }
31587 +
31588 +       return retval;
31589 +}
31590 +
31591 +#endif                         /* DWC_DEVICE_ONLY */
31592 --- /dev/null
31593 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
31594 @@ -0,0 +1,732 @@
31595 +/* ==========================================================================
31596 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
31597 + * $Revision: #39 $
31598 + * $Date: 2009/04/21 $
31599 + * $Change: 1237477 $
31600 + *
31601 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31602 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31603 + * otherwise expressly agreed to in writing between Synopsys and you.
31604 + * 
31605 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31606 + * any End User Software License Agreement or Agreement for Licensed Product
31607 + * with Synopsys or any supplement thereto. You are permitted to use and
31608 + * redistribute this Software in source and binary forms, with or without
31609 + * modification, provided that redistributions of source code must retain this
31610 + * notice. You may not view, use, disclose, copy or distribute this file or
31611 + * any information contained herein except pursuant to this license grant from
31612 + * Synopsys. If you do not agree with this notice, including the disclaimer
31613 + * below, then you are not authorized to use the Software.
31614 + * 
31615 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31616 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31617 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31618 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31619 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31620 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31621 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31622 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31623 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31624 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31625 + * DAMAGE.
31626 + * ========================================================================== */
31627 +#ifndef DWC_DEVICE_ONLY
31628 +
31629 +/**
31630 + * @file
31631 + *
31632 + * This file contains the functions to manage Queue Heads and Queue
31633 + * Transfer Descriptors.
31634 + */
31635 +
31636 +#include "dwc_otg_hcd.h"
31637 +#include "dwc_otg_regs.h"
31638 +
31639 +/** 
31640 + * Free each QTD in the QH's QTD-list then free the QH.  QH should already be
31641 + * removed from a list.  QTD list should already be empty if called from URB
31642 + * Dequeue.
31643 + *
31644 + * @param hcd HCD instance.
31645 + * @param qh The QH to free.
31646 + */
31647 +void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
31648 +{
31649 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
31650 +       uint64_t flags;
31651 +
31652 +       /* Free each QTD in the QTD list */
31653 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
31654 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
31655 +               DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
31656 +               dwc_otg_hcd_qtd_free(qtd);
31657 +       }
31658 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
31659 +
31660 +       if (hcd->core_if->dma_desc_enable) {
31661 +               dwc_otg_hcd_qh_free_ddma(hcd, qh);
31662 +       }
31663 +       else if (qh->dw_align_buf) {
31664 +               uint32_t buf_size;
31665 +               if(qh->ep_type == UE_ISOCHRONOUS) {
31666 +                       buf_size = 4096;
31667 +               } else {
31668 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
31669 +               }
31670 +               dwc_dma_free(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma);
31671 +       }
31672 +       
31673 +       
31674 +       
31675 +       dwc_free(qh);
31676 +       return;
31677 +}
31678 +
31679 +#define BitStuffTime(bytecount)  ((8 * 7* bytecount) / 6)
31680 +#define HS_HOST_DELAY          5       /* nanoseconds */
31681 +#define FS_LS_HOST_DELAY       1000    /* nanoseconds */
31682 +#define HUB_LS_SETUP           333     /* nanoseconds */
31683 +#define NS_TO_US(ns)           ((ns + 500) / 1000)
31684 +                               /* convert & round nanoseconds to microseconds */
31685 +
31686 +static uint32_t calc_bus_time(int speed, int is_in, int is_isoc,
31687 +                                         int bytecount)
31688 +{
31689 +       unsigned long retval;
31690 +
31691 +       switch (speed) {
31692 +       case USB_SPEED_HIGH:
31693 +               if (is_isoc) {
31694 +                       retval =
31695 +                           ((38 * 8 * 2083) +
31696 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
31697 +                           HS_HOST_DELAY;
31698 +               } else {
31699 +                       retval =
31700 +                           ((55 * 8 * 2083) +
31701 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
31702 +                           HS_HOST_DELAY;
31703 +               }
31704 +               break;
31705 +       case USB_SPEED_FULL:
31706 +               if (is_isoc) {
31707 +                       retval =
31708 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
31709 +                       if (is_in) {
31710 +                               retval = 7268 + FS_LS_HOST_DELAY + retval;
31711 +                       } else {
31712 +                               retval = 6265 + FS_LS_HOST_DELAY + retval;
31713 +                       }
31714 +               } else {
31715 +                       retval =
31716 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
31717 +                       retval = 9107 + FS_LS_HOST_DELAY + retval;
31718 +               }
31719 +               break;
31720 +       case USB_SPEED_LOW:
31721 +               if (is_in) {
31722 +                       retval =
31723 +                           (67667 * (31 + 10 * BitStuffTime(bytecount))) /
31724 +                           1000;
31725 +                       retval =
31726 +                           64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
31727 +                           retval;
31728 +               } else {
31729 +                       retval =
31730 +                           (66700 * (31 + 10 * BitStuffTime(bytecount))) /
31731 +                           1000;
31732 +                       retval =
31733 +                           64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
31734 +                           retval;
31735 +               }
31736 +               break;
31737 +       default:
31738 +               DWC_WARN("Unknown device speed\n");
31739 +               retval = -1;
31740 +       }
31741 +       
31742 +       return NS_TO_US(retval);
31743 +}
31744 +
31745 +/** 
31746 + * Initializes a QH structure.
31747 + *
31748 + * @param hcd The HCD state structure for the DWC OTG controller.
31749 + * @param qh  The QH to init.
31750 + * @param urb Holds the information about the device/endpoint that we need
31751 + *           to initialize the QH. 
31752 + */
31753 +#define SCHEDULE_SLOP 10
31754 +void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
31755 +                        dwc_otg_hcd_urb_t * urb)
31756 +{
31757 +       char *speed, *type;
31758 +       int dev_speed;
31759 +       uint32_t hub_addr, hub_port;
31760 +
31761 +       dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
31762 +       
31763 +       /* Initialize QH */
31764 +       qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
31765 +
31766 +       qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
31767 +
31768 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
31769 +       qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info);
31770 +       DWC_CIRCLEQ_INIT(&qh->qtd_list);
31771 +       DWC_LIST_INIT(&qh->qh_list_entry);
31772 +       qh->channel = NULL;
31773 +
31774 +       /* FS/LS Enpoint on HS Hub 
31775 +        * NOT virtual root hub */
31776 +       dev_speed = hcd->fops->speed(hcd, urb->priv);
31777 +       hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port);
31778 +       qh->do_split = 0;
31779 +       if (((dev_speed == USB_SPEED_LOW) ||
31780 +            (dev_speed == USB_SPEED_FULL)) &&
31781 +           (hub_addr != 0 && hub_addr != 1)) {
31782 +               
31783 +               DWC_DEBUGPL(DBG_HCD,
31784 +                           "QH init: EP %d: TT found at hub addr %d, for port %d\n",
31785 +                           dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
31786 +                           hub_port);
31787 +               
31788 +               qh->do_split = 1;
31789 +       }
31790 +
31791 +       if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
31792 +               /* Compute scheduling parameters once and save them. */
31793 +               hprt0_data_t hprt;
31794 +
31795 +               /** @todo Account for split transfers in the bus time. */
31796 +               int bytecount =
31797 +                   dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);
31798 +
31799 +               qh->usecs = calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed),
31800 +                                         qh->ep_is_in,
31801 +                                         (qh->ep_type == UE_ISOCHRONOUS),
31802 +                                         bytecount);
31803 +               /* Start in a slightly future (micro)frame. */
31804 +               qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
31805 +                                                   SCHEDULE_SLOP);
31806 +               qh->interval = urb->interval;
31807 +               
31808 +#if 0
31809 +               /* Increase interrupt polling rate for debugging. */
31810 +               if (qh->ep_type == UE_INTERRUPT) {
31811 +                       qh->interval = 8;
31812 +               }
31813 +#endif
31814 +               hprt.d32 = dwc_read_reg32(hcd->core_if->host_if->hprt0);
31815 +               if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&
31816 +                   ((dev_speed == USB_SPEED_LOW) ||
31817 +                    (dev_speed == USB_SPEED_FULL))) {
31818 +                       qh->interval *= 8;
31819 +                       qh->sched_frame |= 0x7;
31820 +                       qh->start_split_frame = qh->sched_frame;
31821 +               }
31822 +
31823 +       }
31824 +
31825 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
31826 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - qh = %p\n", qh);
31827 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Device Address = %d\n",
31828 +                   dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
31829 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Endpoint %d, %s\n",
31830 +                   dwc_otg_hcd_get_ep_num(&urb->pipe_info),
31831 +                   dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
31832 +       switch (dev_speed) {
31833 +       case USB_SPEED_LOW:
31834 +               qh->dev_speed = DWC_OTG_EP_SPEED_LOW;
31835 +               speed = "low";
31836 +               break;
31837 +       case USB_SPEED_FULL:
31838 +               qh->dev_speed = DWC_OTG_EP_SPEED_FULL;
31839 +               speed = "full";
31840 +               break;
31841 +       case USB_SPEED_HIGH:
31842 +               qh->dev_speed = DWC_OTG_EP_SPEED_HIGH;
31843 +               speed = "high";
31844 +               break;
31845 +       default:
31846 +               speed = "?";
31847 +               break;
31848 +       }
31849 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Speed = %s\n", speed);
31850 +
31851 +       switch (qh->ep_type) {
31852 +       case UE_ISOCHRONOUS:
31853 +               type = "isochronous";
31854 +               break;
31855 +       case UE_INTERRUPT:
31856 +               type = "interrupt";
31857 +               break;
31858 +       case UE_CONTROL:
31859 +               type = "control";
31860 +               break;
31861 +       case UE_BULK:
31862 +               type = "bulk";
31863 +               break;
31864 +       default:
31865 +               type = "?";
31866 +               break;
31867 +       }
31868 +       
31869 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Type = %s\n", type);
31870 +
31871 +#ifdef DEBUG
31872 +       if (qh->ep_type == UE_INTERRUPT) {
31873 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
31874 +                           qh->usecs);
31875 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
31876 +                           qh->interval);
31877 +       }
31878 +#endif
31879 +
31880 +}
31881 +
31882 +/**
31883 + * This function allocates and initializes a QH.
31884 + *
31885 + * @param hcd The HCD state structure for the DWC OTG controller.
31886 + * @param urb Holds the information about the device/endpoint that we need
31887 + *           to initialize the QH.
31888 + *
31889 + * @return Returns pointer to the newly allocated QH, or NULL on error. */
31890 +dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
31891 +                                   dwc_otg_hcd_urb_t * urb)
31892 +{
31893 +       dwc_otg_qh_t *qh;
31894 +
31895 +       /* Allocate memory */
31896 +       /** @todo add memflags argument */
31897 +       qh = dwc_otg_hcd_qh_alloc();
31898 +       if (qh == NULL) {
31899 +               return NULL;
31900 +       }
31901 +
31902 +       qh_init(hcd, qh, urb);
31903 +       
31904 +       if (hcd->core_if->dma_desc_enable && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) {
31905 +               dwc_otg_hcd_qh_free(hcd, qh);   
31906 +               return NULL;
31907 +       }
31908 +       
31909 +       return qh;
31910 +}
31911 +
31912 +/**
31913 + * Checks that a channel is available for a periodic transfer.
31914 + *
31915 + * @return 0 if successful, negative error code otherise.
31916 + */
31917 +static int periodic_channel_available(dwc_otg_hcd_t * hcd)
31918 +{
31919 +       /*
31920 +        * Currently assuming that there is a dedicated host channnel for each
31921 +        * periodic transaction plus at least one host channel for
31922 +        * non-periodic transactions.
31923 +        */
31924 +       int status;
31925 +       int num_channels;
31926 +
31927 +       num_channels = hcd->core_if->core_params->host_channels;
31928 +       if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) &&
31929 +           (hcd->periodic_channels < num_channels - 1)) {
31930 +               status = 0;
31931 +       } else {
31932 +               DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
31933 +                       __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels);    //NOTICE
31934 +               status = -DWC_E_NO_SPACE;
31935 +       }
31936 +
31937 +       return status;
31938 +}
31939 +
31940 +/**
31941 + * Checks that there is sufficient bandwidth for the specified QH in the
31942 + * periodic schedule. For simplicity, this calculation assumes that all the
31943 + * transfers in the periodic schedule may occur in the same (micro)frame.
31944 + *
31945 + * @param hcd The HCD state structure for the DWC OTG controller.
31946 + * @param qh QH containing periodic bandwidth required.
31947 + *
31948 + * @return 0 if successful, negative error code otherwise.
31949 + */
31950 +static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
31951 +{
31952 +       int status;
31953 +       int16_t max_claimed_usecs;
31954 +
31955 +       status = 0;
31956 +
31957 +       if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) {
31958 +               /*
31959 +                * High speed mode.
31960 +                * Max periodic usecs is 80% x 125 usec = 100 usec.
31961 +                */
31962 +
31963 +               max_claimed_usecs = 100 - qh->usecs;
31964 +       } else {
31965 +               /*
31966 +                * Full speed mode.
31967 +                * Max periodic usecs is 90% x 1000 usec = 900 usec.
31968 +                */
31969 +               max_claimed_usecs = 900 - qh->usecs;
31970 +       }
31971 +
31972 +       if (hcd->periodic_usecs > max_claimed_usecs) {
31973 +               DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs);        //NOTICE
31974 +               status = -DWC_E_NO_SPACE;
31975 +       }
31976 +
31977 +       return status;
31978 +}
31979 +
31980 +/**
31981 + * Checks that the max transfer size allowed in a host channel is large enough
31982 + * to handle the maximum data transfer in a single (micro)frame for a periodic
31983 + * transfer.
31984 + *
31985 + * @param hcd The HCD state structure for the DWC OTG controller.
31986 + * @param qh QH for a periodic endpoint.
31987 + *
31988 + * @return 0 if successful, negative error code otherwise.
31989 + */
31990 +static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
31991 +{
31992 +       int status;
31993 +       uint32_t max_xfer_size;
31994 +       uint32_t max_channel_xfer_size;
31995 +
31996 +       status = 0;
31997 +
31998 +       max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
31999 +       max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
32000 +
32001 +       if (max_xfer_size > max_channel_xfer_size) {
32002 +               DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n",
32003 +                               __func__, max_xfer_size, max_channel_xfer_size);        //NOTICE
32004 +               status = -DWC_E_NO_SPACE;
32005 +       }
32006 +
32007 +       return status;
32008 +}
32009 +
32010 +/**
32011 + * Schedules an interrupt or isochronous transfer in the periodic schedule.
32012 + *
32013 + * @param hcd The HCD state structure for the DWC OTG controller.
32014 + * @param qh QH for the periodic transfer. The QH should already contain the
32015 + * scheduling information.
32016 + *
32017 + * @return 0 if successful, negative error code otherwise.
32018 + */
32019 +static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
32020 +{
32021 +       int status = 0;
32022 +
32023 +       status = periodic_channel_available(hcd);
32024 +       if (status) {
32025 +               DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__);        //NOTICE
32026 +               return status;
32027 +       }
32028 +
32029 +       status = check_periodic_bandwidth(hcd, qh);
32030 +       if (status) {
32031 +               DWC_INFO("%s: Insufficient periodic bandwidth for " "periodic transfer.\n", __func__);  //NOTICE
32032 +               return status;
32033 +       }
32034 +
32035 +       status = check_max_xfer_size(hcd, qh);
32036 +       if (status) {
32037 +               DWC_INFO("%s: Channel max transfer size too small " "for periodic transfer.\n", __func__);      //NOTICE
32038 +               return status;
32039 +       }
32040 +
32041 +       if (hcd->core_if->dma_desc_enable) {
32042 +               /* Don't rely on SOF and start in ready schedule */
32043 +               DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
32044 +       }
32045 +       else {
32046 +       /* Always start in the inactive schedule. */
32047 +       DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
32048 +       }
32049 +
32050 +       /* Reserve the periodic channel. */
32051 +       hcd->periodic_channels++;
32052 +
32053 +       /* Update claimed usecs per (micro)frame. */
32054 +       hcd->periodic_usecs += qh->usecs;
32055 +
32056 +       return status;
32057 +}
32058 +
32059 +/**
32060 + * This function adds a QH to either the non periodic or periodic schedule if
32061 + * it is not already in the schedule. If the QH is already in the schedule, no
32062 + * action is taken.
32063 + *
32064 + * @return 0 if successful, negative error code otherwise.
32065 + */
32066 +int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
32067 +{
32068 +       int status = 0;
32069 +       uint64_t flags;
32070 +
32071 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
32072 +
32073 +       if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
32074 +               /* QH already in a schedule. */
32075 +               goto done;
32076 +       }
32077 +
32078 +       /* Add the new QH to the appropriate schedule */
32079 +       if (dwc_qh_is_non_per(qh)) {
32080 +               /* Always start in the inactive schedule. */
32081 +               DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
32082 +                                    &qh->qh_list_entry);
32083 +       } else {
32084 +               status = schedule_periodic(hcd, qh);
32085 +       }
32086 +
32087 +      done:
32088 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
32089 +
32090 +       return status;
32091 +}
32092 +
32093 +/**
32094 + * Removes an interrupt or isochronous transfer from the periodic schedule.
32095 + *
32096 + * @param hcd The HCD state structure for the DWC OTG controller.
32097 + * @param qh QH for the periodic transfer.
32098 + */
32099 +static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
32100 +{
32101 +       DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
32102 +
32103 +       /* Release the periodic channel reservation. */
32104 +       hcd->periodic_channels--;
32105 +
32106 +       /* Update claimed usecs per (micro)frame. */
32107 +       hcd->periodic_usecs -= qh->usecs;
32108 +}
32109 +
32110 +/** 
32111 + * Removes a QH from either the non-periodic or periodic schedule.  Memory is
32112 + * not freed.
32113 + *
32114 + * @param hcd The HCD state structure.
32115 + * @param qh QH to remove from schedule. */
32116 +void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
32117 +{
32118 +       uint64_t flags;
32119 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
32120 +
32121 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
32122 +               /* QH is not in a schedule. */
32123 +               goto done;
32124 +       }
32125 +
32126 +       if (dwc_qh_is_non_per(qh)) {
32127 +               if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {
32128 +                       hcd->non_periodic_qh_ptr =
32129 +                           hcd->non_periodic_qh_ptr->next;
32130 +               }
32131 +               DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
32132 +       } else {
32133 +               deschedule_periodic(hcd, qh);
32134 +       }
32135 +
32136 +      done:
32137 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
32138 +}
32139 +
32140 +/**
32141 + * Deactivates a QH. For non-periodic QHs, removes the QH from the active
32142 + * non-periodic schedule. The QH is added to the inactive non-periodic
32143 + * schedule if any QTDs are still attached to the QH.
32144 + *
32145 + * For periodic QHs, the QH is removed from the periodic queued schedule. If
32146 + * there are any QTDs still attached to the QH, the QH is added to either the
32147 + * periodic inactive schedule or the periodic ready schedule and its next
32148 + * scheduled frame is calculated. The QH is placed in the ready schedule if
32149 + * the scheduled frame has been reached already. Otherwise it's placed in the
32150 + * inactive schedule. If there are no QTDs attached to the QH, the QH is
32151 + * completely removed from the periodic schedule.
32152 + */
32153 +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
32154 +                              int sched_next_periodic_split)
32155 +{
32156 +       uint64_t flags;
32157 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
32158 +
32159 +       if (dwc_qh_is_non_per(qh)) {
32160 +               dwc_otg_hcd_qh_remove(hcd, qh);
32161 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
32162 +                       /* Add back to inactive non-periodic schedule. */
32163 +                       dwc_otg_hcd_qh_add(hcd, qh);
32164 +               }
32165 +       } else {
32166 +               uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
32167 +
32168 +               if (qh->do_split) {
32169 +                       /* Schedule the next continuing periodic split transfer */
32170 +                       if (sched_next_periodic_split) {
32171 +
32172 +                               qh->sched_frame = frame_number;
32173 +                               if (dwc_frame_num_le(frame_number,
32174 +                                                    dwc_frame_num_inc(qh->
32175 +                                                                      start_split_frame,
32176 +                                                                      1))) {
32177 +                                       /*
32178 +                                        * Allow one frame to elapse after start
32179 +                                        * split microframe before scheduling
32180 +                                        * complete split, but DONT if we are
32181 +                                        * doing the next start split in the
32182 +                                        * same frame for an ISOC out.
32183 +                                        */
32184 +                                       if ((qh->ep_type != UE_ISOCHRONOUS) ||
32185 +                                           (qh->ep_is_in != 0)) {
32186 +                                               qh->sched_frame =
32187 +                                                   dwc_frame_num_inc(qh->sched_frame, 1);
32188 +                                       }
32189 +                               }
32190 +                       } else {
32191 +                               qh->sched_frame =
32192 +                                   dwc_frame_num_inc(qh->start_split_frame,
32193 +                                                     qh->interval);
32194 +                               if (dwc_frame_num_le
32195 +                                   (qh->sched_frame, frame_number)) {
32196 +                                       qh->sched_frame = frame_number;
32197 +                               }
32198 +                               qh->sched_frame |= 0x7;
32199 +                               qh->start_split_frame = qh->sched_frame;
32200 +                       }
32201 +               } else {
32202 +                       qh->sched_frame =
32203 +                           dwc_frame_num_inc(qh->sched_frame, qh->interval);
32204 +                       if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
32205 +                               qh->sched_frame = frame_number;
32206 +                       }
32207 +               }
32208 +
32209 +               if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
32210 +                       dwc_otg_hcd_qh_remove(hcd, qh);
32211 +               } else {
32212 +                       /*
32213 +                        * Remove from periodic_sched_queued and move to
32214 +                        * appropriate queue.
32215 +                        */
32216 +                       if (qh->sched_frame == frame_number) {
32217 +                               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
32218 +                                                  &qh->qh_list_entry);
32219 +                       } else {
32220 +                               DWC_LIST_MOVE_HEAD(&hcd->
32221 +                                                  periodic_sched_inactive,
32222 +                                                  &qh->qh_list_entry);
32223 +                       }
32224 +               }
32225 +       }
32226 +
32227 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
32228 +}
32229 +
32230 +/** 
32231 + * This function allocates and initializes a QTD. 
32232 + *
32233 + * @param urb The URB to create a QTD from.  Each URB-QTD pair will end up
32234 + *           pointing to each other so each pair should have a unique correlation.
32235 + *
32236 + * @return Returns pointer to the newly allocated QTD, or NULL on error. */
32237 +dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb)
32238 +{
32239 +       dwc_otg_qtd_t *qtd;
32240 +
32241 +       qtd = dwc_otg_hcd_qtd_alloc();
32242 +       if (qtd == NULL) {
32243 +               return NULL;
32244 +       }
32245 +
32246 +       dwc_otg_hcd_qtd_init(qtd, urb);
32247 +       return qtd;
32248 +}
32249 +
32250 +/** 
32251 + * Initializes a QTD structure.
32252 + *
32253 + * @param qtd The QTD to initialize.
32254 + * @param urb The URB to use for initialization.  */
32255 +void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)
32256 +{
32257 +       dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t));
32258 +       qtd->urb = urb;
32259 +       if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) {
32260 +               /*
32261 +                * The only time the QTD data toggle is used is on the data
32262 +                * phase of control transfers. This phase always starts with
32263 +                * DATA1.
32264 +                */
32265 +               qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
32266 +               qtd->control_phase = DWC_OTG_CONTROL_SETUP;
32267 +       }
32268 +
32269 +       /* start split */
32270 +       qtd->complete_split = 0;
32271 +       qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
32272 +       qtd->isoc_split_offset = 0;
32273 +       qtd->in_process = 0;
32274 +
32275 +       /* Store the qtd ptr in the urb to reference what QTD. */
32276 +       urb->qtd = qtd;
32277 +       return;
32278 +}
32279 +
32280 +/**
32281 + * This function adds a QTD to the QTD-list of a QH.  It will find the correct
32282 + * QH to place the QTD into.  If it does not find a QH, then it will create a
32283 + * new QH. If the QH to which the QTD is added is not currently scheduled, it
32284 + * is placed into the proper schedule based on its EP type.
32285 + *
32286 + * @param[in] qtd The QTD to add
32287 + * @param[in] hcd The DWC HCD structure
32288 + * @param[out] qh out parameter to return queue head
32289 + *
32290 + * @return 0 if successful, negative error code otherwise.
32291 + */
32292 +int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
32293 +                       dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh)
32294 +{
32295 +       int retval = 0;
32296 +       uint64_t flags;
32297 +
32298 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
32299 +
32300 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
32301 +
32302 +       /*
32303 +        * Get the QH which holds the QTD-list to insert to. Create QH if it
32304 +        * doesn't exist.
32305 +        */
32306 +       if (*qh == NULL) {
32307 +               *qh = dwc_otg_hcd_qh_create(hcd, urb);
32308 +               if (*qh == NULL) {
32309 +                       retval = -1;
32310 +                       goto done;
32311 +               }
32312 +       }
32313 +
32314 +       retval = dwc_otg_hcd_qh_add(hcd, *qh);
32315 +       if (retval == 0) {
32316 +               DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
32317 +                                       qtd_list_entry);
32318 +       }
32319 +
32320 +      done:
32321 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
32322 +
32323 +       return retval;
32324 +}
32325 +
32326 +#endif                         /* DWC_DEVICE_ONLY */
32327 --- /dev/null
32328 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
32329 @@ -0,0 +1,2067 @@
32330 +/* ==========================================================================
32331 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
32332 + * $Revision: #79 $
32333 + * $Date: 2009/04/10 $
32334 + * $Change: 1230501 $
32335 + *
32336 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
32337 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
32338 + * otherwise expressly agreed to in writing between Synopsys and you.
32339 + *
32340 + * The Software IS NOT an item of Licensed Software or Licensed Product under
32341 + * any End User Software License Agreement or Agreement for Licensed Product
32342 + * with Synopsys or any supplement thereto. You are permitted to use and
32343 + * redistribute this Software in source and binary forms, with or without
32344 + * modification, provided that redistributions of source code must retain this
32345 + * notice. You may not view, use, disclose, copy or distribute this file or
32346 + * any information contained herein except pursuant to this license grant from
32347 + * Synopsys. If you do not agree with this notice, including the disclaimer
32348 + * below, then you are not authorized to use the Software.
32349 + *
32350 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
32351 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32352 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32353 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
32354 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32355 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32356 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32357 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32358 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32359 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32360 + * DAMAGE.
32361 + * ========================================================================== */
32362 +#ifndef DWC_HOST_ONLY
32363 +
32364 +/** @file
32365 + * This file implements PCD Core. All code in this file is portable and don't
32366 + * use any OS specific functions.
32367 + * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
32368 + * header file, which can be used to implement OS specific PCD interface.
32369 + *
32370 + * An important function of the PCD is managing interrupts generated
32371 + * by the DWC_otg controller. The implementation of the DWC_otg device
32372 + * mode interrupt service routines is in dwc_otg_pcd_intr.c.
32373 + *
32374 + * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
32375 + * @todo Does it work when the request size is greater than DEPTSIZ
32376 + * transfer size
32377 + *
32378 + */
32379 +
32380 +#include "dwc_otg_pcd.h"
32381 +
32382 +#ifdef DWC_UTE_CFI
32383 +#include "dwc_otg_cfi.h"
32384 +
32385 +extern int init_cfi(cfiobject_t * cfiobj);
32386 +#endif
32387 +
32388 +static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
32389 +{
32390 +       int i;
32391 +       if (pcd->ep0.priv == handle) {
32392 +               return &pcd->ep0;
32393 +       }
32394 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
32395 +               if (pcd->in_ep[i].priv == handle)
32396 +                       return &pcd->in_ep[i];
32397 +               if (pcd->out_ep[i].priv == handle)
32398 +                       return &pcd->out_ep[i];
32399 +       }
32400 +
32401 +       return NULL;
32402 +}
32403 +
32404 +/**
32405 + * This function completes a request.  It call's the request call back.
32406 + */
32407 +void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
32408 +                         int32_t status)
32409 +{
32410 +       unsigned stopped = ep->stopped;
32411 +
32412 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, ep);
32413 +       DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
32414 +
32415 +       /* don't modify queue heads during completion callback */
32416 +       ep->stopped = 1;
32417 +       DWC_SPINUNLOCK(ep->pcd->lock);
32418 +       ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
32419 +                               req->actual);
32420 +       DWC_SPINLOCK(ep->pcd->lock);
32421 +
32422 +       if (ep->pcd->request_pending > 0) {
32423 +               --ep->pcd->request_pending;
32424 +       }
32425 +
32426 +       ep->stopped = stopped;
32427 +       dwc_free(req);
32428 +}
32429 +
32430 +/**
32431 + * This function terminates all the requsts in the EP request queue.
32432 + */
32433 +void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
32434 +{
32435 +       dwc_otg_pcd_request_t *req;
32436 +
32437 +       ep->stopped = 1;
32438 +
32439 +       /* called with irqs blocked?? */
32440 +       while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
32441 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
32442 +               dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
32443 +       }
32444 +}
32445 +
32446 +void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
32447 +                      const struct dwc_otg_pcd_function_ops *fops)
32448 +{
32449 +       pcd->fops = fops;
32450 +}
32451 +
32452 +/**
32453 + * PCD Callback function for initializing the PCD when switching to
32454 + * device mode.
32455 + *
32456 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
32457 + */
32458 +static int32_t dwc_otg_pcd_start_cb(void *p)
32459 +{
32460 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
32461 +
32462 +       /*
32463 +        * Initialized the Core for Device mode.
32464 +        */
32465 +       if (dwc_otg_is_device_mode(GET_CORE_IF(pcd))) {
32466 +               dwc_otg_core_dev_init(GET_CORE_IF(pcd));
32467 +       }
32468 +       return 1;
32469 +}
32470 +
32471 +/** CFI-specific buffer allocation function for EP */
32472 +#ifdef DWC_UTE_CFI
32473 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
32474 +                             size_t buflen, int flags)
32475 +{
32476 +       dwc_otg_pcd_ep_t *ep;
32477 +       ep = get_ep_from_handle(pcd, pep);
32478 +       return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
32479 +                                         flags);
32480 +}
32481 +#else
32482 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
32483 +                             size_t buflen, int flags);
32484 +#endif
32485 +
32486 +/**
32487 + * PCD Callback function for notifying the PCD when resuming from
32488 + * suspend.
32489 + *
32490 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
32491 + */
32492 +static int32_t dwc_otg_pcd_resume_cb(void *p)
32493 +{
32494 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
32495 +
32496 +       if (pcd->fops->resume) {
32497 +               pcd->fops->resume(pcd);
32498 +       }
32499 +
32500 +       /* Stop the SRP timeout timer. */
32501 +       if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
32502 +           || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
32503 +               if (GET_CORE_IF(pcd)->srp_timer_started) {
32504 +                       GET_CORE_IF(pcd)->srp_timer_started = 0;
32505 +                       DWC_TIMER_CANCEL(pcd->srp_timer);
32506 +               }
32507 +       }
32508 +       return 1;
32509 +}
32510 +
32511 +/**
32512 + * PCD Callback function for notifying the PCD device is suspended.
32513 + *
32514 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
32515 + */
32516 +static int32_t dwc_otg_pcd_suspend_cb(void *p)
32517 +{
32518 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
32519 +
32520 +       if (pcd->fops->suspend) {
32521 +               pcd->fops->suspend(pcd);
32522 +       }
32523 +
32524 +       return 1;
32525 +}
32526 +
32527 +/**
32528 + * PCD Callback function for stopping the PCD when switching to Host
32529 + * mode.
32530 + *
32531 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
32532 + */
32533 +static int32_t dwc_otg_pcd_stop_cb(void *p)
32534 +{
32535 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
32536 +       extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
32537 +
32538 +       dwc_otg_pcd_stop(pcd);
32539 +       return 1;
32540 +}
32541 +
32542 +/**
32543 + * PCD Callback structure for handling mode switching.
32544 + */
32545 +static dwc_otg_cil_callbacks_t pcd_callbacks = {
32546 +       .start = dwc_otg_pcd_start_cb,
32547 +       .stop = dwc_otg_pcd_stop_cb,
32548 +       .suspend = dwc_otg_pcd_suspend_cb,
32549 +       .resume_wakeup = dwc_otg_pcd_resume_cb,
32550 +       .p = 0,                 /* Set at registration */
32551 +};
32552 +
32553 +/**
32554 + * This function allocates a DMA Descriptor chain for the Endpoint 
32555 + * buffer to be used for a transfer to/from the specified endpoint.
32556 + */
32557 +dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(uint32_t * dma_desc_addr,
32558 +                                               uint32_t count)
32559 +{
32560 +
32561 +       return dwc_dma_alloc(count * sizeof(dwc_otg_dev_dma_desc_t), dma_desc_addr);
32562 +}
32563 +
32564 +/**
32565 + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc.
32566 + */
32567 +void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
32568 +                               uint32_t dma_desc_addr, uint32_t count)
32569 +{
32570 +       dwc_dma_free(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
32571 +                    dma_desc_addr);
32572 +}
32573 +
32574 +#ifdef DWC_EN_ISOC
32575 +
32576 +/**
32577 + * This function initializes a descriptor chain for Isochronous transfer
32578 + *
32579 + * @param core_if Programming view of DWC_otg controller.
32580 + * @param dwc_ep The EP to start the transfer on.
32581 + *
32582 + */
32583 +void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
32584 +                                       dwc_ep_t * dwc_ep)
32585 +{
32586 +
32587 +       dsts_data_t dsts = {.d32 = 0 };
32588 +       depctl_data_t depctl = {.d32 = 0 };
32589 +       volatile uint32_t *addr;
32590 +       int i, j;
32591 +
32592 +       if (dwc_ep->is_in)
32593 +               dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
32594 +       else
32595 +               dwc_ep->desc_cnt =
32596 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
32597 +                   dwc_ep->bInterval;
32598 +
32599 +       /** Allocate descriptors for double buffering */
32600 +       dwc_ep->iso_desc_addr =
32601 +           dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
32602 +                                       dwc_ep->desc_cnt * 2);
32603 +       if (dwc_ep->desc_addr) {
32604 +               DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
32605 +               return;
32606 +       }
32607 +
32608 +       dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
32609 +
32610 +       /** ISO OUT EP */
32611 +       if (dwc_ep->is_in == 0) {
32612 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
32613 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
32614 +               dma_addr_t dma_ad;
32615 +               uint32_t data_per_desc;
32616 +               dwc_otg_dev_out_ep_regs_t *out_regs =
32617 +                   core_if->dev_if->out_ep_regs[dwc_ep->num];
32618 +               int offset;
32619 +
32620 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
32621 +               dma_ad = (dma_addr_t) dwc_read_reg32(&(out_regs->doepdma));
32622 +
32623 +               /** Buffer 0 descriptors setup */
32624 +               dma_ad = dwc_ep->dma_addr0;
32625 +
32626 +               sts.b_iso_out.bs = BS_HOST_READY;
32627 +               sts.b_iso_out.rxsts = 0;
32628 +               sts.b_iso_out.l = 0;
32629 +               sts.b_iso_out.sp = 0;
32630 +               sts.b_iso_out.ioc = 0;
32631 +               sts.b_iso_out.pid = 0;
32632 +               sts.b_iso_out.framenum = 0;
32633 +
32634 +               offset = 0;
32635 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
32636 +                    i += dwc_ep->pkt_per_frm) {
32637 +
32638 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
32639 +                               data_per_desc =
32640 +                                   ((j + 1) * dwc_ep->maxpacket >
32641 +                                    dwc_ep->data_per_frame) ? dwc_ep->
32642 +                                   data_per_frame -
32643 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
32644 +
32645 +                               data_per_desc +=
32646 +                                   (data_per_desc % 4) ? (4 -
32647 +                                                          data_per_desc %
32648 +                                                          4) : 0;
32649 +                               sts.b_iso_out.rxbytes = data_per_desc;
32650 +                               dma_desc->buf = dma_ad;
32651 +                               dma_desc->status.d32 = sts.d32;
32652 +
32653 +                               offset += data_per_desc;
32654 +                               dma_desc++;
32655 +                               dma_ad += data_per_desc;
32656 +                       }
32657 +               }
32658 +
32659 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
32660 +                       data_per_desc =
32661 +                           ((j + 1) * dwc_ep->maxpacket >
32662 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
32663 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
32664 +                       data_per_desc +=
32665 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
32666 +                       sts.b_iso_out.rxbytes = data_per_desc;
32667 +                       dma_desc->buf = dma_ad;
32668 +                       dma_desc->status.d32 = sts.d32;
32669 +
32670 +                       offset += data_per_desc;
32671 +                       dma_desc++;
32672 +                       dma_ad += data_per_desc;
32673 +               }
32674 +
32675 +               sts.b_iso_out.ioc = 1;
32676 +               data_per_desc =
32677 +                   ((j + 1) * dwc_ep->maxpacket >
32678 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
32679 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
32680 +               data_per_desc +=
32681 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
32682 +               sts.b_iso_out.rxbytes = data_per_desc;
32683 +
32684 +               dma_desc->buf = dma_ad;
32685 +               dma_desc->status.d32 = sts.d32;
32686 +               dma_desc++;
32687 +
32688 +               /** Buffer 1 descriptors setup */
32689 +               sts.b_iso_out.ioc = 0;
32690 +               dma_ad = dwc_ep->dma_addr1;
32691 +
32692 +               offset = 0;
32693 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
32694 +                    i += dwc_ep->pkt_per_frm) {
32695 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
32696 +                               data_per_desc =
32697 +                                   ((j + 1) * dwc_ep->maxpacket >
32698 +                                    dwc_ep->data_per_frame) ? dwc_ep->
32699 +                                   data_per_frame -
32700 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
32701 +                               data_per_desc +=
32702 +                                   (data_per_desc % 4) ? (4 -
32703 +                                                          data_per_desc %
32704 +                                                          4) : 0;
32705 +                               sts.b_iso_out.rxbytes = data_per_desc;
32706 +                               dma_desc->buf = dma_ad;
32707 +                               dma_desc->status.d32 = sts.d32;
32708 +
32709 +                               offset += data_per_desc;
32710 +                               dma_desc++;
32711 +                               dma_ad += data_per_desc;
32712 +                       }
32713 +               }
32714 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
32715 +                       data_per_desc =
32716 +                           ((j + 1) * dwc_ep->maxpacket >
32717 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
32718 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
32719 +                       data_per_desc +=
32720 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
32721 +                       sts.b_iso_out.rxbytes = data_per_desc;
32722 +                       dma_desc->buf = dma_ad;
32723 +                       dma_desc->status.d32 = sts.d32;
32724 +
32725 +                       offset += data_per_desc;
32726 +                       dma_desc++;
32727 +                       dma_ad += data_per_desc;
32728 +               }
32729 +
32730 +               sts.b_iso_out.ioc = 1;
32731 +               sts.b_iso_out.l = 1;
32732 +               data_per_desc =
32733 +                   ((j + 1) * dwc_ep->maxpacket >
32734 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
32735 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
32736 +               data_per_desc +=
32737 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
32738 +               sts.b_iso_out.rxbytes = data_per_desc;
32739 +
32740 +               dma_desc->buf = dma_ad;
32741 +               dma_desc->status.d32 = sts.d32;
32742 +
32743 +               dwc_ep->next_frame = 0;
32744 +
32745 +               /** Write dma_ad into DOEPDMA register */
32746 +               dwc_write_reg32(&(out_regs->doepdma),
32747 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
32748 +
32749 +       }
32750 +       /** ISO IN EP */
32751 +       else {
32752 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
32753 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
32754 +               dma_addr_t dma_ad;
32755 +               dwc_otg_dev_in_ep_regs_t *in_regs =
32756 +                   core_if->dev_if->in_ep_regs[dwc_ep->num];
32757 +               unsigned int frmnumber;
32758 +               fifosize_data_t txfifosize, rxfifosize;
32759 +
32760 +               txfifosize.d32 =
32761 +                   dwc_read_reg32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->
32762 +                                  dtxfsts);
32763 +               rxfifosize.d32 =
32764 +                   dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
32765 +
32766 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
32767 +
32768 +               dma_ad = dwc_ep->dma_addr0;
32769 +
32770 +               dsts.d32 =
32771 +                   dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
32772 +
32773 +               sts.b_iso_in.bs = BS_HOST_READY;
32774 +               sts.b_iso_in.txsts = 0;
32775 +               sts.b_iso_in.sp =
32776 +                   (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
32777 +               sts.b_iso_in.ioc = 0;
32778 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
32779 +
32780 +               frmnumber = dwc_ep->next_frame;
32781 +
32782 +               sts.b_iso_in.framenum = frmnumber;
32783 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
32784 +               sts.b_iso_in.l = 0;
32785 +
32786 +               /** Buffer 0 descriptors setup */
32787 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
32788 +                       dma_desc->buf = dma_ad;
32789 +                       dma_desc->status.d32 = sts.d32;
32790 +                       dma_desc++;
32791 +
32792 +                       dma_ad += dwc_ep->data_per_frame;
32793 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
32794 +               }
32795 +
32796 +               sts.b_iso_in.ioc = 1;
32797 +               dma_desc->buf = dma_ad;
32798 +               dma_desc->status.d32 = sts.d32;
32799 +               ++dma_desc;
32800 +
32801 +               /** Buffer 1 descriptors setup */
32802 +               sts.b_iso_in.ioc = 0;
32803 +               dma_ad = dwc_ep->dma_addr1;
32804 +
32805 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
32806 +                    i += dwc_ep->pkt_per_frm) {
32807 +                       dma_desc->buf = dma_ad;
32808 +                       dma_desc->status.d32 = sts.d32;
32809 +                       dma_desc++;
32810 +
32811 +                       dma_ad += dwc_ep->data_per_frame;
32812 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
32813 +
32814 +                       sts.b_iso_in.ioc = 0;
32815 +               }
32816 +               sts.b_iso_in.ioc = 1;
32817 +               sts.b_iso_in.l = 1;
32818 +
32819 +               dma_desc->buf = dma_ad;
32820 +               dma_desc->status.d32 = sts.d32;
32821 +
32822 +               dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
32823 +
32824 +               /** Write dma_ad into diepdma register */
32825 +               dwc_write_reg32(&(in_regs->diepdma),
32826 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
32827 +       }
32828 +       /** Enable endpoint, clear nak  */
32829 +       depctl.d32 = 0;
32830 +       depctl.b.epena = 1;
32831 +       depctl.b.usbactep = 1;
32832 +       depctl.b.cnak = 1;
32833 +
32834 +       dwc_modify_reg32(addr, depctl.d32, depctl.d32);
32835 +       depctl.d32 = dwc_read_reg32(addr);
32836 +}
32837 +
32838 +/**
32839 + * This function initializes a descriptor chain for Isochronous transfer
32840 + *
32841 + * @param core_if Programming view of DWC_otg controller.
32842 + * @param ep The EP to start the transfer on.
32843 + *
32844 + */
32845 +
32846 +void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
32847 +                                      dwc_ep_t * ep)
32848 +{
32849 +       depctl_data_t depctl = {.d32 = 0 };
32850 +       volatile uint32_t *addr;
32851 +
32852 +       if (ep->is_in) {
32853 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
32854 +       } else {
32855 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
32856 +       }
32857 +
32858 +       if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
32859 +               return;
32860 +       } else {
32861 +               deptsiz_data_t deptsiz = {.d32 = 0 };
32862 +
32863 +               ep->xfer_len =
32864 +                   ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
32865 +               ep->pkt_cnt =
32866 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
32867 +               ep->xfer_count = 0;
32868 +               ep->xfer_buff =
32869 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
32870 +               ep->dma_addr =
32871 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
32872 +
32873 +               if (ep->is_in) {
32874 +                       /* Program the transfer size and packet count
32875 +                        *      as follows: xfersize = N * maxpacket +
32876 +                        *      short_packet pktcnt = N + (short_packet
32877 +                        *      exist ? 1 : 0)  
32878 +                        */
32879 +                       deptsiz.b.mc = ep->pkt_per_frm;
32880 +                       deptsiz.b.xfersize = ep->xfer_len;
32881 +                       deptsiz.b.pktcnt =
32882 +                           (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
32883 +                       dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]->
32884 +                                       dieptsiz, deptsiz.d32);
32885 +
32886 +                       /* Write the DMA register */
32887 +                       dwc_write_reg32(&
32888 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
32889 +                                        diepdma), (uint32_t) ep->dma_addr);
32890 +
32891 +               } else {
32892 +                       deptsiz.b.pktcnt =
32893 +                           (ep->xfer_len + (ep->maxpacket - 1)) /
32894 +                           ep->maxpacket;
32895 +                       deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
32896 +
32897 +                       dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]->
32898 +                                       doeptsiz, deptsiz.d32);
32899 +
32900 +                       /* Write the DMA register */
32901 +                       dwc_write_reg32(&
32902 +                                       (core_if->dev_if->out_ep_regs[ep->num]->
32903 +                                        doepdma), (uint32_t) ep->dma_addr);
32904 +
32905 +               }
32906 +               /** Enable endpoint, clear nak  */
32907 +               depctl.d32 = 0;
32908 +               dwc_modify_reg32(addr, depctl.d32, depctl.d32);
32909 +
32910 +               depctl.b.epena = 1;
32911 +               depctl.b.cnak = 1;
32912 +
32913 +               dwc_modify_reg32(addr, depctl.d32, depctl.d32);
32914 +       }
32915 +}
32916 +
32917 +/**
32918 + * This function does the setup for a data transfer for an EP and
32919 + * starts the transfer.         For an IN transfer, the packets will be
32920 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
32921 + * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.
32922 + *
32923 + * @param core_if Programming view of DWC_otg controller.
32924 + * @param ep The EP to start the transfer on.
32925 + */
32926 +
32927 +static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
32928 +                                         dwc_ep_t * ep)
32929 +{
32930 +       if (core_if->dma_enable) {
32931 +               if (core_if->dma_desc_enable) {
32932 +                       if (ep->is_in) {
32933 +                               ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
32934 +                       } else {
32935 +                               ep->desc_cnt = ep->pkt_cnt;
32936 +                       }
32937 +                       dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
32938 +               } else {
32939 +                       if (core_if->pti_enh_enable) {
32940 +                               dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
32941 +                       } else {
32942 +                               ep->cur_pkt_addr =
32943 +                                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->
32944 +                                   xfer_buff0;
32945 +                               ep->cur_pkt_dma_addr =
32946 +                                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->
32947 +                                   dma_addr0;
32948 +                               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
32949 +                       }
32950 +               }
32951 +       } else {
32952 +               ep->cur_pkt_addr =
32953 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
32954 +               ep->cur_pkt_dma_addr =
32955 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
32956 +               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
32957 +       }
32958 +}
32959 +
32960 +/**
32961 + * This function does the setup for a data transfer for an EP and
32962 + * starts the transfer.         For an IN transfer, the packets will be
32963 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
32964 + * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.
32965 + *
32966 + * @param core_if Programming view of DWC_otg controller.
32967 + * @param ep The EP to start the transfer on.
32968 + */
32969 +
32970 +void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
32971 +{
32972 +       depctl_data_t depctl = {.d32 = 0 };
32973 +       volatile uint32_t *addr;
32974 +
32975 +       if (ep->is_in == 1) {
32976 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
32977 +       } else {
32978 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
32979 +       }
32980 +
32981 +       /* disable the ep */
32982 +       depctl.d32 = dwc_read_reg32(addr);
32983 +
32984 +       depctl.b.epdis = 1;
32985 +       depctl.b.snak = 1;
32986 +
32987 +       dwc_write_reg32(addr, depctl.d32);
32988 +
32989 +       if (core_if->dma_desc_enable &&
32990 +           ep->iso_desc_addr && ep->iso_dma_desc_addr) {
32991 +               dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
32992 +                                          ep->iso_dma_desc_addr,
32993 +                                          ep->desc_cnt * 2);
32994 +       }
32995 +
32996 +       /* reset varibales */
32997 +       ep->dma_addr0 = 0;
32998 +       ep->dma_addr1 = 0;
32999 +       ep->xfer_buff0 = 0;
33000 +       ep->xfer_buff1 = 0;
33001 +       ep->data_per_frame = 0;
33002 +       ep->data_pattern_frame = 0;
33003 +       ep->sync_frame = 0;
33004 +       ep->buf_proc_intrvl = 0;
33005 +       ep->bInterval = 0;
33006 +       ep->proc_buf_num = 0;
33007 +       ep->pkt_per_frm = 0;
33008 +       ep->pkt_per_frm = 0;
33009 +       ep->desc_cnt = 0;
33010 +       ep->iso_desc_addr = 0;
33011 +       ep->iso_dma_desc_addr = 0;
33012 +}
33013 +
33014 +int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
33015 +                            uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
33016 +                            dwc_dma_t dma1, int sync_frame, int dp_frame,
33017 +                            int data_per_frame, int start_frame,
33018 +                            int buf_proc_intrvl, void *req_handle,
33019 +                            int atomic_alloc)
33020 +{
33021 +       dwc_otg_pcd_ep_t *ep;
33022 +       uint64_t flags = 0;
33023 +       dwc_ep_t *dwc_ep;
33024 +       int32_t frm_data;
33025 +       dsts_data_t dsts;
33026 +       dwc_otg_core_if_t *core_if;
33027 +
33028 +       ep = get_ep_from_handle(pcd, ep_handle);
33029 +
33030 +       if (!ep->desc || ep->dwc_ep.num == 0) {
33031 +               DWC_WARN("bad ep\n");
33032 +               return -DWC_E_INVALID;
33033 +       }
33034 +
33035 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
33036 +       core_if = GET_CORE_IF(pcd);
33037 +       dwc_ep = &ep->dwc_ep;
33038 +
33039 +       if (ep->iso_req_handle) {
33040 +               DWC_WARN("ISO request in progress\n");
33041 +       }
33042 +
33043 +       dwc_ep->dma_addr0 = dma0;
33044 +       dwc_ep->dma_addr1 = dma1;
33045 +
33046 +       dwc_ep->xfer_buff0 = buf0;
33047 +       dwc_ep->xfer_buff1 = buf1;
33048 +
33049 +       dwc_ep->data_per_frame = data_per_frame;
33050 +
33051 +       /** @todo - pattern data support is to be implemented in the future */
33052 +       dwc_ep->data_pattern_frame = dp_frame;
33053 +       dwc_ep->sync_frame = sync_frame;
33054 +
33055 +       dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
33056 +
33057 +       dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
33058 +
33059 +       dwc_ep->proc_buf_num = 0;
33060 +
33061 +       dwc_ep->pkt_per_frm = 0;
33062 +       frm_data = ep->dwc_ep.data_per_frame;
33063 +       while (frm_data > 0) {
33064 +               dwc_ep->pkt_per_frm++;
33065 +               frm_data -= ep->dwc_ep.maxpacket;
33066 +       }
33067 +
33068 +       dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
33069 +
33070 +       if (start_frame == -1) {
33071 +               dwc_ep->next_frame = dsts.b.soffn + 1;
33072 +               if (dwc_ep->bInterval != 1) {
33073 +                       dwc_ep->next_frame =
33074 +                           dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
33075 +                                                 dwc_ep->next_frame %
33076 +                                                 dwc_ep->bInterval);
33077 +               }
33078 +       } else {
33079 +               dwc_ep->next_frame = start_frame;
33080 +       }
33081 +
33082 +       if (!core_if->pti_enh_enable) {
33083 +               dwc_ep->pkt_cnt =
33084 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
33085 +                   dwc_ep->bInterval;
33086 +       } else {
33087 +               dwc_ep->pkt_cnt =
33088 +                   (dwc_ep->data_per_frame *
33089 +                    (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
33090 +                    - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
33091 +       }
33092 +
33093 +       if (core_if->dma_desc_enable) {
33094 +               dwc_ep->desc_cnt =
33095 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
33096 +                   dwc_ep->bInterval;
33097 +       }
33098 +
33099 +       if (atomic_alloc) {
33100 +               dwc_ep->pkt_info =
33101 +                   dwc_alloc_atomic(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
33102 +       } else {
33103 +               dwc_ep->pkt_info =
33104 +                   dwc_alloc(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
33105 +       }
33106 +       if (!dwc_ep->pkt_info) {
33107 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33108 +               return -DWC_E_NO_MEMORY;
33109 +       }
33110 +       if (core_if->pti_enh_enable) {
33111 +               dwc_memset(dwc_ep->pkt_info, 0,
33112 +                          sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
33113 +       }
33114 +
33115 +       dwc_ep->cur_pkt = 0;
33116 +       ep->iso_req_handle = req_handle;
33117 +
33118 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33119 +       dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
33120 +       return 0;
33121 +}
33122 +
33123 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
33124 +                           void *req_handle)
33125 +{
33126 +       uint64_t flags = 0;
33127 +       dwc_otg_pcd_ep_t *ep;
33128 +       dwc_ep_t *dwc_ep;
33129 +
33130 +       ep = get_ep_from_handle(pcd, ep_handle);
33131 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
33132 +               DWC_WARN("bad ep\n");
33133 +               return -DWC_E_INVALID;
33134 +       }
33135 +       dwc_ep = &ep->dwc_ep;
33136 +
33137 +       dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
33138 +
33139 +       dwc_free(dwc_ep->pkt_info);
33140 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
33141 +       if (ep->iso_req_handle != req_handle) {
33142 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33143 +               return -DWC_E_INVALID;
33144 +       }
33145 +
33146 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33147 +
33148 +       ep->iso_req_handle = 0;
33149 +       return 0;
33150 +}
33151 +
33152 +/**
33153 + * This function is used for perodical data exchnage between PCD and gadget drivers.
33154 + * for Isochronous EPs
33155 + *
33156 + *     - Every time a sync period completes this function is called to 
33157 + *       perform data exchange between PCD and gadget
33158 + */
33159 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
33160 +                            void *req_handle)
33161 +{
33162 +       int i;
33163 +       dwc_ep_t *dwc_ep;
33164 +
33165 +       dwc_ep = &ep->dwc_ep;
33166 +
33167 +       DWC_SPINUNLOCK(ep->pcd->lock);
33168 +       pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
33169 +                                dwc_ep->proc_buf_num ^ 0x1);
33170 +       DWC_SPINLOCK(ep->pcd->lock);
33171 +
33172 +       for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
33173 +               dwc_ep->pkt_info[i].status = 0;
33174 +               dwc_ep->pkt_info[i].offset = 0;
33175 +               dwc_ep->pkt_info[i].length = 0;
33176 +       }
33177 +}
33178 +
33179 +int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
33180 +                                    void *iso_req_handle)
33181 +{
33182 +       dwc_otg_pcd_ep_t *ep;
33183 +       dwc_ep_t *dwc_ep;
33184 +
33185 +       ep = get_ep_from_handle(pcd, ep_handle);
33186 +       dwc_ep = &ep->dwc_ep;
33187 +
33188 +       return dwc_ep->pkt_cnt;
33189 +}
33190 +
33191 +void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
33192 +                                      void *iso_req_handle, int packet,
33193 +                                      int *status, int *actual, int *offset)
33194 +{
33195 +       dwc_otg_pcd_ep_t *ep;
33196 +       dwc_ep_t *dwc_ep;
33197 +
33198 +       ep = get_ep_from_handle(pcd, ep_handle);
33199 +       dwc_ep = &ep->dwc_ep;
33200 +
33201 +       *status = dwc_ep->pkt_info[packet].status;
33202 +       *actual = dwc_ep->pkt_info[packet].length;
33203 +       *offset = dwc_ep->pkt_info[packet].offset;
33204 +}
33205 +
33206 +#endif                         /* DWC_EN_ISOC */
33207 +
33208 +static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
33209 +                               uint32_t is_in, uint32_t ep_num)
33210 +{
33211 +       /* Init EP structure */
33212 +       pcd_ep->desc = 0;
33213 +       pcd_ep->pcd = pcd;
33214 +       pcd_ep->stopped = 1;
33215 +       pcd_ep->queue_sof = 0;
33216 +
33217 +       /* Init DWC ep structure */
33218 +       pcd_ep->dwc_ep.is_in = is_in;
33219 +       pcd_ep->dwc_ep.num = ep_num;
33220 +       pcd_ep->dwc_ep.active = 0;
33221 +       pcd_ep->dwc_ep.tx_fifo_num = 0;
33222 +       /* Control until ep is actvated */
33223 +       pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
33224 +       pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
33225 +       pcd_ep->dwc_ep.dma_addr = 0;
33226 +       pcd_ep->dwc_ep.start_xfer_buff = 0;
33227 +       pcd_ep->dwc_ep.xfer_buff = 0;
33228 +       pcd_ep->dwc_ep.xfer_len = 0;
33229 +       pcd_ep->dwc_ep.xfer_count = 0;
33230 +       pcd_ep->dwc_ep.sent_zlp = 0;
33231 +       pcd_ep->dwc_ep.total_len = 0;
33232 +       pcd_ep->dwc_ep.desc_addr = 0;
33233 +       pcd_ep->dwc_ep.dma_desc_addr = 0;
33234 +       DWC_CIRCLEQ_INIT(&pcd_ep->queue);
33235 +}
33236 +
33237 +/**
33238 + * Initialise ep's
33239 + */
33240 +static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
33241 +{
33242 +       int i;
33243 +       uint32_t hwcfg1;
33244 +       dwc_otg_pcd_ep_t *ep;
33245 +       int in_ep_cntr, out_ep_cntr;
33246 +       uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
33247 +       uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
33248 +
33249 +       /**
33250 +        * Initialize the EP0 structure.
33251 +        */
33252 +       ep = &pcd->ep0;
33253 +       dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
33254 +
33255 +       in_ep_cntr = 0;
33256 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
33257 +       for (i = 1; in_ep_cntr < num_in_eps; i++) {
33258 +               if ((hwcfg1 & 0x1) == 0) {
33259 +                       dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
33260 +                       in_ep_cntr++;
33261 +                       /**
33262 +                        * @todo NGS: Add direction to EP, based on contents
33263 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
33264 +                        * sprintf(";r
33265 +                        */
33266 +                       dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
33267 +
33268 +                       DWC_CIRCLEQ_INIT(&ep->queue);
33269 +               }
33270 +               hwcfg1 >>= 2;
33271 +       }
33272 +
33273 +       out_ep_cntr = 0;
33274 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
33275 +       for (i = 1; out_ep_cntr < num_out_eps; i++) {
33276 +               if ((hwcfg1 & 0x1) == 0) {
33277 +                       dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
33278 +                       out_ep_cntr++;
33279 +                       /**
33280 +                        * @todo NGS: Add direction to EP, based on contents
33281 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
33282 +                        * sprintf(";r
33283 +                        */
33284 +                       dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
33285 +                       DWC_CIRCLEQ_INIT(&ep->queue);
33286 +               }
33287 +               hwcfg1 >>= 2;
33288 +       }
33289 +
33290 +       pcd->ep0state = EP0_DISCONNECT;
33291 +       pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
33292 +       pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
33293 +}
33294 +
33295 +/**
33296 + * This function is called when the SRP timer expires. The SRP should
33297 + * complete within 6 seconds.
33298 + */
33299 +static void srp_timeout(void *ptr)
33300 +{
33301 +       gotgctl_data_t gotgctl;
33302 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
33303 +       volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
33304 +
33305 +       gotgctl.d32 = dwc_read_reg32(addr);
33306 +
33307 +       core_if->srp_timer_started = 0;
33308 +
33309 +       if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
33310 +           (core_if->core_params->i2c_enable)) {
33311 +               DWC_PRINTF("SRP Timeout\n");
33312 +
33313 +               if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
33314 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
33315 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->
33316 +                                                              p);
33317 +                       }
33318 +
33319 +                       /* Clear Session Request */
33320 +                       gotgctl.d32 = 0;
33321 +                       gotgctl.b.sesreq = 1;
33322 +                       dwc_modify_reg32(&core_if->core_global_regs->gotgctl,
33323 +                                        gotgctl.d32, 0);
33324 +
33325 +                       core_if->srp_success = 0;
33326 +               } else {
33327 +                       __DWC_ERROR("Device not connected/responding\n");
33328 +                       gotgctl.b.sesreq = 0;
33329 +                       dwc_write_reg32(addr, gotgctl.d32);
33330 +               }
33331 +       } else if (gotgctl.b.sesreq) {
33332 +               DWC_PRINTF("SRP Timeout\n");
33333 +
33334 +               __DWC_ERROR("Device not connected/responding\n");
33335 +               gotgctl.b.sesreq = 0;
33336 +               dwc_write_reg32(addr, gotgctl.d32);
33337 +       } else {
33338 +               DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
33339 +       }
33340 +}
33341 +
33342 +/**
33343 + * Tasklet
33344 + *
33345 + */
33346 +extern void start_next_request(dwc_otg_pcd_ep_t * ep);
33347 +
33348 +static void start_xfer_tasklet_func(void *data)
33349 +{
33350 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
33351 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
33352 +
33353 +       int i;
33354 +       depctl_data_t diepctl;
33355 +
33356 +       DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
33357 +
33358 +       diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl);
33359 +
33360 +       if (pcd->ep0.queue_sof) {
33361 +               pcd->ep0.queue_sof = 0;
33362 +               start_next_request(&pcd->ep0);
33363 +               // break;
33364 +       }
33365 +
33366 +       for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
33367 +               depctl_data_t diepctl;
33368 +               diepctl.d32 =
33369 +                   dwc_read_reg32(&core_if->dev_if->in_ep_regs[i]->diepctl);
33370 +
33371 +               if (pcd->in_ep[i].queue_sof) {
33372 +                       pcd->in_ep[i].queue_sof = 0;
33373 +                       start_next_request(&pcd->in_ep[i]);
33374 +                       // break;
33375 +               }
33376 +       }
33377 +
33378 +       return;
33379 +}
33380 +
33381 +/**
33382 + * This function initialized the PCD portion of the driver.
33383 + *
33384 + */
33385 +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
33386 +{
33387 +       dwc_otg_pcd_t *pcd = 0;
33388 +       dwc_otg_dev_if_t *dev_if;
33389 +
33390 +       /*
33391 +        * Allocate PCD structure
33392 +        */
33393 +       pcd = dwc_alloc(sizeof(dwc_otg_pcd_t));
33394 +
33395 +       if (pcd == 0) {
33396 +               return NULL;
33397 +       }
33398 +
33399 +       pcd->lock = DWC_SPINLOCK_ALLOC();
33400 +        DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n",
33401 +                    pcd, core_if);//GRAYG
33402 +       pcd->core_if = core_if;
33403 +       if (!pcd->lock) {
33404 +               DWC_ERROR("Could not allocate lock for pcd");
33405 +               dwc_free(pcd);
33406 +               return NULL;
33407 +       }
33408 +       dev_if = core_if->dev_if;
33409 +
33410 +       if (core_if->hwcfg4.b.ded_fifo_en) {
33411 +               DWC_PRINTF("Dedicated Tx FIFOs mode\n");
33412 +       } else {
33413 +               DWC_PRINTF("Shared Tx FIFO mode\n");
33414 +       }
33415 +
33416 +       /*
33417 +        * Initialized the Core for Device mode.
33418 +        */
33419 +       if (dwc_otg_is_device_mode(core_if)) {
33420 +               dwc_otg_core_dev_init(core_if);
33421 +       }
33422 +
33423 +       /*
33424 +        * Register the PCD Callbacks.
33425 +        */
33426 +       dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
33427 +
33428 +       /*
33429 +        * Initialize the DMA buffer for SETUP packets
33430 +        */
33431 +       if (GET_CORE_IF(pcd)->dma_enable) {
33432 +               pcd->setup_pkt =
33433 +                   dwc_dma_alloc(sizeof(*pcd->setup_pkt) * 5,
33434 +                                 &pcd->setup_pkt_dma_handle);
33435 +               if (pcd->setup_pkt == 0) {
33436 +                       dwc_free(pcd);
33437 +                       return NULL;
33438 +               }
33439 +
33440 +               pcd->status_buf =
33441 +                   dwc_dma_alloc(sizeof(uint16_t),
33442 +                                 &pcd->status_buf_dma_handle);
33443 +               if (pcd->status_buf == 0) {
33444 +                       dwc_dma_free(sizeof(*pcd->setup_pkt) * 5,
33445 +                                    pcd->setup_pkt, pcd->setup_pkt_dma_handle);
33446 +                       dwc_free(pcd);
33447 +                       return NULL;
33448 +               }
33449 +
33450 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
33451 +                       dev_if->setup_desc_addr[0] =
33452 +                           dwc_otg_ep_alloc_desc_chain(&dev_if->
33453 +                                                       dma_setup_desc_addr[0],
33454 +                                                       1);
33455 +                       dev_if->setup_desc_addr[1] =
33456 +                           dwc_otg_ep_alloc_desc_chain(&dev_if->
33457 +                                                       dma_setup_desc_addr[1],
33458 +                                                       1);
33459 +                       dev_if->in_desc_addr =
33460 +                           dwc_otg_ep_alloc_desc_chain(&dev_if->
33461 +                                                       dma_in_desc_addr, 1);
33462 +                       dev_if->out_desc_addr =
33463 +                           dwc_otg_ep_alloc_desc_chain(&dev_if->
33464 +                                                       dma_out_desc_addr, 1);
33465 +
33466 +                       if (dev_if->setup_desc_addr[0] == 0
33467 +                           || dev_if->setup_desc_addr[1] == 0
33468 +                           || dev_if->in_desc_addr == 0
33469 +                           || dev_if->out_desc_addr == 0) {
33470 +
33471 +                               if (dev_if->out_desc_addr)
33472 +                                       dwc_otg_ep_free_desc_chain(dev_if->
33473 +                                                                  out_desc_addr,
33474 +                                                                  dev_if->
33475 +                                                                  dma_out_desc_addr,
33476 +                                                                  1);
33477 +                               if (dev_if->in_desc_addr)
33478 +                                       dwc_otg_ep_free_desc_chain(dev_if->
33479 +                                                                  in_desc_addr,
33480 +                                                                  dev_if->
33481 +                                                                  dma_in_desc_addr,
33482 +                                                                  1);
33483 +                               if (dev_if->setup_desc_addr[1])
33484 +                                       dwc_otg_ep_free_desc_chain(dev_if->
33485 +                                                                  setup_desc_addr
33486 +                                                                  [1],
33487 +                                                                  dev_if->
33488 +                                                                  dma_setup_desc_addr
33489 +                                                                  [1], 1);
33490 +                               if (dev_if->setup_desc_addr[0])
33491 +                                       dwc_otg_ep_free_desc_chain(dev_if->
33492 +                                                                  setup_desc_addr
33493 +                                                                  [0],
33494 +                                                                  dev_if->
33495 +                                                                  dma_setup_desc_addr
33496 +                                                                  [0], 1);
33497 +
33498 +                               dwc_dma_free(sizeof(*pcd->setup_pkt) * 5,
33499 +                                            pcd->setup_pkt,
33500 +                                            pcd->setup_pkt_dma_handle);
33501 +                               dwc_dma_free(sizeof(*pcd->status_buf),
33502 +                                            pcd->status_buf,
33503 +                                            pcd->status_buf_dma_handle);
33504 +
33505 +                               dwc_free(pcd);
33506 +
33507 +                               return NULL;
33508 +                       }
33509 +               }
33510 +       } else {
33511 +               pcd->setup_pkt = dwc_alloc(sizeof(*pcd->setup_pkt) * 5);
33512 +               if (pcd->setup_pkt == 0) {
33513 +                       dwc_free(pcd);
33514 +                       return NULL;
33515 +               }
33516 +
33517 +               pcd->status_buf = dwc_alloc(sizeof(uint16_t));
33518 +               if (pcd->status_buf == 0) {
33519 +                       dwc_free(pcd->setup_pkt);
33520 +                       dwc_free(pcd);
33521 +                       return NULL;
33522 +               }
33523 +       }
33524 +
33525 +       dwc_otg_pcd_reinit(pcd);
33526 +
33527 +       /* Allocate the cfi object for the PCD */
33528 +#ifdef DWC_UTE_CFI
33529 +       pcd->cfi = dwc_alloc(sizeof(cfiobject_t));
33530 +       if (NULL == pcd->cfi)
33531 +               return NULL;
33532 +       if (init_cfi(pcd->cfi)) {
33533 +               CFI_INFO("%s: Failed to init the CFI object\n", __func__);
33534 +               return NULL;
33535 +       }
33536 +#endif
33537 +
33538 +       /* Initialize tasklets */
33539 +       pcd->start_xfer_tasklet = DWC_TASK_ALLOC(start_xfer_tasklet_func, pcd);
33540 +       pcd->test_mode_tasklet = DWC_TASK_ALLOC(do_test_mode, pcd);
33541 +       /* Initialize timer */
33542 +       pcd->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
33543 +       return pcd;
33544 +}
33545 +
33546 +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
33547 +{
33548 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
33549 +
33550 +       if (GET_CORE_IF(pcd)->dma_enable) {
33551 +               dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
33552 +                            pcd->setup_pkt_dma_handle);
33553 +               dwc_dma_free(sizeof(uint16_t), pcd->status_buf,
33554 +                            pcd->status_buf_dma_handle);
33555 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
33556 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
33557 +                                                  dev_if->
33558 +                                                  dma_setup_desc_addr[0], 1);
33559 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
33560 +                                                  dev_if->
33561 +                                                  dma_setup_desc_addr[1], 1);
33562 +                       dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
33563 +                                                  dev_if->dma_in_desc_addr, 1);
33564 +                       dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
33565 +                                                  dev_if->dma_out_desc_addr,
33566 +                                                  1);
33567 +               }
33568 +       } else {
33569 +               dwc_free(pcd->setup_pkt);
33570 +               dwc_free(pcd->status_buf);
33571 +       }
33572 +       DWC_SPINLOCK_FREE(pcd->lock);
33573 +       DWC_TASK_FREE(pcd->start_xfer_tasklet);
33574 +       DWC_TASK_FREE(pcd->test_mode_tasklet);
33575 +       DWC_TIMER_FREE(pcd->srp_timer);
33576 +
33577 +/* Release the CFI object's dynamic memory */
33578 +#ifdef DWC_UTE_CFI
33579 +       if (pcd->cfi->ops.release) {
33580 +               pcd->cfi->ops.release(pcd->cfi);
33581 +       }
33582 +#endif
33583 +
33584 +       dwc_free(pcd);
33585 +}
33586 +
33587 +uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
33588 +{
33589 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
33590 +
33591 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
33592 +           ((core_if->hwcfg2.b.hs_phy_type == 2) &&
33593 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
33594 +            (core_if->core_params->ulpi_fs_ls))) {
33595 +               return 0;
33596 +       }
33597 +
33598 +       return 1;
33599 +}
33600 +
33601 +uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
33602 +{
33603 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
33604 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
33605 +
33606 +       usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
33607 +       if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
33608 +               return 0;
33609 +       }
33610 +
33611 +       return 1;
33612 +}
33613 +
33614 +/**
33615 + * This function assigns periodic Tx FIFO to an periodic EP
33616 + * in shared Tx FIFO mode
33617 + */
33618 +static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
33619 +{
33620 +       uint32_t TxMsk = 1;
33621 +       int i;
33622 +
33623 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
33624 +               if ((TxMsk & core_if->tx_msk) == 0) {
33625 +                       core_if->tx_msk |= TxMsk;
33626 +                       return i + 1;
33627 +               }
33628 +               TxMsk <<= 1;
33629 +       }
33630 +       return 0;
33631 +}
33632 +
33633 +/**
33634 + * This function assigns periodic Tx FIFO to an periodic EP
33635 + * in shared Tx FIFO mode
33636 + */
33637 +static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
33638 +{
33639 +       uint32_t PerTxMsk = 1;
33640 +       int i;
33641 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
33642 +               if ((PerTxMsk & core_if->p_tx_msk) == 0) {
33643 +                       core_if->p_tx_msk |= PerTxMsk;
33644 +                       return i + 1;
33645 +               }
33646 +               PerTxMsk <<= 1;
33647 +       }
33648 +       return 0;
33649 +}
33650 +
33651 +/**
33652 + * This function releases periodic Tx FIFO
33653 + * in shared Tx FIFO mode
33654 + */
33655 +static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
33656 +                                 uint32_t fifo_num)
33657 +{
33658 +       core_if->p_tx_msk =
33659 +           (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
33660 +}
33661 +
33662 +/**
33663 + * This function releases periodic Tx FIFO
33664 + * in shared Tx FIFO mode
33665 + */
33666 +static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
33667 +{
33668 +       core_if->tx_msk =
33669 +           (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
33670 +}
33671 +
33672 +int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
33673 +                         const uint8_t * ep_desc, void *usb_ep)
33674 +{
33675 +       int num, dir;
33676 +       dwc_otg_pcd_ep_t *ep = 0;
33677 +       const usb_endpoint_descriptor_t *desc;
33678 +       uint64_t flags;
33679 +       int retval = 0;
33680 +
33681 +       desc = (const usb_endpoint_descriptor_t *)ep_desc;
33682 +
33683 +       if (!desc) {
33684 +               pcd->ep0.priv = usb_ep;
33685 +               ep = &pcd->ep0;
33686 +               retval = -DWC_E_INVALID;
33687 +               goto out;
33688 +       }
33689 +
33690 +       num = UE_GET_ADDR(desc->bEndpointAddress);
33691 +       dir = UE_GET_DIR(desc->bEndpointAddress);
33692 +
33693 +       if (!desc->wMaxPacketSize) {
33694 +               DWC_WARN("bad maxpacketsize\n");
33695 +               retval = -DWC_E_INVALID;
33696 +               goto out;
33697 +       }
33698 +
33699 +       if (dir == UE_DIR_IN) {
33700 +               ep = &pcd->in_ep[num - 1];
33701 +       } else {
33702 +               ep = &pcd->out_ep[num - 1];
33703 +       }
33704 +
33705 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
33706 +
33707 +       ep->desc = desc;
33708 +       ep->priv = usb_ep;
33709 +
33710 +       /*
33711 +        * Activate the EP
33712 +        */
33713 +       ep->stopped = 0;
33714 +
33715 +       ep->dwc_ep.is_in = (dir == UE_DIR_IN);
33716 +       ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
33717 +
33718 +       ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
33719 +
33720 +       if (ep->dwc_ep.is_in) {
33721 +               if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
33722 +                       ep->dwc_ep.tx_fifo_num = 0;
33723 +
33724 +                       if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
33725 +                               /*
33726 +                                * if ISOC EP then assign a Periodic Tx FIFO.
33727 +                                */
33728 +                               ep->dwc_ep.tx_fifo_num =
33729 +                                   assign_perio_tx_fifo(GET_CORE_IF(pcd));
33730 +                       }
33731 +               } else {
33732 +                       /*
33733 +                        * if Dedicated FIFOs mode is on then assign a Tx FIFO.
33734 +                        */
33735 +                       ep->dwc_ep.tx_fifo_num =
33736 +                           assign_tx_fifo(GET_CORE_IF(pcd));
33737 +
33738 +               }
33739 +       }
33740 +       /* Set initial data PID. */
33741 +       if (ep->dwc_ep.type == UE_BULK) {
33742 +               ep->dwc_ep.data_pid_start = 0;
33743 +       }
33744 +
33745 +       /* Alloc DMA Descriptors */
33746 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
33747 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
33748 +                       ep->dwc_ep.desc_addr =
33749 +                           dwc_otg_ep_alloc_desc_chain(&ep->dwc_ep.
33750 +                                                       dma_desc_addr,
33751 +                                                       MAX_DMA_DESC_CNT);
33752 +                       if (!ep->dwc_ep.desc_addr) {
33753 +                               DWC_WARN("%s, can't allocate DMA descriptor\n",
33754 +                                        __func__);
33755 +                               retval = -DWC_E_SHUTDOWN;
33756 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33757 +                               goto out;
33758 +                       }
33759 +               }
33760 +       }
33761 +
33762 +       DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
33763 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"),
33764 +                   ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
33765 +
33766 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
33767 +
33768 +#ifdef DWC_UTE_CFI
33769 +       if (pcd->cfi->ops.ep_enable) {
33770 +               pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
33771 +       }
33772 +#endif
33773 +
33774 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33775 +
33776 +      out:
33777 +       return retval;
33778 +}
33779 +
33780 +int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
33781 +{
33782 +       dwc_otg_pcd_ep_t *ep;
33783 +       uint64_t flags;
33784 +       dwc_otg_dev_dma_desc_t *desc_addr;
33785 +       dwc_dma_t dma_desc_addr;
33786 +
33787 +       ep = get_ep_from_handle(pcd, ep_handle);
33788 +
33789 +       if (!ep || !ep->desc) {
33790 +               DWC_DEBUGPL(DBG_PCD, "%s, %d %s not enabled\n", __func__,
33791 +                           ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT");
33792 +               return -DWC_E_INVALID;
33793 +       }
33794 +
33795 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
33796 +
33797 +       dwc_otg_request_nuke(ep);
33798 +
33799 +       dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
33800 +       ep->desc = 0;
33801 +       ep->stopped = 1;
33802 +
33803 +       if (ep->dwc_ep.is_in) {
33804 +               dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
33805 +               release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
33806 +               release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
33807 +       }
33808 +
33809 +       /* Free DMA Descriptors */
33810 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
33811 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
33812 +                       desc_addr = ep->dwc_ep.desc_addr;
33813 +                       dma_desc_addr = ep->dwc_ep.dma_desc_addr;
33814 +
33815 +                       /* Cannot call dma_free_coherent() with IRQs disabled */
33816 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33817 +                       dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
33818 +                                                  MAX_DMA_DESC_CNT);
33819 +
33820 +                       goto out_unlocked;
33821 +               }
33822 +       }
33823 +
33824 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33825 +
33826 +      out_unlocked:
33827 +       DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
33828 +                   ep->dwc_ep.is_in ? "IN" : "OUT");
33829 +       return 0;
33830 +
33831 +}
33832 +
33833 +int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
33834 +                        uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
33835 +                        int zero, void *req_handle, int atomic_alloc)
33836 +{
33837 +       int prevented = 0;
33838 +       uint64_t flags;
33839 +       dwc_otg_pcd_request_t *req;
33840 +       dwc_otg_pcd_ep_t *ep;
33841 +       uint32_t max_transfer;
33842 +
33843 +       ep = get_ep_from_handle(pcd, ep_handle);
33844 +       if ((!ep->desc && ep->dwc_ep.num != 0)) {
33845 +               DWC_WARN("bad ep\n");
33846 +               return -DWC_E_INVALID;
33847 +       }
33848 +
33849 +       if (atomic_alloc) {
33850 +               req = dwc_alloc_atomic(sizeof(*req));
33851 +       } else {
33852 +               req = dwc_alloc(sizeof(*req));
33853 +       }
33854 +
33855 +       if (!req) {
33856 +               return -DWC_E_NO_MEMORY;
33857 +       }
33858 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
33859 +       if (!GET_CORE_IF(pcd)->core_params->opt) {
33860 +               if (ep->dwc_ep.num != 0) {
33861 +                       DWC_ERROR("queue req %p, len %d buf %p\n",
33862 +                                 req_handle, buflen, buf);
33863 +               }
33864 +       }
33865 +
33866 +       req->buf = buf;
33867 +       req->dma = dma_buf;
33868 +       req->length = buflen;
33869 +       req->sent_zlp = zero;
33870 +       req->priv = req_handle;
33871 +
33872 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
33873 +
33874 +       /*
33875 +        * For EP0 IN without premature status, zlp is required?
33876 +        */
33877 +       if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
33878 +               DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
33879 +               //_req->zero = 1;
33880 +       }
33881 +
33882 +       /* Start the transfer */
33883 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
33884 +               /* EP0 Transfer? */
33885 +               if (ep->dwc_ep.num == 0) {
33886 +                       switch (pcd->ep0state) {
33887 +                       case EP0_IN_DATA_PHASE:
33888 +                               DWC_DEBUGPL(DBG_PCD,
33889 +                                           "%s ep0: EP0_IN_DATA_PHASE\n",
33890 +                                           __func__);
33891 +                               break;
33892 +
33893 +                       case EP0_OUT_DATA_PHASE:
33894 +                               DWC_DEBUGPL(DBG_PCD,
33895 +                                           "%s ep0: EP0_OUT_DATA_PHASE\n",
33896 +                                           __func__);
33897 +                               if (pcd->request_config) {
33898 +                                       /* Complete STATUS PHASE */
33899 +                                       ep->dwc_ep.is_in = 1;
33900 +                                       pcd->ep0state = EP0_IN_STATUS_PHASE;
33901 +                               }
33902 +                               break;
33903 +
33904 +                       case EP0_IN_STATUS_PHASE:
33905 +                               DWC_DEBUGPL(DBG_PCD,
33906 +                                           "%s ep0: EP0_IN_STATUS_PHASE\n",
33907 +                                           __func__);
33908 +                               break;
33909 +
33910 +                       default:
33911 +                               DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
33912 +                                           pcd->ep0state);
33913 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
33914 +                               return -DWC_E_SHUTDOWN;
33915 +                       }
33916 +
33917 +                       ep->dwc_ep.dma_addr = dma_buf;
33918 +                       ep->dwc_ep.start_xfer_buff = buf;
33919 +                       ep->dwc_ep.xfer_buff = buf;
33920 +                       ep->dwc_ep.xfer_len = buflen;
33921 +                       ep->dwc_ep.xfer_count = 0;
33922 +                       ep->dwc_ep.sent_zlp = 0;
33923 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
33924 +
33925 +                       if (zero) {
33926 +                               if ((ep->dwc_ep.xfer_len %
33927 +                                    ep->dwc_ep.maxpacket == 0)
33928 +                                   && (ep->dwc_ep.xfer_len != 0)) {
33929 +                                       ep->dwc_ep.sent_zlp = 1;
33930 +                               }
33931 +
33932 +                       }
33933 +
33934 +                       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
33935 +                                                  &ep->dwc_ep);
33936 +               }               // non-ep0 endpoints
33937 +               else {
33938 +#ifdef DWC_UTE_CFI
33939 +                       if (ep->dwc_ep.buff_mode != BM_STANDARD) {
33940 +                               /* store the request length */
33941 +                               ep->dwc_ep.cfi_req_len = buflen;
33942 +                               pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
33943 +                                                               ep, req);
33944 +               } else {
33945 +#endif
33946 +                               max_transfer =
33947 +                                   GET_CORE_IF(ep->pcd)->core_params->
33948 +                                   max_transfer_size;
33949 +
33950 +                       /* Setup and start the Transfer */
33951 +                       ep->dwc_ep.dma_addr = dma_buf;
33952 +                       ep->dwc_ep.start_xfer_buff = buf;
33953 +                       ep->dwc_ep.xfer_buff = buf;
33954 +                       ep->dwc_ep.xfer_len = 0;
33955 +                       ep->dwc_ep.xfer_count = 0;
33956 +                       ep->dwc_ep.sent_zlp = 0;
33957 +                       ep->dwc_ep.total_len = buflen;
33958 +
33959 +                       ep->dwc_ep.maxxfer = max_transfer;
33960 +                       if (GET_CORE_IF(pcd)->dma_desc_enable) {
33961 +                                       uint32_t out_max_xfer =
33962 +                                           DDMA_MAX_TRANSFER_SIZE -
33963 +                                           (DDMA_MAX_TRANSFER_SIZE % 4);
33964 +                               if (ep->dwc_ep.is_in) {
33965 +                                       if (ep->dwc_ep.maxxfer >
33966 +                                           DDMA_MAX_TRANSFER_SIZE) {
33967 +                                               ep->dwc_ep.maxxfer =
33968 +                                                   DDMA_MAX_TRANSFER_SIZE;
33969 +                                       }
33970 +                               } else {
33971 +                                               if (ep->dwc_ep.maxxfer >
33972 +                                                   out_max_xfer) {
33973 +                                               ep->dwc_ep.maxxfer =
33974 +                                                   out_max_xfer;
33975 +                                       }
33976 +                               }
33977 +                       }
33978 +                       if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
33979 +                               ep->dwc_ep.maxxfer -=
33980 +                                           (ep->dwc_ep.maxxfer %
33981 +                                            ep->dwc_ep.maxpacket);
33982 +                       }
33983 +
33984 +                       if (zero) {
33985 +                               if ((ep->dwc_ep.total_len %
33986 +                                            ep->dwc_ep.maxpacket == 0)
33987 +                                           && (ep->dwc_ep.total_len != 0)) {
33988 +                                       ep->dwc_ep.sent_zlp = 1;
33989 +                               }
33990 +                       }
33991 +#ifdef DWC_UTE_CFI
33992 +                       }
33993 +#endif
33994 +                       dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
33995 +                                                 &ep->dwc_ep);
33996 +               }
33997 +       }
33998 +
33999 +       if ((req != 0) || prevented) {
34000 +               ++pcd->request_pending;
34001 +               DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
34002 +               if (ep->dwc_ep.is_in && ep->stopped
34003 +                   && !(GET_CORE_IF(pcd)->dma_enable)) {
34004 +                       /** @todo NGS Create a function for this. */
34005 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
34006 +                       diepmsk.b.intktxfemp = 1;
34007 +                       if (GET_CORE_IF(pcd)->multiproc_int_enable) {
34008 +                               dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if->
34009 +                                                dev_global_regs->
34010 +                                                diepeachintmsk[ep->dwc_ep.num],
34011 +                                                0, diepmsk.d32);
34012 +                       } else {
34013 +                               dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if->
34014 +                                                dev_global_regs->diepmsk, 0,
34015 +                                                diepmsk.d32);
34016 +                       }
34017 +
34018 +               }
34019 +       }
34020 +
34021 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
34022 +
34023 +       return 0;
34024 +}
34025 +int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
34026 +                          void *req_handle)
34027 +{
34028 +       uint64_t flags;
34029 +       dwc_otg_pcd_request_t *req;
34030 +       dwc_otg_pcd_ep_t *ep;
34031 +
34032 +       ep = get_ep_from_handle(pcd, ep_handle);
34033 +       if (!ep->desc && ep->dwc_ep.num != 0) {
34034 +               DWC_WARN("bad argument\n");
34035 +               return -DWC_E_INVALID;
34036 +       }
34037 +
34038 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
34039 +
34040 +       /* make sure it's actually queued on this endpoint */
34041 +       DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
34042 +               if (req->priv == (void *)req_handle) {
34043 +                       break;
34044 +               }
34045 +       }
34046 +
34047 +       if (req->priv != (void *)req_handle) {
34048 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
34049 +               return -DWC_E_INVALID;
34050 +       }
34051 +
34052 +       if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
34053 +               dwc_otg_request_done(ep, req, -DWC_E_RESTART);
34054 +       } else {
34055 +               req = 0;
34056 +       }
34057 +
34058 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
34059 +
34060 +       return req ? 0 : -DWC_E_SHUTDOWN;
34061 +
34062 +}
34063 +
34064 +/**
34065 + * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests
34066 + *
34067 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
34068 + * requests. If the gadget driver clears the halt status, it will
34069 + * automatically unwedge the endpoint.
34070 + *
34071 + * Returns zero on success, else negative DWC error code.
34072 + */
34073 +int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle)
34074 +{
34075 +       dwc_otg_pcd_ep_t *ep;
34076 +       uint64_t flags;
34077 +       int retval = 0;
34078 +
34079 +       ep = get_ep_from_handle(pcd, ep_handle);
34080 +
34081 +       if ((!ep->desc && ep != &pcd->ep0) ||
34082 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
34083 +               DWC_WARN("%s, bad ep\n", __func__);
34084 +               return -DWC_E_INVALID;
34085 +       }
34086 +
34087 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
34088 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
34089 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
34090 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
34091 +               retval = -DWC_E_AGAIN;
34092 +       } else {
34093 +                /* This code needs to be reviewed */
34094 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
34095 +                       dtxfsts_data_t txstatus;
34096 +                       fifosize_data_t txfifosize;
34097 +
34098 +                       txfifosize.d32 =
34099 +                           dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs->
34100 +                                          dptxfsiz_dieptxf[ep->dwc_ep.
34101 +                                                           tx_fifo_num]);
34102 +                       txstatus.d32 =
34103 +                           dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->
34104 +                                          in_ep_regs[ep->dwc_ep.num]->dtxfsts);
34105 +
34106 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
34107 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
34108 +                               retval = -DWC_E_AGAIN;
34109 +                       } else {
34110 +                               if (ep->dwc_ep.num == 0) {
34111 +                                       pcd->ep0state = EP0_STALL;
34112 +                               }
34113 +
34114 +                               ep->stopped = 1;
34115 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
34116 +                                                    &ep->dwc_ep);
34117 +                       }
34118 +               } else {
34119 +                       if (ep->dwc_ep.num == 0) {
34120 +                               pcd->ep0state = EP0_STALL;
34121 +                       }
34122 +
34123 +                       ep->stopped = 1;
34124 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
34125 +               }
34126 +       }
34127 +
34128 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
34129 +
34130 +       return retval;
34131 +}
34132 +   
34133 +int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
34134 +{
34135 +       dwc_otg_pcd_ep_t *ep;
34136 +       uint64_t flags;
34137 +       int retval = 0;
34138 +
34139 +       ep = get_ep_from_handle(pcd, ep_handle);
34140 +
34141 +       if ((!ep->desc && ep != &pcd->ep0) ||
34142 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
34143 +               DWC_WARN("%s, bad ep\n", __func__);
34144 +               return -DWC_E_INVALID;
34145 +       }
34146 +
34147 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
34148 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
34149 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
34150 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
34151 +               retval = -DWC_E_AGAIN;
34152 +       } else if (value == 0) {
34153 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
34154 +       } else if (value == 1) {
34155 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
34156 +                       dtxfsts_data_t txstatus;
34157 +                       fifosize_data_t txfifosize;
34158 +
34159 +                       txfifosize.d32 =
34160 +                           dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs->
34161 +                                          dptxfsiz_dieptxf[ep->dwc_ep.
34162 +                                                           tx_fifo_num]);
34163 +                       txstatus.d32 =
34164 +                           dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->
34165 +                                          in_ep_regs[ep->dwc_ep.num]->dtxfsts);
34166 +
34167 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
34168 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
34169 +                               retval = -DWC_E_AGAIN;
34170 +                       } else {
34171 +                               if (ep->dwc_ep.num == 0) {
34172 +                                       pcd->ep0state = EP0_STALL;
34173 +                               }
34174 +
34175 +                               ep->stopped = 1;
34176 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
34177 +                                                    &ep->dwc_ep);
34178 +                       }
34179 +               } else {
34180 +                       if (ep->dwc_ep.num == 0) {
34181 +                               pcd->ep0state = EP0_STALL;
34182 +                       }
34183 +
34184 +                       ep->stopped = 1;
34185 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
34186 +               }
34187 +       } else if (value == 2) {
34188 +               ep->dwc_ep.stall_clear_flag = 0;
34189 +       } else if (value == 3) {
34190 +               ep->dwc_ep.stall_clear_flag = 1;
34191 +       }
34192 +
34193 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
34194 +
34195 +       return retval;
34196 +}
34197 +
34198 +/**
34199 + * This function initiates remote wakeup of the host from suspend state.
34200 + */
34201 +void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
34202 +{
34203 +       dctl_data_t dctl = { 0 };
34204 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
34205 +       dsts_data_t dsts;
34206 +
34207 +       dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
34208 +       if (!dsts.b.suspsts) {
34209 +               DWC_WARN("Remote wakeup while is not in suspend state\n");
34210 +       }
34211 +       /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
34212 +       if (pcd->remote_wakeup_enable) {
34213 +               if (set) {
34214 +                       dctl.b.rmtwkupsig = 1;
34215 +                       dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
34216 +                                        dctl, 0, dctl.d32);
34217 +                       DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
34218 +                       dwc_mdelay(2);
34219 +                       dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
34220 +                                        dctl, dctl.d32, 0);
34221 +                       DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
34222 +               }
34223 +       } else {
34224 +               DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
34225 +       }
34226 +}
34227 +
34228 +#ifdef CONFIG_USB_DWC_OTG_LPM
34229 +/**
34230 + * This function initiates remote wakeup of the host from L1 sleep state.
34231 + */
34232 +void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
34233 +{
34234 +       glpmcfg_data_t lpmcfg;
34235 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
34236 +
34237 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
34238 +
34239 +       /* Check if we are in L1 state */
34240 +       if (!lpmcfg.b.prt_sleep_sts) {
34241 +               DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
34242 +               return;
34243 +       }
34244 +
34245 +       /* Check if host allows remote wakeup */
34246 +       if (!lpmcfg.b.rem_wkup_en) {
34247 +               DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
34248 +               return;
34249 +       }
34250 +
34251 +       /* Check if Resume OK */
34252 +       if (!lpmcfg.b.sleep_state_resumeok) {
34253 +               DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
34254 +               return;
34255 +       }
34256 +
34257 +       lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
34258 +       lpmcfg.b.en_utmi_sleep = 0;
34259 +       lpmcfg.b.hird_thres &= (~(1 << 4));
34260 +       dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
34261 +
34262 +       if (set) {
34263 +               dctl_data_t dctl = {.d32 = 0 };
34264 +               dctl.b.rmtwkupsig = 1;
34265 +               /* Set RmtWkUpSig bit to start remote wakup signaling.
34266 +                * Hardware will automatically clear this bit.
34267 +                */
34268 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl,
34269 +                                0, dctl.d32);
34270 +               DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
34271 +       }
34272 +
34273 +}
34274 +#endif
34275 +
34276 +/**
34277 + * Performs remote wakeup.
34278 + */
34279 +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
34280 +{
34281 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
34282 +       if (dwc_otg_is_device_mode(core_if)) {
34283 +#ifdef CONFIG_USB_DWC_OTG_LPM
34284 +               if (core_if->lx_state == DWC_OTG_L1) {
34285 +                       dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
34286 +               } else {
34287 +#endif
34288 +                       dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
34289 +#ifdef CONFIG_USB_DWC_OTG_LPM
34290 +               }
34291 +#endif
34292 +       }
34293 +       return;
34294 +}
34295 +
34296 +int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
34297 +{
34298 +       dsts_data_t dsts;
34299 +       gotgctl_data_t gotgctl;
34300 +       uint64_t flags;
34301 +
34302 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
34303 +
34304 +       /*
34305 +        * This function starts the Protocol if no session is in progress. If
34306 +        * a session is already in progress, but the device is suspended,
34307 +        * remote wakeup signaling is started.
34308 +        */
34309 +
34310 +       /* Check if valid session */
34311 +       gotgctl.d32 =
34312 +           dwc_read_reg32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
34313 +       if (gotgctl.b.bsesvld) {
34314 +               /* Check if suspend state */
34315 +               dsts.d32 =
34316 +                   dwc_read_reg32(&
34317 +                                  (GET_CORE_IF(pcd)->dev_if->dev_global_regs->
34318 +                                   dsts));
34319 +               if (dsts.b.suspsts) {
34320 +                       dwc_otg_pcd_remote_wakeup(pcd, 1);
34321 +               }
34322 +       } else {
34323 +               dwc_otg_pcd_initiate_srp(pcd);
34324 +       }
34325 +
34326 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
34327 +       return 0;
34328 +
34329 +}
34330 +
34331 +/**
34332 + * Start the SRP timer to detect when the SRP does not complete within
34333 + * 6 seconds.
34334 + *
34335 + * @param pcd the pcd structure.
34336 + */
34337 +void dwc_otg_pcd_start_srp_timer(dwc_otg_pcd_t * pcd)
34338 +{
34339 +       GET_CORE_IF(pcd)->srp_timer_started = 1;
34340 +       DWC_TIMER_SCHEDULE(pcd->srp_timer, 6000 /* 6 secs */ );
34341 +}
34342 +
34343 +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
34344 +{
34345 +       uint32_t *addr =
34346 +           (uint32_t *) & (GET_CORE_IF(pcd)->core_global_regs->gotgctl);
34347 +       gotgctl_data_t mem;
34348 +       gotgctl_data_t val;
34349 +
34350 +       val.d32 = dwc_read_reg32(addr);
34351 +       if (val.b.sesreq) {
34352 +               DWC_ERROR("Session Request Already active!\n");
34353 +               return;
34354 +       }
34355 +
34356 +       DWC_INFO("Session Request Initated\n"); //NOTICE
34357 +       mem.d32 = dwc_read_reg32(addr);
34358 +       mem.b.sesreq = 1;
34359 +       dwc_write_reg32(addr, mem.d32);
34360 +
34361 +       /* Start the SRP timer */
34362 +       dwc_otg_pcd_start_srp_timer(pcd);
34363 +       return;
34364 +}
34365 +
34366 +int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
34367 +{
34368 +       return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
34369 +}
34370 +
34371 +int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
34372 +{
34373 +       return GET_CORE_IF(pcd)->core_params->lpm_enable;
34374 +}
34375 +
34376 +uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
34377 +{
34378 +       return pcd->b_hnp_enable;
34379 +}
34380 +
34381 +uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
34382 +{
34383 +       return pcd->a_hnp_support;
34384 +}
34385 +
34386 +uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
34387 +{
34388 +       return pcd->a_alt_hnp_support;
34389 +}
34390 +
34391 +int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
34392 +{
34393 +       return pcd->remote_wakeup_enable;
34394 +}
34395 +
34396 +#endif                         /* DWC_HOST_ONLY */
34397 --- /dev/null
34398 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
34399 @@ -0,0 +1,216 @@
34400 +/* ==========================================================================
34401 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
34402 + * $Revision: #39 $
34403 + * $Date: 2008/12/16 $
34404 + * $Change: 1153731 $
34405 + *
34406 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
34407 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
34408 + * otherwise expressly agreed to in writing between Synopsys and you.
34409 + *
34410 + * The Software IS NOT an item of Licensed Software or Licensed Product under
34411 + * any End User Software License Agreement or Agreement for Licensed Product
34412 + * with Synopsys or any supplement thereto. You are permitted to use and
34413 + * redistribute this Software in source and binary forms, with or without
34414 + * modification, provided that redistributions of source code must retain this
34415 + * notice. You may not view, use, disclose, copy or distribute this file or
34416 + * any information contained herein except pursuant to this license grant from
34417 + * Synopsys. If you do not agree with this notice, including the disclaimer
34418 + * below, then you are not authorized to use the Software.
34419 + *
34420 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
34421 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34422 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34423 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
34424 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34425 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34426 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34427 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34428 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34429 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34430 + * DAMAGE.
34431 + * ========================================================================== */
34432 +#ifndef DWC_HOST_ONLY
34433 +#if !defined(__DWC_PCD_H__)
34434 +#define __DWC_PCD_H__
34435 +
34436 +#include "usb.h"
34437 +#include "dwc_otg_cil.h"
34438 +#include "dwc_otg_pcd_if.h"
34439 +struct cfiobject;
34440 +
34441 +/**
34442 + * @file
34443 + *
34444 + * This file contains the structures, constants, and interfaces for
34445 + * the Perpherial Contoller Driver (PCD).
34446 + *
34447 + * The Peripheral Controller Driver (PCD) for Linux will implement the
34448 + * Gadget API, so that the existing Gadget drivers can be used.         For
34449 + * the Mass Storage Function driver the File-backed USB Storage Gadget
34450 + * (FBS) driver will be used.  The FBS driver supports the
34451 + * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
34452 + * transports.
34453 + *
34454 + */
34455 +
34456 +/** Max Transfer size for any EP */
34457 +#define DDMA_MAX_TRANSFER_SIZE 65535
34458 +
34459 +/** Max DMA Descriptor count for any EP */
34460 +#define MAX_DMA_DESC_CNT 64
34461 +
34462 +/**
34463 + * Get the pointer to the core_if from the pcd pointer.
34464 + */
34465 +#define GET_CORE_IF( _pcd ) (_pcd->core_if)
34466 +
34467 +/**
34468 + * States of EP0.
34469 + */
34470 +typedef enum ep0_state {
34471 +       EP0_DISCONNECT,         /* no host */
34472 +       EP0_IDLE,
34473 +       EP0_IN_DATA_PHASE,
34474 +       EP0_OUT_DATA_PHASE,
34475 +       EP0_IN_STATUS_PHASE,
34476 +       EP0_OUT_STATUS_PHASE,
34477 +       EP0_STALL,
34478 +} ep0state_e;
34479 +
34480 +/** Fordward declaration.*/
34481 +struct dwc_otg_pcd;
34482 +
34483 +/** DWC_otg iso request structure.
34484 + *
34485 + */
34486 +typedef struct usb_iso_request dwc_otg_pcd_iso_request_t;
34487 +
34488 +/** DWC_otg request structure.
34489 + * This structure is a list of requests.
34490 + */
34491 +typedef struct dwc_otg_pcd_request {
34492 +       void *priv;
34493 +       void *buf;
34494 +       dwc_dma_t dma;
34495 +       uint32_t length;
34496 +       uint32_t actual;
34497 +       unsigned sent_zlp:1;
34498 +
34499 +        DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;
34500 +} dwc_otg_pcd_request_t;
34501 +
34502 +DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request);
34503 +
34504 +/**      PCD EP structure.
34505 + * This structure describes an EP, there is an array of EPs in the PCD
34506 + * structure.
34507 + */
34508 +typedef struct dwc_otg_pcd_ep {
34509 +       /** USB EP Descriptor */
34510 +       const usb_endpoint_descriptor_t *desc;
34511 +
34512 +       /** queue of dwc_otg_pcd_requests. */
34513 +       struct req_list queue;
34514 +       unsigned stopped:1;
34515 +       unsigned disabling:1;
34516 +       unsigned dma:1;
34517 +       unsigned queue_sof:1;
34518 +
34519 +#ifdef DWC_EN_ISOC
34520 +       /** ISOC req handle passed */
34521 +       void *iso_req_handle;
34522 +#endif                         //_EN_ISOC_
34523 +
34524 +       /** DWC_otg ep data. */
34525 +       dwc_ep_t dwc_ep;
34526 +
34527 +       /** Pointer to PCD */
34528 +       struct dwc_otg_pcd *pcd;
34529 +
34530 +       void *priv;
34531 +} dwc_otg_pcd_ep_t;
34532 +
34533 +/** DWC_otg PCD Structure.
34534 + * This structure encapsulates the data for the dwc_otg PCD.
34535 + */
34536 +struct dwc_otg_pcd {
34537 +       const struct dwc_otg_pcd_function_ops *fops;
34538 +       /** Core Interface */
34539 +       dwc_otg_core_if_t *core_if;
34540 +       /** State of EP0 */
34541 +       ep0state_e ep0state;
34542 +       /** EP0 Request is pending */
34543 +       unsigned ep0_pending:1;
34544 +       /** Indicates when SET CONFIGURATION Request is in process */
34545 +       unsigned request_config:1;
34546 +       /** The state of the Remote Wakeup Enable. */
34547 +       unsigned remote_wakeup_enable:1;
34548 +       /** The state of the B-Device HNP Enable. */
34549 +       unsigned b_hnp_enable:1;
34550 +       /** The state of A-Device HNP Support. */
34551 +       unsigned a_hnp_support:1;
34552 +       /** The state of the A-Device Alt HNP support. */
34553 +       unsigned a_alt_hnp_support:1;
34554 +       /** Count of pending Requests */
34555 +       unsigned request_pending;
34556 +
34557 +       /** SETUP packet for EP0
34558 +        * This structure is allocated as a DMA buffer on PCD initialization
34559 +        * with enough space for up to 3 setup packets.
34560 +        */
34561 +       union {
34562 +               usb_device_request_t req;
34563 +               uint32_t d32[2];
34564 +       } *setup_pkt;
34565 +
34566 +       dwc_dma_t setup_pkt_dma_handle;
34567 +
34568 +       /** 2-byte dma buffer used to return status from GET_STATUS */
34569 +       uint16_t *status_buf;
34570 +       dwc_dma_t status_buf_dma_handle;
34571 +
34572 +       /** EP0 */
34573 +       dwc_otg_pcd_ep_t ep0;
34574 +
34575 +       /** Array of IN EPs. */
34576 +       dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];
34577 +       /** Array of OUT EPs. */
34578 +       dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];
34579 +       /** number of valid EPs in the above array. */
34580 +//        unsigned      num_eps : 4;
34581 +       dwc_spinlock_t *lock;
34582 +       /** Timer for SRP. If it expires before SRP is successful
34583 +        * clear the SRP. */
34584 +       dwc_timer_t *srp_timer;
34585 +
34586 +       /** Tasklet to defer starting of TEST mode transmissions until
34587 +        *      Status Phase has been completed.
34588 +        */
34589 +       dwc_tasklet_t *test_mode_tasklet;
34590 +
34591 +       /** Tasklet to delay starting of xfer in DMA mode */
34592 +       dwc_tasklet_t *start_xfer_tasklet;
34593 +
34594 +       /** The test mode to enter when the tasklet is executed. */
34595 +       unsigned test_mode;
34596 +       /** The cfi_api structure that implements most of the CFI API
34597 +        * and OTG specific core configuration functionality 
34598 +        */
34599 +#ifdef DWC_UTE_CFI
34600 +       struct cfiobject *cfi;
34601 +#endif
34602 +
34603 +};
34604 +
34605 +//FIXME this functions should be static, and this prototypes should be removed
34606 +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep);
34607 +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep,
34608 +                                dwc_otg_pcd_request_t * req, int32_t status);
34609 +
34610 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
34611 +                            void *req_handle);
34612 +
34613 +extern void do_test_mode(void *data);
34614 +#endif
34615 +#endif                         /* DWC_HOST_ONLY */
34616 --- /dev/null
34617 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
34618 @@ -0,0 +1,333 @@
34619 +/* ==========================================================================
34620 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
34621 + * $Revision: #6 $
34622 + * $Date: 2009/04/03 $
34623 + * $Change: 1225059 $
34624 + *
34625 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
34626 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
34627 + * otherwise expressly agreed to in writing between Synopsys and you.
34628 + *
34629 + * The Software IS NOT an item of Licensed Software or Licensed Product under
34630 + * any End User Software License Agreement or Agreement for Licensed Product
34631 + * with Synopsys or any supplement thereto. You are permitted to use and
34632 + * redistribute this Software in source and binary forms, with or without
34633 + * modification, provided that redistributions of source code must retain this
34634 + * notice. You may not view, use, disclose, copy or distribute this file or
34635 + * any information contained herein except pursuant to this license grant from
34636 + * Synopsys. If you do not agree with this notice, including the disclaimer
34637 + * below, then you are not authorized to use the Software.
34638 + *
34639 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
34640 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34641 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34642 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
34643 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34644 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34645 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34646 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34647 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34648 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34649 + * DAMAGE.
34650 + * ========================================================================== */
34651 +#ifndef DWC_HOST_ONLY
34652 +
34653 +#if !defined(__DWC_PCD_IF_H__)
34654 +#define __DWC_PCD_IF_H__
34655 +
34656 +#include "dwc_os.h"
34657 +#include "dwc_otg_core_if.h"
34658 +
34659 +/** @file 
34660 + * This file defines DWC_OTG PCD Core API.
34661 + */
34662 +
34663 +struct dwc_otg_pcd;
34664 +typedef struct dwc_otg_pcd dwc_otg_pcd_t;
34665 +
34666 +/** Maxpacket size for EP0 */
34667 +#define MAX_EP0_SIZE   64
34668 +/** Maxpacket size for any EP */
34669 +#define MAX_PACKET_SIZE 1024
34670 +
34671 +/** @name Function Driver Callbacks */
34672 +/** @{ */
34673 +
34674 +/** This function will be called whenever a previously queued request has
34675 + * completed.  The status value will be set to -DWC_E_SHUTDOWN to indicated a
34676 + * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset,
34677 + * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid
34678 + * parameters. */
34679 +typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
34680 +                                   void *req_handle, int32_t status,
34681 +                                   uint32_t actual);
34682 +/**
34683 + * This function will be called whenever a previousle queued ISOC request has
34684 + * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count
34685 + * function.
34686 + * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_*
34687 + * functions.
34688 + */
34689 +typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
34690 +                                        void *req_handle, int proc_buf_num);
34691 +/** This function should handle any SETUP request that cannot be handled by the
34692 + * PCD Core.  This includes most GET_DESCRIPTORs, SET_CONFIGS, Any
34693 + * class-specific requests, etc.  The function must non-blocking.
34694 + *
34695 + * Returns 0 on success.
34696 + * Returns -DWC_E_NOT_SUPPORTED if the request is not supported.
34697 + * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes.
34698 + * Returns -DWC_E_SHUTDOWN on any other error. */
34699 +typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes);
34700 +/** This is called whenever the device has been disconnected.  The function
34701 + * driver should take appropriate action to clean up all pending requests in the
34702 + * PCD Core, remove all endpoints (except ep0), and initialize back to reset
34703 + * state. */
34704 +typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd);
34705 +/** This function is called when device has been connected. */
34706 +typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed);
34707 +/** This function is called when device has been suspended */
34708 +typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd);
34709 +/** This function is called when device has received LPM tokens, i.e.
34710 + * device has been sent to sleep state. */
34711 +typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd);
34712 +/** This function is called when device has been resumed
34713 + * from suspend(L2) or L1 sleep state. */
34714 +typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd);
34715 +/** This function is called whenever hnp params has been changed.
34716 + * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions
34717 + * to get hnp parameters. */
34718 +typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd);
34719 +/** This function is called whenever USB RESET is detected. */
34720 +typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd);
34721 +
34722 +typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes);
34723 +
34724 +/** Function Driver Ops Data Structure */
34725 +struct dwc_otg_pcd_function_ops {
34726 +       dwc_connect_cb_t connect;
34727 +       dwc_disconnect_cb_t disconnect;
34728 +       dwc_setup_cb_t setup;
34729 +       dwc_completion_cb_t complete;
34730 +       dwc_isoc_completion_cb_t isoc_complete;
34731 +       dwc_suspend_cb_t suspend;
34732 +       dwc_sleep_cb_t sleep;
34733 +       dwc_resume_cb_t resume;
34734 +       dwc_reset_cb_t reset;
34735 +       dwc_hnp_params_changed_cb_t hnp_changed;
34736 +       cfi_setup_cb_t cfi_setup;
34737 +};
34738 +/** @} */
34739 +
34740 +/** @name Function Driver Functions */
34741 +/** @{ */
34742 +
34743 +/** Call this function to get pointer on dwc_otg_pcd_t,
34744 + * this pointer will be used for all PCD API functions.
34745 + *
34746 + * @param core_if The DWC_OTG Core
34747 + */
34748 +extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);
34749 +
34750 +/** Frees PCD allocated by dwc_otg_pcd_init
34751 + *
34752 + * @param pcd The PCD
34753 + */
34754 +extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd);
34755 +
34756 +/** Call this to bind the function driver to the PCD Core.
34757 + *
34758 + * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function.
34759 + * @param fops The Function Driver Ops data structure containing pointers to all callbacks.
34760 + */
34761 +extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
34762 +                             const struct dwc_otg_pcd_function_ops *fops);
34763 +
34764 +/** Enables an endpoint for use.  This function enables an endpoint in
34765 + * the PCD.  The endpoint is described by the ep_desc which has the
34766 + * same format as a USB ep descriptor.  The ep_handle parameter is used to refer
34767 + * to the endpoint from other API functions and in callbacks.  Normally this
34768 + * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the
34769 + * core for that interface.
34770 + *
34771 + * Returns -DWC_E_INVALID if invalid parameters were passed.
34772 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
34773 + * Returns 0 on success.
34774 + *
34775 + * @param pcd The PCD
34776 + * @param ep_desc Endpoint descriptor
34777 + * @param ep_handle Handle on endpoint, that will be used to identify endpoint.
34778 + */
34779 +extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
34780 +                                const uint8_t * ep_desc, void *ep_handle);
34781 +
34782 +/** Disable the endpoint referenced by ep_handle.
34783 + *
34784 + * Returns -DWC_E_INVALID if invalid parameters were passed.
34785 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
34786 + * Returns 0 on success. */
34787 +extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);
34788 +
34789 +/** Queue a data transfer request on the endpoint referenced by ep_handle.
34790 + * After the transfer is completes, the complete callback will be called with
34791 + * the request status.
34792 + *
34793 + * @param pcd The PCD
34794 + * @param ep_handle The handle of the endpoint
34795 + * @param buf The buffer for the data
34796 + * @param dma_buf The DMA buffer for the data
34797 + * @param buflen The length of the data transfer
34798 + * @param zero Specifies whether to send zero length last packet.
34799 + * @param req_handle Set this handle to any value to use to reference this
34800 + * request in the ep_dequeue function or from the complete callback
34801 + * @param atomic_alloc If driver need to perform atomic allocations
34802 + * for internal data structures.
34803 + *
34804 + * Returns -DWC_E_INVALID if invalid parameters were passed.
34805 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
34806 + * Returns 0 on success. */
34807 +extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
34808 +                               uint8_t * buf, dwc_dma_t dma_buf,
34809 +                               uint32_t buflen, int zero, void *req_handle,
34810 +                               int atomic_alloc);
34811 +
34812 +/** De-queue the specified data transfer that has not yet completed.
34813 + *
34814 + * Returns -DWC_E_INVALID if invalid parameters were passed.
34815 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
34816 + * Returns 0 on success. */
34817 +extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
34818 +                                 void *req_handle);
34819 +
34820 +/** Halt (STALL) an endpoint or clear it.
34821 + *
34822 + * Returns -DWC_E_INVALID if invalid parameters were passed.
34823 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
34824 + * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later
34825 + * Returns 0 on success. */
34826 +extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value);
34827 +
34828 +/** This function */
34829 +extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle);
34830 +
34831 +/** This function should be called on every hardware interrupt */
34832 +extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);
34833 +
34834 +/** This function returns current frame number */
34835 +extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd);
34836 +
34837 +/**
34838 + * Start isochronous transfers on the endpoint referenced by ep_handle.
34839 + * For isochronous transfers duble buffering is used.
34840 + * After processing each of buffers comlete callback will be called with
34841 + * status for each transaction.
34842 + *
34843 + * @param pcd The PCD
34844 + * @param ep_handle The handle of the endpoint
34845 + * @param buf0 The virtual address of first data buffer
34846 + * @param buf1 The virtual address of second data buffer
34847 + * @param dma0 The DMA address of first data buffer
34848 + * @param dma1 The DMA address of second data buffer
34849 + * @param sync_frame Data pattern frame number
34850 + * @param dp_frame Data size for pattern frame
34851 + * @param data_per_frame Data size for regular frame
34852 + * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP.
34853 + * @param buf_proc_intrvl Interval of ISOC Buffer processing
34854 + * @param req_handle Handle of ISOC request
34855 + * @param atomic_alloc Specefies whether to perform atomic allocation for
34856 + *                     internal data structures.
34857 + *
34858 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
34859 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function.
34860 + * Returns -DW_E_SHUTDOWN for any other error.
34861 + * Returns 0 on success
34862 + */
34863 +extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
34864 +                                   uint8_t * buf0, uint8_t * buf1,
34865 +                                   dwc_dma_t dma0, dwc_dma_t dma1,
34866 +                                   int sync_frame, int dp_frame,
34867 +                                   int data_per_frame, int start_frame,
34868 +                                   int buf_proc_intrvl, void *req_handle,
34869 +                                   int atomic_alloc);
34870 +
34871 +/** Stop ISOC transfers on endpoint referenced by ep_handle.
34872 + *
34873 + * @param pcd The PCD
34874 + * @param ep_handle The handle of the endpoint
34875 + * @param req_handle Handle of ISOC request
34876 + *
34877 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function
34878 + * Returns 0 on success
34879 + */
34880 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
34881 +                           void *req_handle);
34882 +
34883 +/** Get ISOC packet status.
34884 + *
34885 + * @param pcd The PCD
34886 + * @param ep_handle The handle of the endpoint
34887 + * @param iso_req_handle Isochronoush request handle
34888 + * @param packet Number of packet
34889 + * @param status Out parameter for returning status
34890 + * @param actual Out parameter for returning actual length
34891 + * @param offset Out parameter for returning offset
34892 + *
34893 + */
34894 +extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd,
34895 +                                             void *ep_handle,
34896 +                                             void *iso_req_handle, int packet,
34897 +                                             int *status, int *actual,
34898 +                                             int *offset);
34899 +
34900 +/** Get ISOC packet count.
34901 + *
34902 + * @param pcd The PCD
34903 + * @param ep_handle The handle of the endpoint
34904 + * @param iso_req_handle
34905 + */
34906 +extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd,
34907 +                                           void *ep_handle,
34908 +                                           void *iso_req_handle);
34909 +
34910 +/** This function starts the SRP Protocol if no session is in progress. If
34911 + * a session is already in progress, but the device is suspended,
34912 + * remote wakeup signaling is started.
34913 + */
34914 +extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd);
34915 +
34916 +/** This function returns 1 if LPM support is enabled, and 0 otherwise. */
34917 +extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd);
34918 +
34919 +/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */
34920 +extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd);
34921 +
34922 +/** Initiate SRP */
34923 +extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd);
34924 +
34925 +/** Starts remote wakeup signaling. */
34926 +extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set);
34927 +
34928 +/** This function returns whether device is dualspeed.*/
34929 +extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd);
34930 +
34931 +/** This function returns whether device is otg. */
34932 +extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd);
34933 +
34934 +/** These functions allow to get hnp parameters */
34935 +extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd);
34936 +extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd);
34937 +extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd);
34938 +
34939 +/** CFI specific Interface functions */
34940 +/** Allocate a cfi buffer */
34941 +extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep,
34942 +                                    dwc_dma_t * addr, size_t buflen,
34943 +                                    int flags);
34944 +
34945 +/******************************************************************************/
34946 +
34947 +/** @} */
34948 +
34949 +#endif                         /* __DWC_PCD_IF_H__ */
34950 +
34951 +#endif                         /* DWC_HOST_ONLY */
34952 --- /dev/null
34953 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
34954 @@ -0,0 +1,4077 @@
34955 +/* ==========================================================================
34956 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
34957 + * $Revision: #93 $
34958 + * $Date: 2009/04/02 $
34959 + * $Change: 1224216 $
34960 + *
34961 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
34962 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
34963 + * otherwise expressly agreed to in writing between Synopsys and you.
34964 + *
34965 + * The Software IS NOT an item of Licensed Software or Licensed Product under
34966 + * any End User Software License Agreement or Agreement for Licensed Product
34967 + * with Synopsys or any supplement thereto. You are permitted to use and
34968 + * redistribute this Software in source and binary forms, with or without
34969 + * modification, provided that redistributions of source code must retain this
34970 + * notice. You may not view, use, disclose, copy or distribute this file or
34971 + * any information contained herein except pursuant to this license grant from
34972 + * Synopsys. If you do not agree with this notice, including the disclaimer
34973 + * below, then you are not authorized to use the Software.
34974 + *
34975 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
34976 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34977 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34978 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
34979 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34980 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34981 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34982 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34983 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34984 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34985 + * DAMAGE.
34986 + * ========================================================================== */
34987 +#ifndef DWC_HOST_ONLY
34988 +
34989 +#include "dwc_otg_pcd.h"
34990 +
34991 +#ifdef DWC_UTE_CFI
34992 +#include "dwc_otg_cfi.h"
34993 +#endif
34994 +
34995 +//#define PRINT_CFI_DMA_DESCS
34996 +
34997 +#define DEBUG_EP0
34998 +
34999 +/**
35000 + * This function updates OTG.
35001 + */
35002 +static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
35003 +{
35004 +
35005 +       if (reset) {
35006 +               pcd->b_hnp_enable = 0;
35007 +               pcd->a_hnp_support = 0;
35008 +               pcd->a_alt_hnp_support = 0;
35009 +       }
35010 +
35011 +       if (pcd->fops->hnp_changed) {
35012 +               pcd->fops->hnp_changed(pcd);
35013 +       }
35014 +}
35015 +
35016 +/** @file
35017 + * This file contains the implementation of the PCD Interrupt handlers.
35018 + *
35019 + * The PCD handles the device interrupts.  Many conditions can cause a
35020 + * device interrupt. When an interrupt occurs, the device interrupt
35021 + * service routine determines the cause of the interrupt and
35022 + * dispatches handling to the appropriate function. These interrupt
35023 + * handling functions are described below.
35024 + * All interrupt registers are processed from LSB to MSB.
35025 + */
35026 +
35027 +/**
35028 + * This function prints the ep0 state for debug purposes.
35029 + */
35030 +static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
35031 +{
35032 +#ifdef DEBUG
35033 +       char str[40];
35034 +
35035 +       switch (pcd->ep0state) {
35036 +       case EP0_DISCONNECT:
35037 +               dwc_strcpy(str, "EP0_DISCONNECT");
35038 +               break;
35039 +       case EP0_IDLE:
35040 +               dwc_strcpy(str, "EP0_IDLE");
35041 +               break;
35042 +       case EP0_IN_DATA_PHASE:
35043 +               dwc_strcpy(str, "EP0_IN_DATA_PHASE");
35044 +               break;
35045 +       case EP0_OUT_DATA_PHASE:
35046 +               dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
35047 +               break;
35048 +       case EP0_IN_STATUS_PHASE:
35049 +               dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
35050 +               break;
35051 +       case EP0_OUT_STATUS_PHASE:
35052 +               dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
35053 +               break;
35054 +       case EP0_STALL:
35055 +               dwc_strcpy(str, "EP0_STALL");
35056 +               break;
35057 +       default:
35058 +               dwc_strcpy(str, "EP0_INVALID");
35059 +       }
35060 +
35061 +       DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
35062 +#endif
35063 +}
35064 +
35065 +#ifdef DWC_UTE_CFI
35066 +static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
35067 +                             const uint8_t * epname, int descnum)
35068 +{
35069 +       CFI_INFO
35070 +           ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
35071 +            epname, descnum, ddesc->buf, ddesc->status.b.bytes,
35072 +            ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
35073 +            ddesc->status.b.bs);
35074 +}
35075 +#endif
35076 +
35077 +/**
35078 + * This function returns pointer to in ep struct with number ep_num
35079 + */
35080 +static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
35081 +{
35082 +       int i;
35083 +       int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
35084 +       if (ep_num == 0) {
35085 +               return &pcd->ep0;
35086 +       } else {
35087 +               for (i = 0; i < num_in_eps; ++i) {
35088 +                       if (pcd->in_ep[i].dwc_ep.num == ep_num)
35089 +                               return &pcd->in_ep[i];
35090 +               }
35091 +               return 0;
35092 +       }
35093 +}
35094 +
35095 +/**
35096 + * This function returns pointer to out ep struct with number ep_num
35097 + */
35098 +static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
35099 +{
35100 +       int i;
35101 +       int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
35102 +       if (ep_num == 0) {
35103 +               return &pcd->ep0;
35104 +       } else {
35105 +               for (i = 0; i < num_out_eps; ++i) {
35106 +                       if (pcd->out_ep[i].dwc_ep.num == ep_num)
35107 +                               return &pcd->out_ep[i];
35108 +               }
35109 +               return 0;
35110 +       }
35111 +}
35112 +
35113 +/**
35114 + * This functions gets a pointer to an EP from the wIndex address
35115 + * value of the control request.
35116 + */
35117 +dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
35118 +{
35119 +       dwc_otg_pcd_ep_t *ep;
35120 +       uint32_t ep_num = UE_GET_ADDR(wIndex);
35121 +
35122 +       if (ep_num == 0) {
35123 +               ep = &pcd->ep0;
35124 +       } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) {   /* in ep */
35125 +               ep = &pcd->in_ep[ep_num - 1];
35126 +       } else {
35127 +               ep = &pcd->out_ep[ep_num - 1];
35128 +       }
35129 +
35130 +       return ep;
35131 +}
35132 +
35133 +/**
35134 + * This function checks the EP request queue, if the queue is not
35135 + * empty the next request is started.
35136 + */
35137 +void start_next_request(dwc_otg_pcd_ep_t * ep)
35138 +{
35139 +       dwc_otg_pcd_request_t *req = 0;
35140 +       uint32_t max_transfer =
35141 +           GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
35142 +
35143 +#ifdef DWC_UTE_CFI
35144 +       struct dwc_otg_pcd *pcd;
35145 +       pcd = ep->pcd;
35146 +#endif
35147 +
35148 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
35149 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
35150 +
35151 +#ifdef DWC_UTE_CFI
35152 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
35153 +                       ep->dwc_ep.cfi_req_len = req->length;
35154 +                       pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
35155 +               } else {
35156 +#endif
35157 +               /* Setup and start the Transfer */
35158 +               ep->dwc_ep.dma_addr = req->dma;
35159 +               ep->dwc_ep.start_xfer_buff = req->buf;
35160 +               ep->dwc_ep.xfer_buff = req->buf;
35161 +               ep->dwc_ep.sent_zlp = 0;
35162 +               ep->dwc_ep.total_len = req->length;
35163 +               ep->dwc_ep.xfer_len = 0;
35164 +               ep->dwc_ep.xfer_count = 0;
35165 +
35166 +               ep->dwc_ep.maxxfer = max_transfer;
35167 +               if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
35168 +                       uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
35169 +                           - (DDMA_MAX_TRANSFER_SIZE % 4);
35170 +                       if (ep->dwc_ep.is_in) {
35171 +                                       if (ep->dwc_ep.maxxfer >
35172 +                                           DDMA_MAX_TRANSFER_SIZE) {
35173 +                                       ep->dwc_ep.maxxfer =
35174 +                                           DDMA_MAX_TRANSFER_SIZE;
35175 +                               }
35176 +                       } else {
35177 +                               if (ep->dwc_ep.maxxfer > out_max_xfer) {
35178 +                                               ep->dwc_ep.maxxfer =
35179 +                                                   out_max_xfer;
35180 +                               }
35181 +                       }
35182 +               }
35183 +               if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
35184 +                       ep->dwc_ep.maxxfer -=
35185 +                           (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
35186 +               }
35187 +               if (req->sent_zlp) {
35188 +                               if ((ep->dwc_ep.total_len %
35189 +                                    ep->dwc_ep.maxpacket == 0)
35190 +                                   && (ep->dwc_ep.total_len != 0)) {
35191 +                               ep->dwc_ep.sent_zlp = 1;
35192 +                       }
35193 +
35194 +               }
35195 +#ifdef DWC_UTE_CFI
35196 +               }
35197 +#endif
35198 +               dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
35199 +       }
35200 +}
35201 +
35202 +/**
35203 + * This function handles the SOF Interrupts. At this time the SOF
35204 + * Interrupt is disabled.
35205 + */
35206 +int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
35207 +{
35208 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
35209 +
35210 +       gintsts_data_t gintsts;
35211 +
35212 +       DWC_DEBUGPL(DBG_PCD, "SOF\n");
35213 +
35214 +       /* Clear interrupt */
35215 +       gintsts.d32 = 0;
35216 +       gintsts.b.sofintr = 1;
35217 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
35218 +
35219 +       return 1;
35220 +}
35221 +
35222 +/**
35223 + * This function handles the Rx Status Queue Level Interrupt, which
35224 + * indicates that there is a least one packet in the Rx FIFO.  The
35225 + * packets are moved from the FIFO to memory, where they will be
35226 + * processed when the Endpoint Interrupt Register indicates Transfer
35227 + * Complete or SETUP Phase Done.
35228 + *
35229 + * Repeat the following until the Rx Status Queue is empty:
35230 + *      -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
35231 + *             info
35232 + *      -# If Receive FIFO is empty then skip to step Clear the interrupt
35233 + *             and exit
35234 + *      -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
35235 + *             SETUP data to the buffer
35236 + *      -# If OUT Data Packet call dwc_otg_read_packet to copy the data
35237 + *             to the destination buffer
35238 + */
35239 +int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
35240 +{
35241 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
35242 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
35243 +       gintmsk_data_t gintmask = {.d32 = 0 };
35244 +       device_grxsts_data_t status;
35245 +       dwc_otg_pcd_ep_t *ep;
35246 +       gintsts_data_t gintsts;
35247 +#ifdef DEBUG
35248 +       static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
35249 +#endif
35250 +
35251 +       //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
35252 +       /* Disable the Rx Status Queue Level interrupt */
35253 +       gintmask.b.rxstsqlvl = 1;
35254 +       dwc_modify_reg32(&global_regs->gintmsk, gintmask.d32, 0);
35255 +
35256 +       /* Get the Status from the top of the FIFO */
35257 +       status.d32 = dwc_read_reg32(&global_regs->grxstsp);
35258 +
35259 +       DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
35260 +                   "pktsts:%x Frame:%d(0x%0x)\n",
35261 +                   status.b.epnum, status.b.bcnt,
35262 +                   dpid_str[status.b.dpid],
35263 +                   status.b.pktsts, status.b.fn, status.b.fn);
35264 +       /* Get pointer to EP structure */
35265 +       ep = get_out_ep(pcd, status.b.epnum);
35266 +
35267 +       switch (status.b.pktsts) {
35268 +       case DWC_DSTS_GOUT_NAK:
35269 +               DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
35270 +               break;
35271 +       case DWC_STS_DATA_UPDT:
35272 +               DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
35273 +               if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
35274 +                       /** @todo NGS Check for buffer overflow? */
35275 +                       dwc_otg_read_packet(core_if,
35276 +                                           ep->dwc_ep.xfer_buff,
35277 +                                           status.b.bcnt);
35278 +                       ep->dwc_ep.xfer_count += status.b.bcnt;
35279 +                       ep->dwc_ep.xfer_buff += status.b.bcnt;
35280 +               }
35281 +               break;
35282 +       case DWC_STS_XFER_COMP:
35283 +               DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
35284 +               break;
35285 +       case DWC_DSTS_SETUP_COMP:
35286 +#ifdef DEBUG_EP0
35287 +               DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
35288 +#endif
35289 +               break;
35290 +       case DWC_DSTS_SETUP_UPDT:
35291 +               dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
35292 +#ifdef DEBUG_EP0
35293 +               DWC_DEBUGPL(DBG_PCD,
35294 +                           "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
35295 +                           pcd->setup_pkt->req.bmRequestType,
35296 +                           pcd->setup_pkt->req.bRequest,
35297 +                           UGETW(pcd->setup_pkt->req.wValue),
35298 +                           UGETW(pcd->setup_pkt->req.wIndex),
35299 +                           UGETW(pcd->setup_pkt->req.wLength));
35300 +#endif
35301 +               ep->dwc_ep.xfer_count += status.b.bcnt;
35302 +               break;
35303 +       default:
35304 +               DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
35305 +                           status.b.pktsts);
35306 +               break;
35307 +       }
35308 +
35309 +       /* Enable the Rx Status Queue Level interrupt */
35310 +       dwc_modify_reg32(&global_regs->gintmsk, 0, gintmask.d32);
35311 +       /* Clear interrupt */
35312 +       gintsts.d32 = 0;
35313 +       gintsts.b.rxstsqlvl = 1;
35314 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
35315 +
35316 +       //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
35317 +       return 1;
35318 +}
35319 +
35320 +/**
35321 + * This function examines the Device IN Token Learning Queue to
35322 + * determine the EP number of the last IN token received.  This
35323 + * implementation is for the Mass Storage device where there are only
35324 + * 2 IN EPs (Control-IN and BULK-IN).
35325 + *
35326 + * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
35327 + * are 8 EP Numbers in each of the other possible DTKNQ Registers.
35328 + *
35329 + * @param core_if Programming view of DWC_otg controller.
35330 + *
35331 + */
35332 +static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
35333 +{
35334 +       dwc_otg_device_global_regs_t *dev_global_regs =
35335 +           core_if->dev_if->dev_global_regs;
35336 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
35337 +       /* Number of Token Queue Registers */
35338 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
35339 +       dtknq1_data_t dtknqr1;
35340 +       uint32_t in_tkn_epnums[4];
35341 +       int ndx = 0;
35342 +       int i = 0;
35343 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
35344 +       int epnum = 0;
35345 +
35346 +       //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
35347 +
35348 +       /* Read the DTKNQ Registers */
35349 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
35350 +               in_tkn_epnums[i] = dwc_read_reg32(addr);
35351 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
35352 +                           in_tkn_epnums[i]);
35353 +               if (addr == &dev_global_regs->dvbusdis) {
35354 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
35355 +               } else {
35356 +                       ++addr;
35357 +               }
35358 +
35359 +       }
35360 +
35361 +       /* Copy the DTKNQR1 data to the bit field. */
35362 +       dtknqr1.d32 = in_tkn_epnums[0];
35363 +       /* Get the EP numbers */
35364 +       in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
35365 +       ndx = dtknqr1.b.intknwptr - 1;
35366 +
35367 +       //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
35368 +       if (ndx == -1) {
35369 +               /** @todo Find a simpler way to calculate the max
35370 +                * queue position.*/
35371 +               int cnt = TOKEN_Q_DEPTH;
35372 +               if (TOKEN_Q_DEPTH <= 6) {
35373 +                       cnt = TOKEN_Q_DEPTH - 1;
35374 +               } else if (TOKEN_Q_DEPTH <= 14) {
35375 +                       cnt = TOKEN_Q_DEPTH - 7;
35376 +               } else if (TOKEN_Q_DEPTH <= 22) {
35377 +                       cnt = TOKEN_Q_DEPTH - 15;
35378 +               } else {
35379 +                       cnt = TOKEN_Q_DEPTH - 23;
35380 +               }
35381 +               epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
35382 +       } else {
35383 +               if (ndx <= 5) {
35384 +                       epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
35385 +               } else if (ndx <= 13) {
35386 +                       ndx -= 6;
35387 +                       epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
35388 +               } else if (ndx <= 21) {
35389 +                       ndx -= 14;
35390 +                       epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
35391 +               } else if (ndx <= 29) {
35392 +                       ndx -= 22;
35393 +                       epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
35394 +               }
35395 +       }
35396 +       //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
35397 +       return epnum;
35398 +}
35399 +
35400 +/**
35401 + * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
35402 + * The active request is checked for the next packet to be loaded into
35403 + * the non-periodic Tx FIFO.
35404 + */
35405 +int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
35406 +{
35407 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
35408 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
35409 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
35410 +       gnptxsts_data_t txstatus = {.d32 = 0 };
35411 +       gintsts_data_t gintsts;
35412 +
35413 +       int epnum = 0;
35414 +       dwc_otg_pcd_ep_t *ep = 0;
35415 +       uint32_t len = 0;
35416 +       int dwords;
35417 +
35418 +       /* Get the epnum from the IN Token Learning Queue. */
35419 +       epnum = get_ep_of_last_in_token(core_if);
35420 +       ep = get_in_ep(pcd, epnum);
35421 +
35422 +       DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
35423 +
35424 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
35425 +
35426 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
35427 +       if (len > ep->dwc_ep.maxpacket) {
35428 +               len = ep->dwc_ep.maxpacket;
35429 +       }
35430 +       dwords = (len + 3) / 4;
35431 +
35432 +       /* While there is space in the queue and space in the FIFO and
35433 +        * More data to tranfer, Write packets to the Tx FIFO */
35434 +       txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts);
35435 +       DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
35436 +
35437 +       while (txstatus.b.nptxqspcavail > 0 &&
35438 +              txstatus.b.nptxfspcavail > dwords &&
35439 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
35440 +               /* Write the FIFO */
35441 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
35442 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
35443 +
35444 +               if (len > ep->dwc_ep.maxpacket) {
35445 +                       len = ep->dwc_ep.maxpacket;
35446 +               }
35447 +
35448 +               dwords = (len + 3) / 4;
35449 +               txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts);
35450 +               DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
35451 +       }
35452 +
35453 +       DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
35454 +                   dwc_read_reg32(&global_regs->gnptxsts));
35455 +
35456 +       /* Clear interrupt */
35457 +       gintsts.d32 = 0;
35458 +       gintsts.b.nptxfempty = 1;
35459 +       dwc_write_reg32(&global_regs->gintsts, gintsts.d32);
35460 +
35461 +       return 1;
35462 +}
35463 +
35464 +/**
35465 + * This function is called when dedicated Tx FIFO Empty interrupt occurs.
35466 + * The active request is checked for the next packet to be loaded into
35467 + * apropriate Tx FIFO.
35468 + */
35469 +static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
35470 +{
35471 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
35472 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
35473 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
35474 +       dtxfsts_data_t txstatus = {.d32 = 0 };
35475 +       dwc_otg_pcd_ep_t *ep = 0;
35476 +       uint32_t len = 0;
35477 +       int dwords;
35478 +
35479 +       ep = get_in_ep(pcd, epnum);
35480 +
35481 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
35482 +
35483 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
35484 +
35485 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
35486 +
35487 +       if (len > ep->dwc_ep.maxpacket) {
35488 +               len = ep->dwc_ep.maxpacket;
35489 +       }
35490 +
35491 +       dwords = (len + 3) / 4;
35492 +
35493 +       /* While there is space in the queue and space in the FIFO and
35494 +        * More data to tranfer, Write packets to the Tx FIFO */
35495 +       txstatus.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts);
35496 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
35497 +
35498 +       while (txstatus.b.txfspcavail > dwords &&
35499 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
35500 +              ep->dwc_ep.xfer_len != 0) {
35501 +               /* Write the FIFO */
35502 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
35503 +
35504 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
35505 +               if (len > ep->dwc_ep.maxpacket) {
35506 +                       len = ep->dwc_ep.maxpacket;
35507 +               }
35508 +
35509 +               dwords = (len + 3) / 4;
35510 +               txstatus.d32 =
35511 +                   dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts);
35512 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
35513 +                           txstatus.d32);
35514 +       }
35515 +
35516 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
35517 +                   dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts));
35518 +
35519 +       return 1;
35520 +}
35521 +
35522 +/**
35523 + * This function is called when the Device is disconnected. It stops
35524 + * any active requests and informs the Gadget driver of the
35525 + * disconnect.
35526 + */
35527 +void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
35528 +{
35529 +       int i, num_in_eps, num_out_eps;
35530 +       dwc_otg_pcd_ep_t *ep;
35531 +
35532 +       gintmsk_data_t intr_mask = {.d32 = 0 };
35533 +
35534 +       DWC_SPINLOCK(pcd->lock);
35535 +
35536 +       num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
35537 +       num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
35538 +
35539 +       DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
35540 +       /* don't disconnect drivers more than once */
35541 +       if (pcd->ep0state == EP0_DISCONNECT) {
35542 +               DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
35543 +               return;
35544 +       }
35545 +       pcd->ep0state = EP0_DISCONNECT;
35546 +
35547 +       /* Reset the OTG state. */
35548 +       dwc_otg_pcd_update_otg(pcd, 1);
35549 +
35550 +       /* Disable the NP Tx Fifo Empty Interrupt. */
35551 +       intr_mask.b.nptxfempty = 1;
35552 +       dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
35553 +                        intr_mask.d32, 0);
35554 +
35555 +       /* Flush the FIFOs */
35556 +       /**@todo NGS Flush Periodic FIFOs */
35557 +       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
35558 +       dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
35559 +
35560 +       /* prevent new request submissions, kill any outstanding requests  */
35561 +       ep = &pcd->ep0;
35562 +       dwc_otg_request_nuke(ep);
35563 +       /* prevent new request submissions, kill any outstanding requests  */
35564 +       for (i = 0; i < num_in_eps; i++) {
35565 +               dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
35566 +               dwc_otg_request_nuke(ep);
35567 +       }
35568 +       /* prevent new request submissions, kill any outstanding requests  */
35569 +       for (i = 0; i < num_out_eps; i++) {
35570 +               dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
35571 +               dwc_otg_request_nuke(ep);
35572 +       }
35573 +
35574 +       /* report disconnect; the driver is already quiesced */
35575 +       if (pcd->fops->disconnect) {
35576 +               DWC_SPINUNLOCK(pcd->lock);
35577 +               pcd->fops->disconnect(pcd);
35578 +               DWC_SPINLOCK(pcd->lock);
35579 +       }
35580 +       DWC_SPINUNLOCK(pcd->lock);
35581 +}
35582 +
35583 +/**
35584 + * This interrupt indicates that ...
35585 + */
35586 +int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
35587 +{
35588 +       gintmsk_data_t intr_mask = {.d32 = 0 };
35589 +       gintsts_data_t gintsts;
35590 +
35591 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
35592 +       intr_mask.b.i2cintr = 1;
35593 +       dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
35594 +                        intr_mask.d32, 0);
35595 +
35596 +       /* Clear interrupt */
35597 +       gintsts.d32 = 0;
35598 +       gintsts.b.i2cintr = 1;
35599 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
35600 +                       gintsts.d32);
35601 +       return 1;
35602 +}
35603 +
35604 +/**
35605 + * This interrupt indicates that ...
35606 + */
35607 +int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
35608 +{
35609 +       gintsts_data_t gintsts;
35610 +#if defined(VERBOSE)
35611 +       DWC_PRINTF("Early Suspend Detected\n");
35612 +#endif
35613 +       /* Clear interrupt */
35614 +       gintsts.d32 = 0;
35615 +       gintsts.b.erlysuspend = 1;
35616 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
35617 +                       gintsts.d32);
35618 +       return 1;
35619 +}
35620 +
35621 +/**
35622 + * This function configures EPO to receive SETUP packets.
35623 + *
35624 + * @todo NGS: Update the comments from the HW FS.
35625 + *
35626 + *     -# Program the following fields in the endpoint specific registers
35627 + *     for Control OUT EP 0, in order to receive a setup packet
35628 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
35629 + *       setup packets)
35630 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
35631 + *       to back setup packets)
35632 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
35633 + *               store any setup packets received
35634 + *
35635 + * @param core_if Programming view of DWC_otg controller.
35636 + * @param pcd    Programming view of the PCD.
35637 + */
35638 +static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
35639 +                                dwc_otg_pcd_t * pcd)
35640 +{
35641 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
35642 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
35643 +       dwc_otg_dev_dma_desc_t *dma_desc;
35644 +       depctl_data_t doepctl = {.d32 = 0 };
35645 +
35646 +#ifdef VERBOSE
35647 +       DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
35648 +                   dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));
35649 +#endif
35650 +
35651 +       doeptsize0.b.supcnt = 3;
35652 +       doeptsize0.b.pktcnt = 1;
35653 +       doeptsize0.b.xfersize = 8 * 3;
35654 +
35655 +       if (core_if->dma_enable) {
35656 +               if (!core_if->dma_desc_enable) {
35657 +                       /** put here as for Hermes mode deptisz register should not be written */
35658 +                       dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz,
35659 +                                       doeptsize0.d32);
35660 +
35661 +                       /** @todo dma needs to handle multiple setup packets (up to 3) */
35662 +                       dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma,
35663 +                                       pcd->setup_pkt_dma_handle);
35664 +               } else {
35665 +                       dev_if->setup_desc_index =
35666 +                           (dev_if->setup_desc_index + 1) & 1;
35667 +                       dma_desc =
35668 +                           dev_if->setup_desc_addr[dev_if->setup_desc_index];
35669 +
35670 +                       /** DMA Descriptor Setup */
35671 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
35672 +                       dma_desc->status.b.l = 1;
35673 +                       dma_desc->status.b.ioc = 1;
35674 +                       dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
35675 +                       dma_desc->buf = pcd->setup_pkt_dma_handle;
35676 +                       dma_desc->status.b.bs = BS_HOST_READY;
35677 +
35678 +                       /** DOEPDMA0 Register write */
35679 +                       dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma,
35680 +                                       dev_if->dma_setup_desc_addr[dev_if->
35681 +                                                                   setup_desc_index]);
35682 +               }
35683 +
35684 +       } else {
35685 +               /** put here as for Hermes mode deptisz register should not be written */
35686 +               dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz,
35687 +                               doeptsize0.d32);
35688 +       }
35689 +
35690 +       /** DOEPCTL0 Register write */
35691 +       doepctl.b.epena = 1;
35692 +       doepctl.b.cnak = 1;
35693 +       dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
35694 +
35695 +#ifdef VERBOSE
35696 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
35697 +                   dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));
35698 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
35699 +                   dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl));
35700 +#endif
35701 +}
35702 +
35703 +/**
35704 + * This interrupt occurs when a USB Reset is detected. When the USB
35705 + * Reset Interrupt occurs the device state is set to DEFAULT and the
35706 + * EP0 state is set to IDLE.
35707 + *     -#      Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
35708 + *     -#      Unmask the following interrupt bits
35709 + *             - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
35710 + *     - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
35711 + *     - DOEPMSK.SETUP = 1
35712 + *     - DOEPMSK.XferCompl = 1
35713 + *     - DIEPMSK.XferCompl = 1
35714 + *     - DIEPMSK.TimeOut = 1
35715 + *     -# Program the following fields in the endpoint specific registers
35716 + *     for Control OUT EP 0, in order to receive a setup packet
35717 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
35718 + *       setup packets)
35719 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
35720 + *       to back setup packets)
35721 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
35722 + *               store any setup packets received
35723 + * At this point, all the required initialization, except for enabling
35724 + * the control 0 OUT endpoint is done, for receiving SETUP packets.
35725 + */
35726 +int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
35727 +{
35728 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
35729 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
35730 +       depctl_data_t doepctl = {.d32 = 0 };
35731 +       daint_data_t daintmsk = {.d32 = 0 };
35732 +       doepmsk_data_t doepmsk = {.d32 = 0 };
35733 +       diepmsk_data_t diepmsk = {.d32 = 0 };
35734 +       dcfg_data_t dcfg = {.d32 = 0 };
35735 +       grstctl_t resetctl = {.d32 = 0 };
35736 +       dctl_data_t dctl = {.d32 = 0 };
35737 +       int i = 0;
35738 +       gintsts_data_t gintsts;
35739 +       pcgcctl_data_t power = {.d32 = 0 };
35740 +
35741 +       power.d32 = dwc_read_reg32(core_if->pcgcctl);
35742 +       if (power.b.stoppclk) {
35743 +               power.d32 = 0;
35744 +               power.b.stoppclk = 1;
35745 +               dwc_modify_reg32(core_if->pcgcctl, power.d32, 0);
35746 +
35747 +               power.b.pwrclmp = 1;
35748 +               dwc_modify_reg32(core_if->pcgcctl, power.d32, 0);
35749 +
35750 +               power.b.rstpdwnmodule = 1;
35751 +               dwc_modify_reg32(core_if->pcgcctl, power.d32, 0);
35752 +       }
35753 +
35754 +       core_if->lx_state = DWC_OTG_L0;
35755 +
35756 +       DWC_PRINTF("USB RESET\n");
35757 +#ifdef DWC_EN_ISOC
35758 +       for (i = 1; i < 16; ++i) {
35759 +               dwc_otg_pcd_ep_t *ep;
35760 +               dwc_ep_t *dwc_ep;
35761 +               ep = get_in_ep(pcd, i);
35762 +               if (ep != 0) {
35763 +                       dwc_ep = &ep->dwc_ep;
35764 +                       dwc_ep->next_frame = 0xffffffff;
35765 +               }
35766 +       }
35767 +#endif                         /* DWC_EN_ISOC */
35768 +
35769 +       /* reset the HNP settings */
35770 +       dwc_otg_pcd_update_otg(pcd, 1);
35771 +
35772 +       /* Clear the Remote Wakeup Signalling */
35773 +       dctl.b.rmtwkupsig = 1;
35774 +       dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
35775 +
35776 +       /* Set NAK for all OUT EPs */
35777 +       doepctl.b.snak = 1;
35778 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
35779 +               dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
35780 +       }
35781 +
35782 +       /* Flush the NP Tx FIFO */
35783 +       dwc_otg_flush_tx_fifo(core_if, 0x10);
35784 +       /* Flush the Learning Queue */
35785 +       resetctl.b.intknqflsh = 1;
35786 +       dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32);
35787 +
35788 +       if (core_if->multiproc_int_enable) {
35789 +               daintmsk.b.inep0 = 1;
35790 +               daintmsk.b.outep0 = 1;
35791 +               dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk,
35792 +                               daintmsk.d32);
35793 +
35794 +               doepmsk.b.setup = 1;
35795 +               doepmsk.b.xfercompl = 1;
35796 +               doepmsk.b.ahberr = 1;
35797 +               doepmsk.b.epdisabled = 1;
35798 +
35799 +               if (core_if->dma_desc_enable) {
35800 +                       doepmsk.b.stsphsercvd = 1;
35801 +                       doepmsk.b.bna = 1;
35802 +               }
35803 +/*             
35804 +               doepmsk.b.babble = 1;
35805 +               doepmsk.b.nyet = 1;
35806 +               
35807 +               if(core_if->dma_enable) {
35808 +                       doepmsk.b.nak = 1;
35809 +               }
35810 +*/
35811 +               dwc_write_reg32(&dev_if->dev_global_regs->doepeachintmsk[0],
35812 +                               doepmsk.d32);
35813 +
35814 +               diepmsk.b.xfercompl = 1;
35815 +               diepmsk.b.timeout = 1;
35816 +               diepmsk.b.epdisabled = 1;
35817 +               diepmsk.b.ahberr = 1;
35818 +               diepmsk.b.intknepmis = 1;
35819 +
35820 +               if (core_if->dma_desc_enable) {
35821 +                       diepmsk.b.bna = 1;
35822 +               }
35823 +/*             
35824 +               if(core_if->dma_enable) {
35825 +                       diepmsk.b.nak = 1;
35826 +               }
35827 +*/
35828 +               dwc_write_reg32(&dev_if->dev_global_regs->diepeachintmsk[0],
35829 +                               diepmsk.d32);
35830 +       } else {
35831 +               daintmsk.b.inep0 = 1;
35832 +               daintmsk.b.outep0 = 1;
35833 +               dwc_write_reg32(&dev_if->dev_global_regs->daintmsk,
35834 +                               daintmsk.d32);
35835 +
35836 +               doepmsk.b.setup = 1;
35837 +               doepmsk.b.xfercompl = 1;
35838 +               doepmsk.b.ahberr = 1;
35839 +               doepmsk.b.epdisabled = 1;
35840 +
35841 +               if (core_if->dma_desc_enable) {
35842 +                       doepmsk.b.stsphsercvd = 1;
35843 +                       doepmsk.b.bna = 1;
35844 +               }
35845 +               dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
35846 +
35847 +               diepmsk.b.xfercompl = 1;
35848 +               diepmsk.b.timeout = 1;
35849 +               diepmsk.b.epdisabled = 1;
35850 +               diepmsk.b.ahberr = 1;
35851 +               diepmsk.b.intknepmis = 1;
35852 +
35853 +               if (core_if->dma_desc_enable) {
35854 +                       diepmsk.b.bna = 1;
35855 +               }
35856 +
35857 +               dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
35858 +       }
35859 +
35860 +       /* Reset Device Address */
35861 +       dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg);
35862 +       dcfg.b.devaddr = 0;
35863 +       dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
35864 +
35865 +       /* setup EP0 to receive SETUP packets */
35866 +       ep0_out_start(core_if, pcd);
35867 +
35868 +       /* Clear interrupt */
35869 +       gintsts.d32 = 0;
35870 +       gintsts.b.usbreset = 1;
35871 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
35872 +
35873 +       return 1;
35874 +}
35875 +
35876 +/**
35877 + * Get the device speed from the device status register and convert it
35878 + * to USB speed constant.
35879 + *
35880 + * @param core_if Programming view of DWC_otg controller.
35881 + */
35882 +static int get_device_speed(dwc_otg_core_if_t * core_if)
35883 +{
35884 +       dsts_data_t dsts;
35885 +       int speed = 0;
35886 +       dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
35887 +
35888 +       switch (dsts.b.enumspd) {
35889 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
35890 +               speed = USB_SPEED_HIGH;
35891 +               break;
35892 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
35893 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
35894 +               speed = USB_SPEED_FULL;
35895 +               break;
35896 +
35897 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
35898 +               speed = USB_SPEED_LOW;
35899 +               break;
35900 +       }
35901 +
35902 +       return speed;
35903 +}
35904 +
35905 +/**
35906 + * Read the device status register and set the device speed in the
35907 + * data structure.
35908 + * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
35909 + */
35910 +int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
35911 +{
35912 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
35913 +       gintsts_data_t gintsts;
35914 +       gusbcfg_data_t gusbcfg;
35915 +       dwc_otg_core_global_regs_t *global_regs =
35916 +           GET_CORE_IF(pcd)->core_global_regs;
35917 +       uint8_t utmi16b, utmi8b;
35918 +       int speed;
35919 +       DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
35920 +
35921 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
35922 +               utmi16b = 6;
35923 +               utmi8b = 9;
35924 +       } else {
35925 +               utmi16b = 4;
35926 +               utmi8b = 8;
35927 +       }
35928 +       dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
35929 +
35930 +#ifdef DEBUG_EP0
35931 +       print_ep0_state(pcd);
35932 +#endif
35933 +
35934 +       if (pcd->ep0state == EP0_DISCONNECT) {
35935 +               pcd->ep0state = EP0_IDLE;
35936 +       } else if (pcd->ep0state == EP0_STALL) {
35937 +               pcd->ep0state = EP0_IDLE;
35938 +       }
35939 +
35940 +       pcd->ep0state = EP0_IDLE;
35941 +
35942 +       ep0->stopped = 0;
35943 +
35944 +       speed = get_device_speed(GET_CORE_IF(pcd));
35945 +       pcd->fops->connect(pcd, speed);
35946 +
35947 +       /* Set USB turnaround time based on device speed and PHY interface. */
35948 +       gusbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
35949 +       if (speed == USB_SPEED_HIGH) {
35950 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
35951 +                   DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
35952 +                       /* ULPI interface */
35953 +                       gusbcfg.b.usbtrdtim = 9;
35954 +               }
35955 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
35956 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
35957 +                       /* UTMI+ interface */
35958 +                       if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
35959 +                               gusbcfg.b.usbtrdtim = utmi8b;
35960 +                       } else if (GET_CORE_IF(pcd)->hwcfg4.b.
35961 +                                  utmi_phy_data_width == 1) {
35962 +                               gusbcfg.b.usbtrdtim = utmi16b;
35963 +                       } else if (GET_CORE_IF(pcd)->core_params->
35964 +                                  phy_utmi_width == 8) {
35965 +                               gusbcfg.b.usbtrdtim = utmi8b;
35966 +                       } else {
35967 +                               gusbcfg.b.usbtrdtim = utmi16b;
35968 +                       }
35969 +               }
35970 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
35971 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
35972 +                       /* UTMI+  OR  ULPI interface */
35973 +                       if (gusbcfg.b.ulpi_utmi_sel == 1) {
35974 +                               /* ULPI interface */
35975 +                               gusbcfg.b.usbtrdtim = 9;
35976 +                       } else {
35977 +                               /* UTMI+ interface */
35978 +                               if (GET_CORE_IF(pcd)->core_params->
35979 +                                   phy_utmi_width == 16) {
35980 +                                       gusbcfg.b.usbtrdtim = utmi16b;
35981 +                               } else {
35982 +                                       gusbcfg.b.usbtrdtim = utmi8b;
35983 +                               }
35984 +                       }
35985 +               }
35986 +       } else {
35987 +               /* Full or low speed */
35988 +               gusbcfg.b.usbtrdtim = 9;
35989 +       }
35990 +       dwc_write_reg32(&global_regs->gusbcfg, gusbcfg.d32);
35991 +
35992 +       /* Clear interrupt */
35993 +       gintsts.d32 = 0;
35994 +       gintsts.b.enumdone = 1;
35995 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
35996 +                       gintsts.d32);
35997 +       return 1;
35998 +}
35999 +
36000 +/**
36001 + * This interrupt indicates that the ISO OUT Packet was dropped due to
36002 + * Rx FIFO full or Rx Status Queue Full.  If this interrupt occurs
36003 + * read all the data from the Rx FIFO.
36004 + */
36005 +int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
36006 +{
36007 +       gintmsk_data_t intr_mask = {.d32 = 0 };
36008 +       gintsts_data_t gintsts;
36009 +
36010 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
36011 +                  "ISOC Out Dropped");
36012 +
36013 +       intr_mask.b.isooutdrop = 1;
36014 +       dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
36015 +                        intr_mask.d32, 0);
36016 +
36017 +       /* Clear interrupt */
36018 +       gintsts.d32 = 0;
36019 +       gintsts.b.isooutdrop = 1;
36020 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
36021 +                       gintsts.d32);
36022 +
36023 +       return 1;
36024 +}
36025 +
36026 +/**
36027 + * This interrupt indicates the end of the portion of the micro-frame
36028 + * for periodic transactions.  If there is a periodic transaction for
36029 + * the next frame, load the packets into the EP periodic Tx FIFO.
36030 + */
36031 +int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
36032 +{
36033 +       gintmsk_data_t intr_mask = {.d32 = 0 };
36034 +       gintsts_data_t gintsts;
36035 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
36036 +
36037 +       intr_mask.b.eopframe = 1;
36038 +       dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
36039 +                        intr_mask.d32, 0);
36040 +
36041 +       /* Clear interrupt */
36042 +       gintsts.d32 = 0;
36043 +       gintsts.b.eopframe = 1;
36044 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
36045 +                       gintsts.d32);
36046 +
36047 +       return 1;
36048 +}
36049 +
36050 +/**
36051 + * This interrupt indicates that EP of the packet on the top of the
36052 + * non-periodic Tx FIFO does not match EP of the IN Token received.
36053 + *
36054 + * The "Device IN Token Queue" Registers are read to determine the
36055 + * order the IN Tokens have been received.     The non-periodic Tx FIFO
36056 + * is flushed, so it can be reloaded in the order seen in the IN Token
36057 + * Queue.
36058 + */
36059 +int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_core_if_t * core_if)
36060 +{
36061 +       gintsts_data_t gintsts;
36062 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
36063 +
36064 +       /* Clear interrupt */
36065 +       gintsts.d32 = 0;
36066 +       gintsts.b.epmismatch = 1;
36067 +       dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32);
36068 +
36069 +       return 1;
36070 +}
36071 +
36072 +/**
36073 + * This funcion stalls EP0.
36074 + */
36075 +static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
36076 +{
36077 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
36078 +       usb_device_request_t *ctrl = &pcd->setup_pkt->req;
36079 +       DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
36080 +                ctrl->bmRequestType, ctrl->bRequest, err_val);
36081 +
36082 +       ep0->dwc_ep.is_in = 1;
36083 +       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
36084 +       pcd->ep0.stopped = 1;
36085 +       pcd->ep0state = EP0_IDLE;
36086 +       ep0_out_start(GET_CORE_IF(pcd), pcd);
36087 +}
36088 +
36089 +/**
36090 + * This functions delegates the setup command to the gadget driver.
36091 + */
36092 +static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
36093 +                                  usb_device_request_t * ctrl)
36094 +{
36095 +       int ret = 0;
36096 +       DWC_SPINUNLOCK(pcd->lock);
36097 +       ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
36098 +       DWC_SPINLOCK(pcd->lock);
36099 +       if (ret < 0) {
36100 +               ep0_do_stall(pcd, ret);
36101 +       }
36102 +
36103 +       /** @todo This is a g_file_storage gadget driver specific
36104 +        * workaround: a DELAYED_STATUS result from the fsg_setup
36105 +        * routine will result in the gadget queueing a EP0 IN status
36106 +        * phase for a two-stage control transfer.      Exactly the same as
36107 +        * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
36108 +        * specific request.  Need a generic way to know when the gadget
36109 +        * driver will queue the status phase.  Can we assume when we
36110 +        * call the gadget driver setup() function that it will always
36111 +        * queue and require the following flag?  Need to look into
36112 +        * this.
36113 +        */
36114 +
36115 +       if (ret == 256 + 999) {
36116 +               pcd->request_config = 1;
36117 +       }
36118 +}
36119 +
36120 +#ifdef DWC_UTE_CFI
36121 +/**
36122 + * This functions delegates the CFI setup commands to the gadget driver.
36123 + * This function will return a negative value to indicate a failure.
36124 + */
36125 +static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
36126 +                                  struct cfi_usb_ctrlrequest *ctrl_req)
36127 +{
36128 +       int ret = 0;
36129 +
36130 +       if (pcd->fops && pcd->fops->cfi_setup) {
36131 +               DWC_SPINUNLOCK(pcd->lock);
36132 +               ret = pcd->fops->cfi_setup(pcd, ctrl_req);
36133 +               DWC_SPINLOCK(pcd->lock);
36134 +               if (ret < 0) {
36135 +                       ep0_do_stall(pcd, ret);
36136 +                       return ret;
36137 +               }
36138 +       }
36139 +
36140 +       return ret;
36141 +}
36142 +#endif
36143 +
36144 +/**
36145 + * This function starts the Zero-Length Packet for the IN status phase
36146 + * of a 2 stage control transfer.
36147 + */
36148 +static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
36149 +{
36150 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
36151 +       if (pcd->ep0state == EP0_STALL) {
36152 +               return;
36153 +       }
36154 +
36155 +       pcd->ep0state = EP0_IN_STATUS_PHASE;
36156 +
36157 +       /* Prepare for more SETUP Packets */
36158 +       DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
36159 +       ep0->dwc_ep.xfer_len = 0;
36160 +       ep0->dwc_ep.xfer_count = 0;
36161 +       ep0->dwc_ep.is_in = 1;
36162 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
36163 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
36164 +
36165 +       /* Prepare for more SETUP Packets */
36166 +       //ep0_out_start(GET_CORE_IF(pcd), pcd);
36167 +}
36168 +
36169 +/**
36170 + * This function starts the Zero-Length Packet for the OUT status phase
36171 + * of a 2 stage control transfer.
36172 + */
36173 +static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
36174 +{
36175 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
36176 +       if (pcd->ep0state == EP0_STALL) {
36177 +               DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
36178 +               return;
36179 +       }
36180 +       pcd->ep0state = EP0_OUT_STATUS_PHASE;
36181 +
36182 +       DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
36183 +       ep0->dwc_ep.xfer_len = 0;
36184 +       ep0->dwc_ep.xfer_count = 0;
36185 +       ep0->dwc_ep.is_in = 0;
36186 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
36187 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
36188 +
36189 +       /* Prepare for more SETUP Packets */
36190 +       if (GET_CORE_IF(pcd)->dma_enable == 0) {
36191 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
36192 +       }
36193 +}
36194 +
36195 +/**
36196 + * Clear the EP halt (STALL) and if pending requests start the
36197 + * transfer.
36198 + */
36199 +static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
36200 +{
36201 +       if (ep->dwc_ep.stall_clear_flag == 0)
36202 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
36203 +
36204 +       /* Reactive the EP */
36205 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
36206 +       if (ep->stopped) {
36207 +               ep->stopped = 0;
36208 +               /* If there is a request in the EP queue start it */
36209 +
36210 +               /** @todo FIXME: this causes an EP mismatch in DMA mode.
36211 +                * epmismatch not yet implemented. */
36212 +
36213 +               /*
36214 +                * Above fixme is solved by implmenting a tasklet to call the
36215 +                * start_next_request(), outside of interrupt context at some
36216 +                * time after the current time, after a clear-halt setup packet.
36217 +                * Still need to implement ep mismatch in the future if a gadget
36218 +                * ever uses more than one endpoint at once
36219 +                */
36220 +               ep->queue_sof = 1;
36221 +               DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
36222 +       }
36223 +       /* Start Control Status Phase */
36224 +       do_setup_in_status_phase(pcd);
36225 +}
36226 +
36227 +/**
36228 + * This function is called when the SET_FEATURE TEST_MODE Setup packet
36229 + * is sent from the host.  The Device Control register is written with
36230 + * the Test Mode bits set to the specified Test Mode.  This is done as
36231 + * a tasklet so that the "Status" phase of the control transfer
36232 + * completes before transmitting the TEST packets.
36233 + *
36234 + * @todo This has not been tested since the tasklet struct was put
36235 + * into the PCD struct!
36236 + *
36237 + */
36238 +void do_test_mode(void *data)
36239 +{
36240 +       dctl_data_t dctl;
36241 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
36242 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
36243 +       int test_mode = pcd->test_mode;
36244 +
36245 +//        DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
36246 +
36247 +       dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl);
36248 +       switch (test_mode) {
36249 +       case 1:         // TEST_J
36250 +               dctl.b.tstctl = 1;
36251 +               break;
36252 +
36253 +       case 2:         // TEST_K
36254 +               dctl.b.tstctl = 2;
36255 +               break;
36256 +
36257 +       case 3:         // TEST_SE0_NAK
36258 +               dctl.b.tstctl = 3;
36259 +               break;
36260 +
36261 +       case 4:         // TEST_PACKET
36262 +               dctl.b.tstctl = 4;
36263 +               break;
36264 +
36265 +       case 5:         // TEST_FORCE_ENABLE
36266 +               dctl.b.tstctl = 5;
36267 +               break;
36268 +       }
36269 +       dwc_write_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
36270 +}
36271 +
36272 +/**
36273 + * This function process the GET_STATUS Setup Commands.
36274 + */
36275 +static inline void do_get_status(dwc_otg_pcd_t * pcd)
36276 +{
36277 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
36278 +       dwc_otg_pcd_ep_t *ep;
36279 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
36280 +       uint16_t *status = pcd->status_buf;
36281 +
36282 +#ifdef DEBUG_EP0
36283 +       DWC_DEBUGPL(DBG_PCD,
36284 +                   "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
36285 +                   ctrl.bmRequestType, ctrl.bRequest,
36286 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
36287 +                   UGETW(ctrl.wLength));
36288 +#endif
36289 +
36290 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
36291 +       case UT_DEVICE:
36292 +               *status = 0x1;  /* Self powered */
36293 +               *status |= pcd->remote_wakeup_enable << 1;
36294 +               break;
36295 +
36296 +       case UT_INTERFACE:
36297 +               *status = 0;
36298 +               break;
36299 +
36300 +       case UT_ENDPOINT:
36301 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
36302 +               if (ep == 0 || UGETW(ctrl.wLength) > 2) {
36303 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
36304 +                       return;
36305 +               }
36306 +               /** @todo check for EP stall */
36307 +               *status = ep->stopped;
36308 +               break;
36309 +       }
36310 +       pcd->ep0_pending = 1;
36311 +       ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
36312 +       ep0->dwc_ep.xfer_buff = (uint8_t *) status;
36313 +       ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
36314 +       ep0->dwc_ep.xfer_len = 2;
36315 +       ep0->dwc_ep.xfer_count = 0;
36316 +       ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
36317 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
36318 +}
36319 +
36320 +/**
36321 + * This function process the SET_FEATURE Setup Commands.
36322 + */
36323 +static inline void do_set_feature(dwc_otg_pcd_t * pcd)
36324 +{
36325 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
36326 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
36327 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
36328 +       dwc_otg_pcd_ep_t *ep = 0;
36329 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
36330 +       gotgctl_data_t gotgctl = {.d32 = 0 };
36331 +
36332 +       DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
36333 +                   ctrl.bmRequestType, ctrl.bRequest,
36334 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
36335 +                   UGETW(ctrl.wLength));
36336 +       DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
36337 +
36338 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
36339 +       case UT_DEVICE:
36340 +               switch (UGETW(ctrl.wValue)) {
36341 +               case UF_DEVICE_REMOTE_WAKEUP:
36342 +                       pcd->remote_wakeup_enable = 1;
36343 +                       break;
36344 +
36345 +               case UF_TEST_MODE:
36346 +                       /* Setup the Test Mode tasklet to do the Test
36347 +                        * Packet generation after the SETUP Status
36348 +                        * phase has completed. */
36349 +
36350 +                       /** @todo This has not been tested since the
36351 +                        * tasklet struct was put into the PCD
36352 +                        * struct! */
36353 +                       pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
36354 +                       DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
36355 +                       break;
36356 +
36357 +               case UF_DEVICE_B_HNP_ENABLE:
36358 +                       DWC_DEBUGPL(DBG_PCDV,
36359 +                                   "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
36360 +
36361 +                       /* dev may initiate HNP */
36362 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
36363 +                               pcd->b_hnp_enable = 1;
36364 +                               dwc_otg_pcd_update_otg(pcd, 0);
36365 +                               DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
36366 +                               /**@todo Is the gotgctl.devhnpen cleared
36367 +                                * by a USB Reset? */
36368 +                               gotgctl.b.devhnpen = 1;
36369 +                               gotgctl.b.hnpreq = 1;
36370 +                               dwc_write_reg32(&global_regs->gotgctl,
36371 +                                               gotgctl.d32);
36372 +                       } else {
36373 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
36374 +                       }
36375 +                       break;
36376 +
36377 +               case UF_DEVICE_A_HNP_SUPPORT:
36378 +                       /* RH port supports HNP */
36379 +                       DWC_DEBUGPL(DBG_PCDV,
36380 +                                   "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
36381 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
36382 +                               pcd->a_hnp_support = 1;
36383 +                               dwc_otg_pcd_update_otg(pcd, 0);
36384 +                       } else {
36385 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
36386 +                       }
36387 +                       break;
36388 +
36389 +               case UF_DEVICE_A_ALT_HNP_SUPPORT:
36390 +                       /* other RH port does */
36391 +                       DWC_DEBUGPL(DBG_PCDV,
36392 +                                   "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
36393 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
36394 +                               pcd->a_alt_hnp_support = 1;
36395 +                               dwc_otg_pcd_update_otg(pcd, 0);
36396 +                       } else {
36397 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
36398 +                       }
36399 +                       break;
36400 +               }
36401 +               do_setup_in_status_phase(pcd);
36402 +               break;
36403 +
36404 +       case UT_INTERFACE:
36405 +               do_gadget_setup(pcd, &ctrl);
36406 +               break;
36407 +
36408 +       case UT_ENDPOINT:
36409 +               if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
36410 +                       ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
36411 +                       if (ep == 0) {
36412 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
36413 +                               return;
36414 +                       }
36415 +                       ep->stopped = 1;
36416 +                       dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
36417 +               }
36418 +               do_setup_in_status_phase(pcd);
36419 +               break;
36420 +       }
36421 +}
36422 +
36423 +/**
36424 + * This function process the CLEAR_FEATURE Setup Commands.
36425 + */
36426 +static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
36427 +{
36428 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
36429 +       dwc_otg_pcd_ep_t *ep = 0;
36430 +
36431 +       DWC_DEBUGPL(DBG_PCD,
36432 +                   "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
36433 +                   ctrl.bmRequestType, ctrl.bRequest,
36434 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
36435 +                   UGETW(ctrl.wLength));
36436 +
36437 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
36438 +       case UT_DEVICE:
36439 +               switch (UGETW(ctrl.wValue)) {
36440 +               case UF_DEVICE_REMOTE_WAKEUP:
36441 +                       pcd->remote_wakeup_enable = 0;
36442 +                       break;
36443 +
36444 +               case UF_TEST_MODE:
36445 +                       /** @todo Add CLEAR_FEATURE for TEST modes. */
36446 +                       break;
36447 +               }
36448 +               do_setup_in_status_phase(pcd);
36449 +               break;
36450 +
36451 +       case UT_ENDPOINT:
36452 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
36453 +               if (ep == 0) {
36454 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
36455 +                       return;
36456 +               }
36457 +
36458 +               pcd_clear_halt(pcd, ep);
36459 +
36460 +               break;
36461 +       }
36462 +}
36463 +
36464 +/**
36465 + * This function process the SET_ADDRESS Setup Commands.
36466 + */
36467 +static inline void do_set_address(dwc_otg_pcd_t * pcd)
36468 +{
36469 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
36470 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
36471 +
36472 +       if (ctrl.bmRequestType == UT_DEVICE) {
36473 +               dcfg_data_t dcfg = {.d32 = 0 };
36474 +
36475 +#ifdef DEBUG_EP0
36476 +//                      DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
36477 +#endif
36478 +               dcfg.b.devaddr = UGETW(ctrl.wValue);
36479 +               dwc_modify_reg32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
36480 +               do_setup_in_status_phase(pcd);
36481 +       }
36482 +}
36483 +
36484 +/**
36485 + *     This function processes SETUP commands.  In Linux, the USB Command
36486 + *     processing is done in two places - the first being the PCD and the
36487 + *     second in the Gadget Driver (for example, the File-Backed Storage
36488 + *     Gadget Driver).
36489 + *
36490 + * <table>
36491 + * <tr><td>Command     </td><td>Driver </td><td>Description</td></tr>
36492 + *
36493 + * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
36494 + * defined in chapter 9 of the USB 2.0 Specification chapter 9
36495 + * </td></tr>
36496 + *
36497 + * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
36498 + * requests are the ENDPOINT_HALT feature is procesed, all others the
36499 + * interface requests are ignored.</td></tr>
36500 + *
36501 + * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
36502 + * requests are processed by the PCD.  Interface requests are passed
36503 + * to the Gadget Driver.</td></tr>
36504 + *
36505 + * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
36506 + * with device address received </td></tr>
36507 + *
36508 + * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
36509 + * requested descriptor</td></tr>
36510 + *
36511 + * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
36512 + * not implemented by any of the existing Gadget Drivers.</td></tr>
36513 + *
36514 + * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
36515 + * all EPs and enable EPs for new configuration.</td></tr>
36516 + *
36517 + * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
36518 + * the current configuration</td></tr>
36519 + *
36520 + * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
36521 + * EPs and enable EPs for new configuration.</td></tr>
36522 + *
36523 + * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
36524 + * current interface.</td></tr>
36525 + *
36526 + * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
36527 + * message.</td></tr>
36528 + * </table>
36529 + *
36530 + * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
36531 + * processed by pcd_setup. Calling the Function Driver's setup function from
36532 + * pcd_setup processes the gadget SETUP commands.
36533 + */
36534 +static inline void pcd_setup(dwc_otg_pcd_t * pcd)
36535 +{
36536 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
36537 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
36538 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
36539 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
36540 +
36541 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
36542 +
36543 +#ifdef DWC_UTE_CFI
36544 +       int retval = 0;
36545 +       struct cfi_usb_ctrlrequest cfi_req;
36546 +#endif
36547 +
36548 +#ifdef DEBUG_EP0
36549 +       DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
36550 +                   ctrl.bmRequestType, ctrl.bRequest,
36551 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
36552 +                   UGETW(ctrl.wLength));
36553 +#endif
36554 +
36555 +       doeptsize0.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doeptsiz);
36556 +
36557 +       /** @todo handle > 1 setup packet , assert error for now */
36558 +
36559 +       if (core_if->dma_enable && core_if->dma_desc_enable == 0
36560 +           && (doeptsize0.b.supcnt < 2)) {
36561 +               DWC_ERROR
36562 +                   ("\n\n-----------    CANNOT handle > 1 setup packet in DMA mode\n\n");
36563 +       }
36564 +
36565 +       /* Clean up the request queue */
36566 +       dwc_otg_request_nuke(ep0);
36567 +       ep0->stopped = 0;
36568 +
36569 +       if (ctrl.bmRequestType & UE_DIR_IN) {
36570 +               ep0->dwc_ep.is_in = 1;
36571 +               pcd->ep0state = EP0_IN_DATA_PHASE;
36572 +       } else {
36573 +               ep0->dwc_ep.is_in = 0;
36574 +               pcd->ep0state = EP0_OUT_DATA_PHASE;
36575 +       }
36576 +
36577 +       if (UGETW(ctrl.wLength) == 0) {
36578 +               ep0->dwc_ep.is_in = 1;
36579 +               pcd->ep0state = EP0_IN_STATUS_PHASE;
36580 +       }
36581 +
36582 +       if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
36583 +
36584 +#ifdef DWC_UTE_CFI
36585 +               DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
36586 +
36587 +               //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ctrl.bRequestType, ctrl.bRequest);
36588 +               if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
36589 +                       if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
36590 +                               retval = cfi_setup(pcd, &cfi_req);
36591 +                               if (retval < 0) {
36592 +                                       ep0_do_stall(pcd, retval);
36593 +                                       pcd->ep0_pending = 0;
36594 +                                       return;
36595 +                               }
36596 +
36597 +                               /* if need gadget setup then call it and check the retval */
36598 +                               if (pcd->cfi->need_gadget_att) {
36599 +                                       retval =
36600 +                                           cfi_gadget_setup(pcd,
36601 +                                                            &pcd->cfi->
36602 +                                                            ctrl_req);
36603 +                                       if (retval < 0) {
36604 +                                               pcd->ep0_pending = 0;
36605 +                                               return;
36606 +                                       }
36607 +                               }
36608 +
36609 +                               if (pcd->cfi->need_status_in_complete) {
36610 +                                       do_setup_in_status_phase(pcd);
36611 +                               }
36612 +                               return;
36613 +                       }
36614 +               }
36615 +#endif
36616 +
36617 +               /* handle non-standard (class/vendor) requests in the gadget driver */
36618 +               do_gadget_setup(pcd, &ctrl);
36619 +               return;
36620 +       }
36621 +
36622 +       /** @todo NGS: Handle bad setup packet? */
36623 +
36624 +///////////////////////////////////////////
36625 +//// --- Standard Request handling --- ////
36626 +
36627 +       switch (ctrl.bRequest) {
36628 +       case UR_GET_STATUS:
36629 +               do_get_status(pcd);
36630 +               break;
36631 +
36632 +       case UR_CLEAR_FEATURE:
36633 +               do_clear_feature(pcd);
36634 +               break;
36635 +
36636 +       case UR_SET_FEATURE:
36637 +               do_set_feature(pcd);
36638 +               break;
36639 +
36640 +       case UR_SET_ADDRESS:
36641 +               do_set_address(pcd);
36642 +               break;
36643 +
36644 +       case UR_SET_INTERFACE:
36645 +       case UR_SET_CONFIG:
36646 +//              _pcd->request_config = 1;       /* Configuration changed */
36647 +               do_gadget_setup(pcd, &ctrl);
36648 +               break;
36649 +
36650 +       case UR_SYNCH_FRAME:
36651 +               do_gadget_setup(pcd, &ctrl);
36652 +               break;
36653 +
36654 +       default:
36655 +               /* Call the Gadget Driver's setup functions */
36656 +               do_gadget_setup(pcd, &ctrl);
36657 +               break;
36658 +       }
36659 +}
36660 +
36661 +/**
36662 + * This function completes the ep0 control transfer.
36663 + */
36664 +static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
36665 +{
36666 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
36667 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
36668 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
36669 +           dev_if->in_ep_regs[ep->dwc_ep.num];
36670 +#ifdef DEBUG_EP0
36671 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs =
36672 +           dev_if->out_ep_regs[ep->dwc_ep.num];
36673 +#endif
36674 +       deptsiz0_data_t deptsiz;
36675 +       dev_dma_desc_sts_t desc_sts;
36676 +       dwc_otg_pcd_request_t *req;
36677 +       int is_last = 0;
36678 +       dwc_otg_pcd_t *pcd = ep->pcd;
36679 +
36680 +#ifdef DWC_UTE_CFI
36681 +       struct cfi_usb_ctrlrequest *ctrlreq;
36682 +       int retval = -DWC_E_NOT_SUPPORTED;
36683 +#endif
36684 +
36685 +       if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
36686 +               if (ep->dwc_ep.is_in) {
36687 +#ifdef DEBUG_EP0
36688 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
36689 +#endif
36690 +                       do_setup_out_status_phase(pcd);
36691 +               } else {
36692 +#ifdef DEBUG_EP0
36693 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
36694 +#endif
36695 +
36696 +#ifdef DWC_UTE_CFI
36697 +                       ctrlreq = &pcd->cfi->ctrl_req;
36698 +
36699 +                       if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
36700 +                               if (ctrlreq->bRequest > 0xB0
36701 +                                   && ctrlreq->bRequest < 0xBF) {
36702 +
36703 +                                       /* Return if the PCD failed to handle the request */
36704 +                                       if ((retval =
36705 +                                            pcd->cfi->ops.
36706 +                                            ctrl_write_complete(pcd->cfi,
36707 +                                                                pcd)) < 0) {
36708 +                                               CFI_INFO
36709 +                                                   ("ERROR setting a new value in the PCD(%d)\n",
36710 +                                                    retval);
36711 +                                               ep0_do_stall(pcd, retval);
36712 +                                               pcd->ep0_pending = 0;
36713 +                                               return 0;
36714 +                                       }
36715 +
36716 +                                       /* If the gadget needs to be notified on the request */
36717 +                                       if (pcd->cfi->need_gadget_att == 1) {
36718 +                                               //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
36719 +                                               retval =
36720 +                                                   cfi_gadget_setup(pcd,
36721 +                                                                    &pcd->cfi->
36722 +                                                                    ctrl_req);
36723 +
36724 +                                               /* Return from the function if the gadget failed to process
36725 +                                                * the request properly - this should never happen !!!
36726 +                                                */
36727 +                                               if (retval < 0) {
36728 +                                                       CFI_INFO
36729 +                                                           ("ERROR setting a new value in the gadget(%d)\n",
36730 +                                                            retval);
36731 +                                                       pcd->ep0_pending = 0;
36732 +                                                       return 0;
36733 +                                               }
36734 +                                       }
36735 +
36736 +                                       CFI_INFO("%s: RETVAL=%d\n", __func__,
36737 +                                                retval);
36738 +                                       /* If we hit here then the PCD and the gadget has properly
36739 +                                        * handled the request - so send the ZLP IN to the host.
36740 +                                        */
36741 +                                       /* @todo: MAS - decide whether we need to start the setup
36742 +                                        * stage based on the need_setup value of the cfi object
36743 +                                        */
36744 +                                       do_setup_in_status_phase(pcd);
36745 +                                       pcd->ep0_pending = 0;
36746 +                                       return 1;
36747 +                               }
36748 +                       }
36749 +#endif
36750 +
36751 +                       do_setup_in_status_phase(pcd);
36752 +               }
36753 +               pcd->ep0_pending = 0;
36754 +               return 1;
36755 +       }
36756 +
36757 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
36758 +               return 0;
36759 +       }
36760 +       req = DWC_CIRCLEQ_FIRST(&ep->queue);
36761 +
36762 +       if (pcd->ep0state == EP0_OUT_STATUS_PHASE
36763 +           || pcd->ep0state == EP0_IN_STATUS_PHASE) {
36764 +               is_last = 1;
36765 +       } else if (ep->dwc_ep.is_in) {
36766 +               deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz);
36767 +               if (core_if->dma_desc_enable != 0)
36768 +                       desc_sts = dev_if->in_desc_addr->status;
36769 +#ifdef DEBUG_EP0
36770 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d  xfersize=%d pktcnt=%d\n",
36771 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
36772 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
36773 +#endif
36774 +
36775 +               if (((core_if->dma_desc_enable == 0)
36776 +                    && (deptsiz.b.xfersize == 0))
36777 +                   || ((core_if->dma_desc_enable != 0)
36778 +                       && (desc_sts.b.bytes == 0))) {
36779 +                       req->actual = ep->dwc_ep.xfer_count;
36780 +                       /* Is a Zero Len Packet needed? */
36781 +                       if (req->sent_zlp) {
36782 +#ifdef DEBUG_EP0
36783 +                               DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
36784 +#endif
36785 +                               req->sent_zlp = 0;
36786 +                       }
36787 +                       do_setup_out_status_phase(pcd);
36788 +               }
36789 +       } else {
36790 +               /* ep0-OUT */
36791 +#ifdef DEBUG_EP0
36792 +               deptsiz.d32 = dwc_read_reg32(&out_ep_regs->doeptsiz);
36793 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
36794 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
36795 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
36796 +#endif
36797 +               req->actual = ep->dwc_ep.xfer_count;
36798 +
36799 +               /* Is a Zero Len Packet needed? */
36800 +               if (req->sent_zlp) {
36801 +#ifdef DEBUG_EP0
36802 +                       DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
36803 +#endif
36804 +                       req->sent_zlp = 0;
36805 +               }
36806 +               if (core_if->dma_desc_enable == 0)
36807 +                       do_setup_in_status_phase(pcd);
36808 +       }
36809 +
36810 +       /* Complete the request */
36811 +       if (is_last) {
36812 +               dwc_otg_request_done(ep, req, 0);
36813 +               ep->dwc_ep.start_xfer_buff = 0;
36814 +               ep->dwc_ep.xfer_buff = 0;
36815 +               ep->dwc_ep.xfer_len = 0;
36816 +               return 1;
36817 +       }
36818 +       return 0;
36819 +}
36820 +
36821 +#ifdef DWC_UTE_CFI
36822 +/**
36823 + * This function calculates traverses all the CFI DMA descriptors and
36824 + * and accumulates the bytes that are left to be transfered.
36825 + *
36826 + * @return The total bytes left to transfered, or a negative value as failure
36827 + */
36828 +static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
36829 +{
36830 +       int32_t ret = 0;
36831 +       int i;
36832 +       struct dwc_otg_dma_desc *ddesc = NULL;
36833 +       struct cfi_ep *cfiep;
36834 +
36835 +       /* See if the pcd_ep has its respective cfi_ep mapped */
36836 +       cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
36837 +       if (!cfiep) {
36838 +               CFI_INFO("%s: Failed to find ep\n", __func__);
36839 +               return -1;
36840 +       }
36841 +
36842 +       ddesc = ep->dwc_ep.descs;
36843 +
36844 +       for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
36845 +
36846 +#if defined(PRINT_CFI_DMA_DESCS)
36847 +               print_desc(ddesc, ep->ep.name, i);
36848 +#endif
36849 +               ret += ddesc->status.b.bytes;
36850 +               ddesc++;
36851 +       }
36852 +
36853 +       if (ret)
36854 +               CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
36855 +                        ret);
36856 +
36857 +       return ret;
36858 +}
36859 +#endif
36860 +
36861 +/**
36862 + * This function completes the request for the EP.     If there are
36863 + * additional requests for the EP in the queue they will be started.
36864 + */
36865 +static void complete_ep(dwc_otg_pcd_ep_t * ep)
36866 +{
36867 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
36868 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
36869 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
36870 +           dev_if->in_ep_regs[ep->dwc_ep.num];
36871 +       deptsiz_data_t deptsiz;
36872 +       dev_dma_desc_sts_t desc_sts;
36873 +       dwc_otg_pcd_request_t *req = 0;
36874 +       dwc_otg_dev_dma_desc_t *dma_desc;
36875 +       uint32_t byte_count = 0;
36876 +       int is_last = 0;
36877 +       int i;
36878 +
36879 +       DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
36880 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"));
36881 +
36882 +       /* Get any pending requests */
36883 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
36884 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
36885 +               if (!req) {
36886 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
36887 +                       return;
36888 +               }
36889 +       } else {
36890 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
36891 +               return;
36892 +       }
36893 +
36894 +       DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
36895 +
36896 +       if (ep->dwc_ep.is_in) {
36897 +               deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz);
36898 +
36899 +               if (core_if->dma_enable) {
36900 +                       if (core_if->dma_desc_enable == 0) {
36901 +                               if (deptsiz.b.xfersize == 0
36902 +                                   && deptsiz.b.pktcnt == 0) {
36903 +                                       byte_count =
36904 +                                           ep->dwc_ep.xfer_len -
36905 +                                           ep->dwc_ep.xfer_count;
36906 +
36907 +                                       ep->dwc_ep.xfer_buff += byte_count;
36908 +                                       ep->dwc_ep.dma_addr += byte_count;
36909 +                                       ep->dwc_ep.xfer_count += byte_count;
36910 +
36911 +                                       DWC_DEBUGPL(DBG_PCDV,
36912 +                                                   "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
36913 +                                                   ep->dwc_ep.num,
36914 +                                                   (ep->dwc_ep.
36915 +                                                    is_in ? "IN" : "OUT"),
36916 +                                                   ep->dwc_ep.xfer_len,
36917 +                                                   deptsiz.b.xfersize,
36918 +                                                   deptsiz.b.pktcnt);
36919 +
36920 +                                       if (ep->dwc_ep.xfer_len <
36921 +                                           ep->dwc_ep.total_len) {
36922 +                                               dwc_otg_ep_start_transfer
36923 +                                                   (core_if, &ep->dwc_ep);
36924 +                                       } else if (ep->dwc_ep.sent_zlp) {
36925 +                                               /*      
36926 +                                                * This fragment of code should initiate 0 
36927 +                                                * length trasfer in case if it is queued
36928 +                                                * a trasfer with size divisible to EPs max 
36929 +                                                * packet size and with usb_request zero field 
36930 +                                                * is set, which means that after data is transfered, 
36931 +                                                * it is also should be transfered 
36932 +                                                * a 0 length packet at the end. For Slave and 
36933 +                                                * Buffer DMA modes in this case SW has 
36934 +                                                * to initiate 2 transfers one with transfer size, 
36935 +                                                * and the second with 0 size. For Desriptor 
36936 +                                                * DMA mode SW is able to initiate a transfer, 
36937 +                                                * which will handle all the packets including 
36938 +                                                * the last  0 legth.
36939 +                                                */
36940 +                                               ep->dwc_ep.sent_zlp = 0;
36941 +                                               dwc_otg_ep_start_zl_transfer
36942 +                                                   (core_if, &ep->dwc_ep);
36943 +                                       } else {
36944 +                                               is_last = 1;
36945 +                                       }
36946 +                               } else {
36947 +                                       DWC_WARN
36948 +                                           ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
36949 +                                            ep->dwc_ep.num,
36950 +                                            (ep->dwc_ep.is_in ? "IN" : "OUT"),
36951 +                                            deptsiz.b.xfersize,
36952 +                                            deptsiz.b.pktcnt);
36953 +                               }
36954 +                       } else {
36955 +                               dma_desc = ep->dwc_ep.desc_addr;
36956 +                               byte_count = 0;
36957 +                               ep->dwc_ep.sent_zlp = 0;
36958 +
36959 +#ifdef DWC_UTE_CFI
36960 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
36961 +                                        ep->dwc_ep.buff_mode);
36962 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
36963 +                                       int residue;
36964 +
36965 +                                       residue = cfi_calc_desc_residue(ep);
36966 +                                       if (residue < 0)
36967 +                                               return;
36968 +
36969 +                                       byte_count = residue;
36970 +                               } else {
36971 +#endif
36972 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
36973 +                                            ++i) {
36974 +                                       desc_sts = dma_desc->status;
36975 +                                       byte_count += desc_sts.b.bytes;
36976 +                                       dma_desc++;
36977 +                               }
36978 +#ifdef DWC_UTE_CFI
36979 +                               }
36980 +#endif
36981 +                               if (byte_count == 0) {
36982 +                                       ep->dwc_ep.xfer_count =
36983 +                                           ep->dwc_ep.total_len;
36984 +                                       is_last = 1;
36985 +                               } else {
36986 +                                       DWC_WARN("Incomplete transfer\n");
36987 +                               }
36988 +                       }
36989 +               } else {
36990 +                       if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
36991 +                               DWC_DEBUGPL(DBG_PCDV,
36992 +                                           "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
36993 +                                           ep->dwc_ep.num,
36994 +                                           ep->dwc_ep.is_in ? "IN" : "OUT",
36995 +                                           ep->dwc_ep.xfer_len,
36996 +                                           deptsiz.b.xfersize,
36997 +                                           deptsiz.b.pktcnt);
36998 +
36999 +                               /*      Check if the whole transfer was completed,  
37000 +                                *      if no, setup transfer for next portion of data
37001 +                                */
37002 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
37003 +                                       dwc_otg_ep_start_transfer(core_if,
37004 +                                                                 &ep->dwc_ep);
37005 +                               } else if (ep->dwc_ep.sent_zlp) {
37006 +                                       /*      
37007 +                                        * This fragment of code should initiate 0 
37008 +                                        * length trasfer in case if it is queued
37009 +                                        * a trasfer with size divisible to EPs max 
37010 +                                        * packet size and with usb_request zero field 
37011 +                                        * is set, which means that after data is transfered, 
37012 +                                        * it is also should be transfered 
37013 +                                        * a 0 length packet at the end. For Slave and 
37014 +                                        * Buffer DMA modes in this case SW has 
37015 +                                        * to initiate 2 transfers one with transfer size, 
37016 +                                        * and the second with 0 size. For Desriptor 
37017 +                                        * DMA mode SW is able to initiate a transfer, 
37018 +                                        * which will handle all the packets including 
37019 +                                        * the last  0 legth.
37020 +                                        */
37021 +                                       ep->dwc_ep.sent_zlp = 0;
37022 +                                       dwc_otg_ep_start_zl_transfer(core_if,
37023 +                                                                    &ep->
37024 +                                                                    dwc_ep);
37025 +                               } else {
37026 +                                       is_last = 1;
37027 +                               }
37028 +                       } else {
37029 +                               DWC_WARN
37030 +                                   ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
37031 +                                    ep->dwc_ep.num,
37032 +                                    (ep->dwc_ep.is_in ? "IN" : "OUT"),
37033 +                                    deptsiz.b.xfersize, deptsiz.b.pktcnt);
37034 +                       }
37035 +               }
37036 +       } else {
37037 +               dwc_otg_dev_out_ep_regs_t *out_ep_regs =
37038 +                   dev_if->out_ep_regs[ep->dwc_ep.num];
37039 +               desc_sts.d32 = 0;
37040 +               if (core_if->dma_enable) {
37041 +                       if (core_if->dma_desc_enable) {
37042 +                               dma_desc = ep->dwc_ep.desc_addr;
37043 +                               byte_count = 0;
37044 +                               ep->dwc_ep.sent_zlp = 0;
37045 +
37046 +#ifdef DWC_UTE_CFI
37047 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
37048 +                                        ep->dwc_ep.buff_mode);
37049 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
37050 +                                       int residue;
37051 +                                       residue = cfi_calc_desc_residue(ep);
37052 +                                       if (residue < 0)
37053 +                                               return;
37054 +                                       byte_count = residue;
37055 +                               } else {
37056 +#endif
37057 +
37058 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
37059 +                                            ++i) {
37060 +                                       desc_sts = dma_desc->status;
37061 +                                       byte_count += desc_sts.b.bytes;
37062 +                                       dma_desc++;
37063 +                               }
37064 +
37065 +#ifdef DWC_UTE_CFI
37066 +                               }
37067 +#endif
37068 +                               ep->dwc_ep.xfer_count = ep->dwc_ep.total_len
37069 +                                   - byte_count +
37070 +                                   ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3);
37071 +                               is_last = 1;
37072 +                       } else {
37073 +                               deptsiz.d32 = 0;
37074 +                               deptsiz.d32 =
37075 +                                   dwc_read_reg32(&out_ep_regs->doeptsiz);
37076 +
37077 +                               byte_count = (ep->dwc_ep.xfer_len -
37078 +                                             ep->dwc_ep.xfer_count -
37079 +                                             deptsiz.b.xfersize);
37080 +                               ep->dwc_ep.xfer_buff += byte_count;
37081 +                               ep->dwc_ep.dma_addr += byte_count;
37082 +                               ep->dwc_ep.xfer_count += byte_count;
37083 +
37084 +                               /*      Check if the whole transfer was completed,  
37085 +                                *      if no, setup transfer for next portion of data
37086 +                                */
37087 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
37088 +                                       dwc_otg_ep_start_transfer(core_if,
37089 +                                                                 &ep->dwc_ep);
37090 +                               } else if (ep->dwc_ep.sent_zlp) {
37091 +                                       /*      
37092 +                                        * This fragment of code should initiate 0 
37093 +                                        * length trasfer in case if it is queued
37094 +                                        * a trasfer with size divisible to EPs max 
37095 +                                        * packet size and with usb_request zero field 
37096 +                                        * is set, which means that after data is transfered, 
37097 +                                        * it is also should be transfered 
37098 +                                        * a 0 length packet at the end. For Slave and 
37099 +                                        * Buffer DMA modes in this case SW has 
37100 +                                        * to initiate 2 transfers one with transfer size, 
37101 +                                        * and the second with 0 size. For Desriptor 
37102 +                                        * DMA mode SW is able to initiate a transfer, 
37103 +                                        * which will handle all the packets including 
37104 +                                        * the last  0 legth.
37105 +                                        */
37106 +                                       ep->dwc_ep.sent_zlp = 0;
37107 +                                       dwc_otg_ep_start_zl_transfer(core_if,
37108 +                                                                    &ep->
37109 +                                                                    dwc_ep);
37110 +                               } else {
37111 +                                       is_last = 1;
37112 +                               }
37113 +                       }
37114 +               } else {
37115 +                       /*      Check if the whole transfer was completed,  
37116 +                        *      if no, setup transfer for next portion of data
37117 +                        */
37118 +                       if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
37119 +                               dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
37120 +                       } else if (ep->dwc_ep.sent_zlp) {
37121 +                               /*      
37122 +                                * This fragment of code should initiate 0 
37123 +                                * length trasfer in case if it is queued
37124 +                                * a trasfer with size divisible to EPs max 
37125 +                                * packet size and with usb_request zero field 
37126 +                                * is set, which means that after data is transfered, 
37127 +                                * it is also should be transfered 
37128 +                                * a 0 length packet at the end. For Slave and 
37129 +                                * Buffer DMA modes in this case SW has 
37130 +                                * to initiate 2 transfers one with transfer size, 
37131 +                                * and the second with 0 size. For Desriptor 
37132 +                                * DMA mode SW is able to initiate a transfer, 
37133 +                                * which will handle all the packets including 
37134 +                                * the last  0 legth.
37135 +                                */
37136 +                               ep->dwc_ep.sent_zlp = 0;
37137 +                               dwc_otg_ep_start_zl_transfer(core_if,
37138 +                                                            &ep->dwc_ep);
37139 +                       } else {
37140 +                               is_last = 1;
37141 +                       }
37142 +               }
37143 +
37144 +               DWC_DEBUGPL(DBG_PCDV,
37145 +                           "addr %p,    %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
37146 +                           &out_ep_regs->doeptsiz, ep->dwc_ep.num,
37147 +                           ep->dwc_ep.is_in ? "IN" : "OUT",
37148 +                           ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
37149 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
37150 +       }
37151 +
37152 +       /* Complete the request */
37153 +       if (is_last) {
37154 +#ifdef DWC_UTE_CFI
37155 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
37156 +                       req->actual = ep->dwc_ep.cfi_req_len - byte_count;
37157 +               } else {
37158 +#endif
37159 +               req->actual = ep->dwc_ep.xfer_count;
37160 +#ifdef DWC_UTE_CFI
37161 +               }
37162 +#endif
37163 +
37164 +               dwc_otg_request_done(ep, req, 0);
37165 +
37166 +               ep->dwc_ep.start_xfer_buff = 0;
37167 +               ep->dwc_ep.xfer_buff = 0;
37168 +               ep->dwc_ep.xfer_len = 0;
37169 +
37170 +               /* If there is a request in the queue start it. */
37171 +               start_next_request(ep);
37172 +       }
37173 +}
37174 +
37175 +#ifdef DWC_EN_ISOC
37176 +
37177 +/**
37178 + * This function BNA interrupt for Isochronous EPs
37179 + *
37180 + */
37181 +static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
37182 +{
37183 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
37184 +       volatile uint32_t *addr;
37185 +       depctl_data_t depctl = {.d32 = 0 };
37186 +       dwc_otg_pcd_t *pcd = ep->pcd;
37187 +       dwc_otg_dev_dma_desc_t *dma_desc;
37188 +       int i;
37189 +
37190 +       dma_desc =
37191 +           dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
37192 +
37193 +       if (dwc_ep->is_in) {
37194 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
37195 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
37196 +                       sts.d32 = dma_desc->status.d32;
37197 +                       sts.b_iso_in.bs = BS_HOST_READY;
37198 +                       dma_desc->status.d32 = sts.d32;
37199 +               }
37200 +       } else {
37201 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
37202 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
37203 +                       sts.d32 = dma_desc->status.d32;
37204 +                       sts.b_iso_out.bs = BS_HOST_READY;
37205 +                       dma_desc->status.d32 = sts.d32;
37206 +               }
37207 +       }
37208 +
37209 +       if (dwc_ep->is_in == 0) {
37210 +               addr =
37211 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
37212 +                   doepctl;
37213 +       } else {
37214 +               addr =
37215 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
37216 +       }
37217 +       depctl.b.epena = 1;
37218 +       dwc_modify_reg32(addr, depctl.d32, depctl.d32);
37219 +}
37220 +
37221 +/**
37222 + * This function sets latest iso packet information(non-PTI mode)
37223 + *
37224 + * @param core_if Programming view of DWC_otg controller.
37225 + * @param ep The EP to start the transfer on.
37226 + *
37227 + */
37228 +void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
37229 +{
37230 +       deptsiz_data_t deptsiz = {.d32 = 0 };
37231 +       dma_addr_t dma_addr;
37232 +       uint32_t offset;
37233 +
37234 +       if (ep->proc_buf_num)
37235 +               dma_addr = ep->dma_addr1;
37236 +       else
37237 +               dma_addr = ep->dma_addr0;
37238 +
37239 +       if (ep->is_in) {
37240 +               deptsiz.d32 =
37241 +                   dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->
37242 +                                  dieptsiz);
37243 +               offset = ep->data_per_frame;
37244 +       } else {
37245 +               deptsiz.d32 =
37246 +                   dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]->
37247 +                                  doeptsiz);
37248 +               offset =
37249 +                   ep->data_per_frame +
37250 +                   (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
37251 +       }
37252 +
37253 +       if (!deptsiz.b.xfersize) {
37254 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
37255 +               ep->pkt_info[ep->cur_pkt].offset =
37256 +                   ep->cur_pkt_dma_addr - dma_addr;
37257 +               ep->pkt_info[ep->cur_pkt].status = 0;
37258 +       } else {
37259 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
37260 +               ep->pkt_info[ep->cur_pkt].offset =
37261 +                   ep->cur_pkt_dma_addr - dma_addr;
37262 +               ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
37263 +       }
37264 +       ep->cur_pkt_addr += offset;
37265 +       ep->cur_pkt_dma_addr += offset;
37266 +       ep->cur_pkt++;
37267 +}
37268 +
37269 +/**
37270 + * This function sets latest iso packet information(DDMA mode)
37271 + *
37272 + * @param core_if Programming view of DWC_otg controller.
37273 + * @param dwc_ep The EP to start the transfer on.
37274 + *
37275 + */
37276 +static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
37277 +                                  dwc_ep_t * dwc_ep)
37278 +{
37279 +       dwc_otg_dev_dma_desc_t *dma_desc;
37280 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
37281 +       iso_pkt_info_t *iso_packet;
37282 +       uint32_t data_per_desc;
37283 +       uint32_t offset;
37284 +       int i, j;
37285 +
37286 +       iso_packet = dwc_ep->pkt_info;
37287 +
37288 +       /** Reinit closed DMA Descriptors*/
37289 +       /** ISO OUT EP */
37290 +       if (dwc_ep->is_in == 0) {
37291 +               dma_desc =
37292 +                   dwc_ep->iso_desc_addr +
37293 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
37294 +               offset = 0;
37295 +
37296 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
37297 +                    i += dwc_ep->pkt_per_frm) {
37298 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
37299 +                               data_per_desc =
37300 +                                   ((j + 1) * dwc_ep->maxpacket >
37301 +                                    dwc_ep->data_per_frame) ? dwc_ep->
37302 +                                   data_per_frame -
37303 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
37304 +                               data_per_desc +=
37305 +                                   (data_per_desc % 4) ? (4 -
37306 +                                                          data_per_desc %
37307 +                                                          4) : 0;
37308 +
37309 +                               sts.d32 = dma_desc->status.d32;
37310 +
37311 +                               /* Write status in iso_packet_decsriptor  */
37312 +                               iso_packet->status =
37313 +                                   sts.b_iso_out.rxsts +
37314 +                                   (sts.b_iso_out.bs ^ BS_DMA_DONE);
37315 +                               if (iso_packet->status) {
37316 +                                       iso_packet->status = -DWC_E_NO_DATA;
37317 +                               }
37318 +
37319 +                               /* Received data length */
37320 +                               if (!sts.b_iso_out.rxbytes) {
37321 +                                       iso_packet->length =
37322 +                                           data_per_desc -
37323 +                                           sts.b_iso_out.rxbytes;
37324 +                               } else {
37325 +                                       iso_packet->length =
37326 +                                           data_per_desc -
37327 +                                           sts.b_iso_out.rxbytes + (4 -
37328 +                                                                    dwc_ep->
37329 +                                                                    data_per_frame
37330 +                                                                    % 4);
37331 +                               }
37332 +
37333 +                               iso_packet->offset = offset;
37334 +
37335 +                               offset += data_per_desc;
37336 +                               dma_desc++;
37337 +                               iso_packet++;
37338 +                       }
37339 +               }
37340 +
37341 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
37342 +                       data_per_desc =
37343 +                           ((j + 1) * dwc_ep->maxpacket >
37344 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
37345 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
37346 +                       data_per_desc +=
37347 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
37348 +
37349 +                       sts.d32 = dma_desc->status.d32;
37350 +
37351 +                       /* Write status in iso_packet_decsriptor  */
37352 +                       iso_packet->status =
37353 +                           sts.b_iso_out.rxsts +
37354 +                           (sts.b_iso_out.bs ^ BS_DMA_DONE);
37355 +                       if (iso_packet->status) {
37356 +                               iso_packet->status = -DWC_E_NO_DATA;
37357 +                       }
37358 +
37359 +                       /* Received data length */
37360 +                       iso_packet->length =
37361 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
37362 +
37363 +                       iso_packet->offset = offset;
37364 +
37365 +                       offset += data_per_desc;
37366 +                       iso_packet++;
37367 +                       dma_desc++;
37368 +               }
37369 +
37370 +               sts.d32 = dma_desc->status.d32;
37371 +
37372 +               /* Write status in iso_packet_decsriptor  */
37373 +               iso_packet->status =
37374 +                   sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
37375 +               if (iso_packet->status) {
37376 +                       iso_packet->status = -DWC_E_NO_DATA;
37377 +               }
37378 +               /* Received data length */
37379 +               if (!sts.b_iso_out.rxbytes) {
37380 +                       iso_packet->length =
37381 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
37382 +               } else {
37383 +                       iso_packet->length =
37384 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
37385 +                           (4 - dwc_ep->data_per_frame % 4);
37386 +               }
37387 +
37388 +               iso_packet->offset = offset;
37389 +       } else {
37390 +/** ISO IN EP */
37391 +
37392 +               dma_desc =
37393 +                   dwc_ep->iso_desc_addr +
37394 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
37395 +
37396 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
37397 +                       sts.d32 = dma_desc->status.d32;
37398 +
37399 +                       /* Write status in iso packet descriptor */
37400 +                       iso_packet->status =
37401 +                           sts.b_iso_in.txsts +
37402 +                           (sts.b_iso_in.bs ^ BS_DMA_DONE);
37403 +                       if (iso_packet->status != 0) {
37404 +                               iso_packet->status = -DWC_E_NO_DATA;
37405 +
37406 +                       }
37407 +                       /* Bytes has been transfered */
37408 +                       iso_packet->length =
37409 +                           dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
37410 +
37411 +                       dma_desc++;
37412 +                       iso_packet++;
37413 +               }
37414 +
37415 +               sts.d32 = dma_desc->status.d32;
37416 +               while (sts.b_iso_in.bs == BS_DMA_BUSY) {
37417 +                       sts.d32 = dma_desc->status.d32;
37418 +               }
37419 +
37420 +               /* Write status in iso packet descriptor ??? do be done with ERROR codes */
37421 +               iso_packet->status =
37422 +                   sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
37423 +               if (iso_packet->status != 0) {
37424 +                       iso_packet->status = -DWC_E_NO_DATA;
37425 +               }
37426 +
37427 +               /* Bytes has been transfered */
37428 +               iso_packet->length =
37429 +                   dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
37430 +       }
37431 +}
37432 +
37433 +/**
37434 + * This function reinitialize DMA Descriptors for Isochronous transfer
37435 + *
37436 + * @param core_if Programming view of DWC_otg controller.
37437 + * @param dwc_ep The EP to start the transfer on.
37438 + *
37439 + */
37440 +static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
37441 +{
37442 +       int i, j;
37443 +       dwc_otg_dev_dma_desc_t *dma_desc;
37444 +       dma_addr_t dma_ad;
37445 +       volatile uint32_t *addr;
37446 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
37447 +       uint32_t data_per_desc;
37448 +
37449 +       if (dwc_ep->is_in == 0) {
37450 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
37451 +       } else {
37452 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
37453 +       }
37454 +
37455 +       if (dwc_ep->proc_buf_num == 0) {
37456 +               /** Buffer 0 descriptors setup */
37457 +               dma_ad = dwc_ep->dma_addr0;
37458 +       } else {
37459 +               /** Buffer 1 descriptors setup */
37460 +               dma_ad = dwc_ep->dma_addr1;
37461 +       }
37462 +
37463 +       /** Reinit closed DMA Descriptors*/
37464 +       /** ISO OUT EP */
37465 +       if (dwc_ep->is_in == 0) {
37466 +               dma_desc =
37467 +                   dwc_ep->iso_desc_addr +
37468 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
37469 +
37470 +               sts.b_iso_out.bs = BS_HOST_READY;
37471 +               sts.b_iso_out.rxsts = 0;
37472 +               sts.b_iso_out.l = 0;
37473 +               sts.b_iso_out.sp = 0;
37474 +               sts.b_iso_out.ioc = 0;
37475 +               sts.b_iso_out.pid = 0;
37476 +               sts.b_iso_out.framenum = 0;
37477 +
37478 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
37479 +                    i += dwc_ep->pkt_per_frm) {
37480 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
37481 +                               data_per_desc =
37482 +                                   ((j + 1) * dwc_ep->maxpacket >
37483 +                                    dwc_ep->data_per_frame) ? dwc_ep->
37484 +                                   data_per_frame -
37485 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
37486 +                               data_per_desc +=
37487 +                                   (data_per_desc % 4) ? (4 -
37488 +                                                          data_per_desc %
37489 +                                                          4) : 0;
37490 +                               sts.b_iso_out.rxbytes = data_per_desc;
37491 +                               dma_desc->buf = dma_ad;
37492 +                               dma_desc->status.d32 = sts.d32;
37493 +
37494 +                               dma_ad += data_per_desc;
37495 +                               dma_desc++;
37496 +                       }
37497 +               }
37498 +
37499 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
37500 +
37501 +                       data_per_desc =
37502 +                           ((j + 1) * dwc_ep->maxpacket >
37503 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
37504 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
37505 +                       data_per_desc +=
37506 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
37507 +                       sts.b_iso_out.rxbytes = data_per_desc;
37508 +
37509 +                       dma_desc->buf = dma_ad;
37510 +                       dma_desc->status.d32 = sts.d32;
37511 +
37512 +                       dma_desc++;
37513 +                       dma_ad += data_per_desc;
37514 +               }
37515 +
37516 +               sts.b_iso_out.ioc = 1;
37517 +               sts.b_iso_out.l = dwc_ep->proc_buf_num;
37518 +
37519 +               data_per_desc =
37520 +                   ((j + 1) * dwc_ep->maxpacket >
37521 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
37522 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
37523 +               data_per_desc +=
37524 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
37525 +               sts.b_iso_out.rxbytes = data_per_desc;
37526 +
37527 +               dma_desc->buf = dma_ad;
37528 +               dma_desc->status.d32 = sts.d32;
37529 +       } else {
37530 +/** ISO IN EP */
37531 +
37532 +               dma_desc =
37533 +                   dwc_ep->iso_desc_addr +
37534 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
37535 +
37536 +               sts.b_iso_in.bs = BS_HOST_READY;
37537 +               sts.b_iso_in.txsts = 0;
37538 +               sts.b_iso_in.sp = 0;
37539 +               sts.b_iso_in.ioc = 0;
37540 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
37541 +               sts.b_iso_in.framenum = dwc_ep->next_frame;
37542 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
37543 +               sts.b_iso_in.l = 0;
37544 +
37545 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
37546 +                       dma_desc->buf = dma_ad;
37547 +                       dma_desc->status.d32 = sts.d32;
37548 +
37549 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
37550 +                       dma_ad += dwc_ep->data_per_frame;
37551 +                       dma_desc++;
37552 +               }
37553 +
37554 +               sts.b_iso_in.ioc = 1;
37555 +               sts.b_iso_in.l = dwc_ep->proc_buf_num;
37556 +
37557 +               dma_desc->buf = dma_ad;
37558 +               dma_desc->status.d32 = sts.d32;
37559 +
37560 +               dwc_ep->next_frame =
37561 +                   sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
37562 +       }
37563 +       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
37564 +}
37565 +
37566 +/**
37567 + * This function is to handle Iso EP transfer complete interrupt
37568 + * in case Iso out packet was dropped
37569 + *
37570 + * @param core_if Programming view of DWC_otg controller.
37571 + * @param dwc_ep The EP for wihich transfer complete was asserted
37572 + *
37573 + */
37574 +static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
37575 +                                          dwc_ep_t * dwc_ep)
37576 +{
37577 +       uint32_t dma_addr;
37578 +       uint32_t drp_pkt;
37579 +       uint32_t drp_pkt_cnt;
37580 +       deptsiz_data_t deptsiz = {.d32 = 0 };
37581 +       depctl_data_t depctl = {.d32 = 0 };
37582 +       int i;
37583 +
37584 +       deptsiz.d32 =
37585 +           dwc_read_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->
37586 +                          doeptsiz);
37587 +
37588 +       drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
37589 +       drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
37590 +
37591 +       /* Setting dropped packets status */
37592 +       for (i = 0; i < drp_pkt_cnt; ++i) {
37593 +               dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
37594 +               drp_pkt++;
37595 +               deptsiz.b.pktcnt--;
37596 +       }
37597 +
37598 +       if (deptsiz.b.pktcnt > 0) {
37599 +               deptsiz.b.xfersize =
37600 +                   dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
37601 +                                       deptsiz.b.pktcnt) * dwc_ep->maxpacket;
37602 +       } else {
37603 +               deptsiz.b.xfersize = 0;
37604 +               deptsiz.b.pktcnt = 0;
37605 +       }
37606 +
37607 +       dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
37608 +                       deptsiz.d32);
37609 +
37610 +       if (deptsiz.b.pktcnt > 0) {
37611 +               if (dwc_ep->proc_buf_num) {
37612 +                       dma_addr =
37613 +                           dwc_ep->dma_addr1 + dwc_ep->xfer_len -
37614 +                           deptsiz.b.xfersize;
37615 +               } else {
37616 +                       dma_addr =
37617 +                           dwc_ep->dma_addr0 + dwc_ep->xfer_len -
37618 +                           deptsiz.b.xfersize;;
37619 +               }
37620 +
37621 +               dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->
37622 +                               doepdma, dma_addr);
37623 +
37624 +               /** Re-enable endpoint, clear nak  */
37625 +               depctl.d32 = 0;
37626 +               depctl.b.epena = 1;
37627 +               depctl.b.cnak = 1;
37628 +
37629 +               dwc_modify_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->
37630 +                                doepctl, depctl.d32, depctl.d32);
37631 +               return 0;
37632 +       } else {
37633 +               return 1;
37634 +       }
37635 +}
37636 +
37637 +/**
37638 + * This function sets iso packets information(PTI mode)
37639 + *
37640 + * @param core_if Programming view of DWC_otg controller.
37641 + * @param ep The EP to start the transfer on.
37642 + *
37643 + */
37644 +static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
37645 +{
37646 +       int i, j;
37647 +       dma_addr_t dma_ad;
37648 +       iso_pkt_info_t *packet_info = ep->pkt_info;
37649 +       uint32_t offset;
37650 +       uint32_t frame_data;
37651 +       deptsiz_data_t deptsiz;
37652 +
37653 +       if (ep->proc_buf_num == 0) {
37654 +               /** Buffer 0 descriptors setup */
37655 +               dma_ad = ep->dma_addr0;
37656 +       } else {
37657 +               /** Buffer 1 descriptors setup */
37658 +               dma_ad = ep->dma_addr1;
37659 +       }
37660 +
37661 +       if (ep->is_in) {
37662 +               deptsiz.d32 =
37663 +                   dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->
37664 +                                  dieptsiz);
37665 +       } else {
37666 +               deptsiz.d32 =
37667 +                   dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]->
37668 +                                  doeptsiz);
37669 +       }
37670 +
37671 +       if (!deptsiz.b.xfersize) {
37672 +               offset = 0;
37673 +               for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
37674 +                       frame_data = ep->data_per_frame;
37675 +                       for (j = 0; j < ep->pkt_per_frm; ++j) {
37676 +
37677 +                               /* Packet status - is not set as initially 
37678 +                                * it is set to 0 and if packet was sent 
37679 +                                successfully, status field will remain 0*/
37680 +
37681 +                               /* Bytes has been transfered */
37682 +                               packet_info->length =
37683 +                                   (ep->maxpacket <
37684 +                                    frame_data) ? ep->maxpacket : frame_data;
37685 +
37686 +                               /* Received packet offset */
37687 +                               packet_info->offset = offset;
37688 +                               offset += packet_info->length;
37689 +                               frame_data -= packet_info->length;
37690 +
37691 +                               packet_info++;
37692 +                       }
37693 +               }
37694 +               return 1;
37695 +       } else {
37696 +               /* This is a workaround for in case of Transfer Complete with 
37697 +                * PktDrpSts interrupts merging - in this case Transfer complete 
37698 +                * interrupt for Isoc Out Endpoint is asserted without PktDrpSts 
37699 +                * set and with DOEPTSIZ register non zero. Investigations showed,
37700 +                * that this happens when Out packet is dropped, but because of 
37701 +                * interrupts merging during first interrupt handling PktDrpSts
37702 +                * bit is cleared and for next merged interrupts it is not reset.
37703 +                * In this case SW hadles the interrupt as if PktDrpSts bit is set.
37704 +                */
37705 +               if (ep->is_in) {
37706 +                       return 1;
37707 +               } else {
37708 +                       return handle_iso_out_pkt_dropped(core_if, ep);
37709 +               }
37710 +       }
37711 +}
37712 +
37713 +/**
37714 + * This function is to handle Iso EP transfer complete interrupt
37715 + *
37716 + * @param pcd The PCD
37717 + * @param ep The EP for which transfer complete was asserted
37718 + *
37719 + */
37720 +static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
37721 +{
37722 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
37723 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
37724 +       uint8_t is_last = 0;
37725 +
37726 +       if(ep->dwc_ep.next_frame == 0xffffffff) {
37727 +               DWC_WARN("Next frame is not set!\n");
37728 +               return;
37729 +       }
37730 +
37731 +       if (core_if->dma_enable) {
37732 +               if (core_if->dma_desc_enable) {
37733 +                       set_ddma_iso_pkts_info(core_if, dwc_ep);
37734 +                       reinit_ddma_iso_xfer(core_if, dwc_ep);
37735 +                       is_last = 1;
37736 +               } else {
37737 +                       if (core_if->pti_enh_enable) {
37738 +                               if (set_iso_pkts_info(core_if, dwc_ep)) {
37739 +                                       dwc_ep->proc_buf_num =
37740 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
37741 +                                       dwc_otg_iso_ep_start_buf_transfer
37742 +                                           (core_if, dwc_ep);
37743 +                                       is_last = 1;
37744 +                               }
37745 +                       } else {
37746 +                               set_current_pkt_info(core_if, dwc_ep);
37747 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
37748 +                                       is_last = 1;
37749 +                                       dwc_ep->cur_pkt = 0;
37750 +                                       dwc_ep->proc_buf_num =
37751 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
37752 +                                       if (dwc_ep->proc_buf_num) {
37753 +                                               dwc_ep->cur_pkt_addr =
37754 +                                                   dwc_ep->xfer_buff1;
37755 +                                               dwc_ep->cur_pkt_dma_addr =
37756 +                                                   dwc_ep->dma_addr1;
37757 +                                       } else {
37758 +                                               dwc_ep->cur_pkt_addr =
37759 +                                                   dwc_ep->xfer_buff0;
37760 +                                               dwc_ep->cur_pkt_dma_addr =
37761 +                                                   dwc_ep->dma_addr0;
37762 +                                       }
37763 +
37764 +                               }
37765 +                               dwc_otg_iso_ep_start_frm_transfer(core_if,
37766 +                                                                 dwc_ep);
37767 +                       }
37768 +               }
37769 +       } else {
37770 +               set_current_pkt_info(core_if, dwc_ep);
37771 +               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
37772 +                       is_last = 1;
37773 +                       dwc_ep->cur_pkt = 0;
37774 +                       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
37775 +                       if (dwc_ep->proc_buf_num) {
37776 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
37777 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
37778 +                       } else {
37779 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
37780 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
37781 +                       }
37782 +
37783 +               }
37784 +               dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
37785 +       }
37786 +       if (is_last)
37787 +               dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
37788 +}
37789 +#endif                         /* DWC_EN_ISOC */
37790 +
37791 +/**
37792 + * This function handles EP0 Control transfers.
37793 + *
37794 + * The state of the control tranfers are tracked in
37795 + * <code>ep0state</code>.
37796 + */
37797 +static void handle_ep0(dwc_otg_pcd_t * pcd)
37798 +{
37799 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
37800 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
37801 +       dev_dma_desc_sts_t desc_sts;
37802 +       deptsiz0_data_t deptsiz;
37803 +       uint32_t byte_count;
37804 +
37805 +#ifdef DEBUG_EP0
37806 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
37807 +       print_ep0_state(pcd);
37808 +#endif
37809 +
37810 +//      DWC_PRINTF("HANDLE EP0\n");
37811 +
37812 +       switch (pcd->ep0state) {
37813 +       case EP0_DISCONNECT:
37814 +               break;
37815 +
37816 +       case EP0_IDLE:
37817 +               pcd->request_config = 0;
37818 +
37819 +               pcd_setup(pcd);
37820 +               break;
37821 +
37822 +       case EP0_IN_DATA_PHASE:
37823 +#ifdef DEBUG_EP0
37824 +               DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
37825 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
37826 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
37827 +#endif
37828 +
37829 +               if (core_if->dma_enable != 0) {
37830 +                       /*
37831 +                        * For EP0 we can only program 1 packet at a time so we
37832 +                        * need to do the make calculations after each complete.
37833 +                        * Call write_packet to make the calculations, as in
37834 +                        * slave mode, and use those values to determine if we
37835 +                        * can complete.
37836 +                        */
37837 +                       if (core_if->dma_desc_enable == 0) {
37838 +                               deptsiz.d32 =
37839 +                                   dwc_read_reg32(&core_if->dev_if->
37840 +                                                  in_ep_regs[0]->dieptsiz);
37841 +                               byte_count =
37842 +                                   ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
37843 +                       } else {
37844 +                               desc_sts =
37845 +                                   core_if->dev_if->in_desc_addr->status;
37846 +                               byte_count =
37847 +                                   ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
37848 +                       }
37849 +                       ep0->dwc_ep.xfer_count += byte_count;
37850 +                       ep0->dwc_ep.xfer_buff += byte_count;
37851 +                       ep0->dwc_ep.dma_addr += byte_count;
37852 +               }
37853 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
37854 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
37855 +                                                     &ep0->dwc_ep);
37856 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
37857 +               } else if (ep0->dwc_ep.sent_zlp) {
37858 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
37859 +                                                     &ep0->dwc_ep);
37860 +                       ep0->dwc_ep.sent_zlp = 0;
37861 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
37862 +               } else {
37863 +                       ep0_complete_request(ep0);
37864 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
37865 +               }
37866 +               break;
37867 +       case EP0_OUT_DATA_PHASE:
37868 +#ifdef DEBUG_EP0
37869 +               DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
37870 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
37871 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
37872 +#endif
37873 +               if (core_if->dma_enable != 0) {
37874 +                       if (core_if->dma_desc_enable == 0) {
37875 +                               deptsiz.d32 =
37876 +                                   dwc_read_reg32(&core_if->dev_if->
37877 +                                                  out_ep_regs[0]->doeptsiz);
37878 +                               byte_count =
37879 +                                   ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
37880 +                       } else {
37881 +                               desc_sts =
37882 +                                   core_if->dev_if->out_desc_addr->status;
37883 +                               byte_count =
37884 +                                   ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
37885 +                       }
37886 +                       ep0->dwc_ep.xfer_count += byte_count;
37887 +                       ep0->dwc_ep.xfer_buff += byte_count;
37888 +                       ep0->dwc_ep.dma_addr += byte_count;
37889 +               }
37890 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
37891 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
37892 +                                                     &ep0->dwc_ep);
37893 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
37894 +               } else if (ep0->dwc_ep.sent_zlp) {
37895 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
37896 +                                                     &ep0->dwc_ep);
37897 +                       ep0->dwc_ep.sent_zlp = 0;
37898 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
37899 +               } else {
37900 +                       ep0_complete_request(ep0);
37901 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
37902 +               }
37903 +               break;
37904 +
37905 +       case EP0_IN_STATUS_PHASE:
37906 +       case EP0_OUT_STATUS_PHASE:
37907 +               DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
37908 +               ep0_complete_request(ep0);
37909 +               pcd->ep0state = EP0_IDLE;
37910 +               ep0->stopped = 1;
37911 +               ep0->dwc_ep.is_in = 0;  /* OUT for next SETUP */
37912 +
37913 +               /* Prepare for more SETUP Packets */
37914 +               if (core_if->dma_enable) {
37915 +                       ep0_out_start(core_if, pcd);
37916 +               }
37917 +               break;
37918 +
37919 +       case EP0_STALL:
37920 +               DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
37921 +               break;
37922 +       }
37923 +#ifdef DEBUG_EP0
37924 +       print_ep0_state(pcd);
37925 +#endif
37926 +}
37927 +
37928 +/**
37929 + * Restart transfer
37930 + */
37931 +static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
37932 +{
37933 +       dwc_otg_core_if_t *core_if;
37934 +       dwc_otg_dev_if_t *dev_if;
37935 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
37936 +       dwc_otg_pcd_ep_t *ep;
37937 +
37938 +       ep = get_in_ep(pcd, epnum);
37939 +
37940 +#ifdef DWC_EN_ISOC
37941 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
37942 +               return;
37943 +       }
37944 +#endif                         /* DWC_EN_ISOC  */
37945 +
37946 +       core_if = GET_CORE_IF(pcd);
37947 +       dev_if = core_if->dev_if;
37948 +
37949 +       dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz);
37950 +
37951 +       DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
37952 +                   " stopped=%d\n", ep->dwc_ep.xfer_buff,
37953 +                   ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
37954 +       /*
37955 +        * If xfersize is 0 and pktcnt in not 0, resend the last packet.
37956 +        */
37957 +       if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
37958 +           ep->dwc_ep.start_xfer_buff != 0) {
37959 +               if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
37960 +                       ep->dwc_ep.xfer_count = 0;
37961 +                       ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
37962 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
37963 +               } else {
37964 +                       ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
37965 +                       /* convert packet size to dwords. */
37966 +                       ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
37967 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
37968 +               }
37969 +               ep->stopped = 0;
37970 +               DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
37971 +                           "xfer_len=%0x stopped=%d\n",
37972 +                           ep->dwc_ep.xfer_buff,
37973 +                           ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
37974 +                           ep->stopped);
37975 +               if (epnum == 0) {
37976 +                       dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
37977 +               } else {
37978 +                       dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
37979 +               }
37980 +       }
37981 +}
37982 +
37983 +/**
37984 + * handle the IN EP disable interrupt.
37985 + */
37986 +static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
37987 +                                            const uint32_t epnum)
37988 +{
37989 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
37990 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
37991 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
37992 +       dctl_data_t dctl = {.d32 = 0 };
37993 +       dwc_otg_pcd_ep_t *ep;
37994 +       dwc_ep_t *dwc_ep;
37995 +
37996 +       ep = get_in_ep(pcd, epnum);
37997 +       dwc_ep = &ep->dwc_ep;
37998 +
37999 +       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
38000 +               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
38001 +               return;
38002 +       }
38003 +
38004 +       DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
38005 +                   dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl));
38006 +       dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz);
38007 +
38008 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
38009 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
38010 +
38011 +       if (ep->stopped) {
38012 +               /* Flush the Tx FIFO */
38013 +               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
38014 +               /* Clear the Global IN NP NAK */
38015 +               dctl.d32 = 0;
38016 +               dctl.b.cgnpinnak = 1;
38017 +               dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, 0);
38018 +               /* Restart the transaction */
38019 +               if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
38020 +                       restart_transfer(pcd, epnum);
38021 +               }
38022 +       } else {
38023 +               /* Restart the transaction */
38024 +               if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
38025 +                       restart_transfer(pcd, epnum);
38026 +               }
38027 +               DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
38028 +       }
38029 +}
38030 +
38031 +/**
38032 + * Handler for the IN EP timeout handshake interrupt.
38033 + */
38034 +static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
38035 +                                            const uint32_t epnum)
38036 +{
38037 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
38038 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
38039 +
38040 +#ifdef DEBUG
38041 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
38042 +       uint32_t num = 0;
38043 +#endif
38044 +       dctl_data_t dctl = {.d32 = 0 };
38045 +       dwc_otg_pcd_ep_t *ep;
38046 +
38047 +       gintmsk_data_t intr_mask = {.d32 = 0 };
38048 +
38049 +       ep = get_in_ep(pcd, epnum);
38050 +
38051 +       /* Disable the NP Tx Fifo Empty Interrrupt */
38052 +       if (!core_if->dma_enable) {
38053 +               intr_mask.b.nptxfempty = 1;
38054 +               dwc_modify_reg32(&core_if->core_global_regs->gintmsk,
38055 +                                intr_mask.d32, 0);
38056 +       }
38057 +       /** @todo NGS Check EP type.
38058 +        * Implement for Periodic EPs */
38059 +       /*
38060 +        * Non-periodic EP
38061 +        */
38062 +       /* Enable the Global IN NAK Effective Interrupt */
38063 +       intr_mask.b.ginnakeff = 1;
38064 +       dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
38065 +
38066 +       /* Set Global IN NAK */
38067 +       dctl.b.sgnpinnak = 1;
38068 +       dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
38069 +
38070 +       ep->stopped = 1;
38071 +
38072 +#ifdef DEBUG
38073 +       dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[num]->dieptsiz);
38074 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
38075 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
38076 +#endif
38077 +
38078 +#ifdef DISABLE_PERIODIC_EP
38079 +       /*
38080 +        * Set the NAK bit for this EP to
38081 +        * start the disable process.
38082 +        */
38083 +       diepctl.d32 = 0;
38084 +       diepctl.b.snak = 1;
38085 +       dwc_modify_reg32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
38086 +                        diepctl.d32);
38087 +       ep->disabling = 1;
38088 +       ep->stopped = 1;
38089 +#endif
38090 +}
38091 +
38092 +/**
38093 + * Handler for the IN EP NAK interrupt. 
38094 + */
38095 +static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
38096 +                                           const uint32_t epnum)
38097 +{
38098 +       /** @todo implement ISR */
38099 +       dwc_otg_core_if_t *core_if;
38100 +       diepmsk_data_t intr_mask = {.d32 = 0 };
38101 +
38102 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
38103 +       core_if = GET_CORE_IF(pcd);
38104 +       intr_mask.b.nak = 1;
38105 +
38106 +       if (core_if->multiproc_int_enable) {
38107 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
38108 +                                diepeachintmsk[epnum], intr_mask.d32, 0);
38109 +       } else {
38110 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->diepmsk,
38111 +                                intr_mask.d32, 0);
38112 +       }
38113 +
38114 +       return 1;
38115 +}
38116 +
38117 +/**
38118 + * Handler for the OUT EP Babble interrupt. 
38119 + */
38120 +static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
38121 +                                               const uint32_t epnum)
38122 +{
38123 +       /** @todo implement ISR */
38124 +       dwc_otg_core_if_t *core_if;
38125 +       doepmsk_data_t intr_mask = {.d32 = 0 };
38126 +
38127 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
38128 +                  "OUT EP Babble");
38129 +       core_if = GET_CORE_IF(pcd);
38130 +       intr_mask.b.babble = 1;
38131 +
38132 +       if (core_if->multiproc_int_enable) {
38133 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
38134 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
38135 +       } else {
38136 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk,
38137 +                                intr_mask.d32, 0);
38138 +       }
38139 +
38140 +       return 1;
38141 +}
38142 +
38143 +/**
38144 + * Handler for the OUT EP NAK interrupt. 
38145 + */
38146 +static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
38147 +                                            const uint32_t epnum)
38148 +{
38149 +       /** @todo implement ISR */
38150 +       dwc_otg_core_if_t *core_if;
38151 +       doepmsk_data_t intr_mask = {.d32 = 0 };
38152 +
38153 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
38154 +       core_if = GET_CORE_IF(pcd);
38155 +       intr_mask.b.nak = 1;
38156 +
38157 +       if (core_if->multiproc_int_enable) {
38158 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
38159 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
38160 +       } else {
38161 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk,
38162 +                                intr_mask.d32, 0);
38163 +       }
38164 +
38165 +       return 1;
38166 +}
38167 +
38168 +/**
38169 + * Handler for the OUT EP NYET interrupt. 
38170 + */
38171 +static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
38172 +                                             const uint32_t epnum)
38173 +{
38174 +       /** @todo implement ISR */
38175 +       dwc_otg_core_if_t *core_if;
38176 +       doepmsk_data_t intr_mask = {.d32 = 0 };
38177 +
38178 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
38179 +       core_if = GET_CORE_IF(pcd);
38180 +       intr_mask.b.nyet = 1;
38181 +
38182 +       if (core_if->multiproc_int_enable) {
38183 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->
38184 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
38185 +       } else {
38186 +               dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk,
38187 +                                intr_mask.d32, 0);
38188 +       }
38189 +
38190 +       return 1;
38191 +}
38192 +
38193 +/**
38194 + * This interrupt indicates that an IN EP has a pending Interrupt.
38195 + * The sequence for handling the IN EP interrupt is shown below:
38196 + * -#  Read the Device All Endpoint Interrupt register
38197 + * -#  Repeat the following for each IN EP interrupt bit set (from
38198 + *             LSB to MSB).
38199 + * -#  Read the Device Endpoint Interrupt (DIEPINTn) register
38200 + * -#  If "Transfer Complete" call the request complete function
38201 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
38202 + * -#  If "AHB Error Interrupt" log error
38203 + * -#  If "Time-out Handshake" log error
38204 + * -#  If "IN Token Received when TxFIFO Empty" write packet to Tx
38205 + *             FIFO.
38206 + * -#  If "IN Token EP Mismatch" (disable, this is handled by EP
38207 + *             Mismatch Interrupt)
38208 + */
38209 +static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
38210 +{
38211 +#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
38212 +do { \
38213 +               diepint_data_t diepint = {.d32=0}; \
38214 +               diepint.b.__intr = 1; \
38215 +               dwc_write_reg32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
38216 +               diepint.d32); \
38217 +} while (0)
38218 +
38219 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
38220 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
38221 +       diepint_data_t diepint = {.d32 = 0 };
38222 +       dctl_data_t dctl = {.d32 = 0 };
38223 +       depctl_data_t depctl = {.d32 = 0 };
38224 +       uint32_t ep_intr;
38225 +       uint32_t epnum = 0;
38226 +       dwc_otg_pcd_ep_t *ep;
38227 +       dwc_ep_t *dwc_ep;
38228 +       gintmsk_data_t intr_mask = {.d32 = 0 };
38229 +
38230 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
38231 +
38232 +       /* Read in the device interrupt bits */
38233 +       ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
38234 +
38235 +       /* Service the Device IN interrupts for each endpoint */
38236 +       while (ep_intr) {
38237 +               if (ep_intr & 0x1) {
38238 +                       uint32_t empty_msk;
38239 +                       /* Get EP pointer */
38240 +                       ep = get_in_ep(pcd, epnum);
38241 +                       dwc_ep = &ep->dwc_ep;
38242 +
38243 +                       depctl.d32 =
38244 +                           dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl);
38245 +                       empty_msk =
38246 +                           dwc_read_reg32(&dev_if->dev_global_regs->
38247 +                                          dtknqr4_fifoemptymsk);
38248 +
38249 +                       DWC_DEBUGPL(DBG_PCDV,
38250 +                                   "IN EP INTERRUPT - %d\nepmty_msk - %8x  diepctl - %8x\n",
38251 +                                   epnum, empty_msk, depctl.d32);
38252 +
38253 +                       DWC_DEBUGPL(DBG_PCD,
38254 +                                   "EP%d-%s: type=%d, mps=%d\n",
38255 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
38256 +                                   dwc_ep->type, dwc_ep->maxpacket);
38257 +
38258 +                       diepint.d32 =
38259 +                           dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
38260 +
38261 +                       DWC_DEBUGPL(DBG_PCDV,
38262 +                                   "EP %d Interrupt Register - 0x%x\n", epnum,
38263 +                                   diepint.d32);
38264 +                       /* Transfer complete */
38265 +                       if (diepint.b.xfercompl) {
38266 +                               /* Disable the NP Tx FIFO Empty
38267 +                                * Interrrupt */
38268 +                               if (core_if->en_multiple_tx_fifo == 0) {
38269 +                                       intr_mask.b.nptxfempty = 1;
38270 +                                       dwc_modify_reg32(&core_if->
38271 +                                                        core_global_regs->
38272 +                                                        gintmsk, intr_mask.d32,
38273 +                                                        0);
38274 +                               } else {
38275 +                                       /* Disable the Tx FIFO Empty Interrupt for this EP */
38276 +                                       uint32_t fifoemptymsk =
38277 +                                           0x1 << dwc_ep->num;
38278 +                                       dwc_modify_reg32(&core_if->dev_if->
38279 +                                                        dev_global_regs->
38280 +                                                        dtknqr4_fifoemptymsk,
38281 +                                                        fifoemptymsk, 0);
38282 +                               }
38283 +                               /* Clear the bit in DIEPINTn for this interrupt */
38284 +                               CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
38285 +
38286 +                               /* Complete the transfer */
38287 +                               if (epnum == 0) {
38288 +                                       handle_ep0(pcd);
38289 +                               }
38290 +#ifdef DWC_EN_ISOC
38291 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
38292 +                                       if (!ep->stopped)
38293 +                                               complete_iso_ep(pcd, ep);
38294 +                               }
38295 +#endif                         /* DWC_EN_ISOC */
38296 +                               else {
38297 +
38298 +                                       complete_ep(ep);
38299 +                               }
38300 +                       }
38301 +                       /* Endpoint disable      */
38302 +                       if (diepint.b.epdisabled) {
38303 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
38304 +                                           epnum);
38305 +                               handle_in_ep_disable_intr(pcd, epnum);
38306 +
38307 +                               /* Clear the bit in DIEPINTn for this interrupt */
38308 +                               CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
38309 +                       }
38310 +                       /* AHB Error */
38311 +                       if (diepint.b.ahberr) {
38312 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN AHB Error\n",
38313 +                                           epnum);
38314 +                               /* Clear the bit in DIEPINTn for this interrupt */
38315 +                               CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
38316 +                       }
38317 +                       /* TimeOUT Handshake (non-ISOC IN EPs) */
38318 +                       if (diepint.b.timeout) {
38319 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN Time-out\n",
38320 +                                           epnum);
38321 +                               handle_in_ep_timeout_intr(pcd, epnum);
38322 +
38323 +                               CLEAR_IN_EP_INTR(core_if, epnum, timeout);
38324 +                       }
38325 +                       /** IN Token received with TxF Empty */
38326 +                       if (diepint.b.intktxfemp) {
38327 +                               DWC_DEBUGPL(DBG_ANY,
38328 +                                           "EP%d IN TKN TxFifo Empty\n",
38329 +                                           epnum);
38330 +                               if (!ep->stopped && epnum != 0) {
38331 +
38332 +                                       diepmsk_data_t diepmsk = {.d32 = 0 };
38333 +                                       diepmsk.b.intktxfemp = 1;
38334 +
38335 +                                       if (core_if->multiproc_int_enable) {
38336 +                                               dwc_modify_reg32(&dev_if->
38337 +                                                                dev_global_regs->
38338 +                                                                diepeachintmsk
38339 +                                                                [epnum],
38340 +                                                                diepmsk.d32,
38341 +                                                                0);
38342 +                                       } else {
38343 +                                               dwc_modify_reg32(&dev_if->
38344 +                                                                dev_global_regs->
38345 +                                                                diepmsk,
38346 +                                                                diepmsk.d32,
38347 +                                                                0);
38348 +                                       }
38349 +                               } else if (core_if->dma_desc_enable
38350 +                                          && epnum == 0
38351 +                                          && pcd->ep0state ==
38352 +                                          EP0_OUT_STATUS_PHASE) {
38353 +                                       // EP0 IN set STALL
38354 +                                       depctl.d32 =
38355 +                                           dwc_read_reg32(&dev_if->
38356 +                                                          in_ep_regs[epnum]->
38357 +                                                          diepctl);
38358 +
38359 +                                       /* set the disable and stall bits */
38360 +                                       if (depctl.b.epena) {
38361 +                                               depctl.b.epdis = 1;
38362 +                                       }
38363 +                                       depctl.b.stall = 1;
38364 +                                       dwc_write_reg32(&dev_if->
38365 +                                                       in_ep_regs[epnum]->
38366 +                                                       diepctl, depctl.d32);
38367 +                               }
38368 +                               CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
38369 +                       }
38370 +                       /** IN Token Received with EP mismatch */
38371 +                       if (diepint.b.intknepmis) {
38372 +                               DWC_DEBUGPL(DBG_ANY,
38373 +                                           "EP%d IN TKN EP Mismatch\n", epnum);
38374 +                               CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);
38375 +                       }
38376 +                       /** IN Endpoint NAK Effective */
38377 +                       if (diepint.b.inepnakeff) {
38378 +                               DWC_DEBUGPL(DBG_ANY,
38379 +                                           "EP%d IN EP NAK Effective\n",
38380 +                                           epnum);
38381 +                               /* Periodic EP */
38382 +                               if (ep->disabling) {
38383 +                                       depctl.d32 = 0;
38384 +                                       depctl.b.snak = 1;
38385 +                                       depctl.b.epdis = 1;
38386 +                                       dwc_modify_reg32(&dev_if->
38387 +                                                        in_ep_regs[epnum]->
38388 +                                                        diepctl, depctl.d32,
38389 +                                                        depctl.d32);
38390 +                               }
38391 +                               CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
38392 +
38393 +                       }
38394 +
38395 +                       /** IN EP Tx FIFO Empty Intr */
38396 +                       if (diepint.b.emptyintr) {
38397 +                               DWC_DEBUGPL(DBG_ANY,
38398 +                                           "EP%d Tx FIFO Empty Intr \n",
38399 +                                           epnum);
38400 +                               write_empty_tx_fifo(pcd, epnum);
38401 +
38402 +                               CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
38403 +
38404 +                       }
38405 +
38406 +                       /** IN EP BNA Intr */
38407 +                       if (diepint.b.bna) {
38408 +                               CLEAR_IN_EP_INTR(core_if, epnum, bna);
38409 +                               if (core_if->dma_desc_enable) {
38410 +#ifdef DWC_EN_ISOC
38411 +                                       if (dwc_ep->type ==
38412 +                                           DWC_OTG_EP_TYPE_ISOC) {
38413 +                                               /*
38414 +                                                * This checking is performed to prevent first "false" BNA 
38415 +                                                * handling occuring right after reconnect 
38416 +                                                */
38417 +                                               if (dwc_ep->next_frame !=
38418 +                                                   0xffffffff)
38419 +                                                       dwc_otg_pcd_handle_iso_bna
38420 +                                                           (ep);
38421 +                                       } else
38422 +#endif                         /* DWC_EN_ISOC */
38423 +                                       {
38424 +                                               dctl.d32 =
38425 +                                                   dwc_read_reg32(&dev_if->
38426 +                                                                  dev_global_regs->
38427 +                                                                  dctl);
38428 +
38429 +                                               /* If Global Continue on BNA is disabled - disable EP */
38430 +                                               if (!dctl.b.gcontbna) {
38431 +                                                       depctl.d32 = 0;
38432 +                                                       depctl.b.snak = 1;
38433 +                                                       depctl.b.epdis = 1;
38434 +                                                       dwc_modify_reg32
38435 +                                                           (&dev_if->
38436 +                                                            in_ep_regs[epnum]->
38437 +                                                            diepctl,
38438 +                                                            depctl.d32,
38439 +                                                            depctl.d32);
38440 +                                               } else {
38441 +                                                       start_next_request(ep);
38442 +                                               }
38443 +                                       }
38444 +                               }
38445 +                       }
38446 +                       /* NAK Interrutp */
38447 +                       if (diepint.b.nak) {
38448 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
38449 +                                           epnum);
38450 +                               handle_in_ep_nak_intr(pcd, epnum);
38451 +
38452 +                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
38453 +                       }
38454 +               }
38455 +               epnum++;
38456 +               ep_intr >>= 1;
38457 +       }
38458 +
38459 +       return 1;
38460 +#undef CLEAR_IN_EP_INTR
38461 +}
38462 +
38463 +/**
38464 + * This interrupt indicates that an OUT EP has a pending Interrupt.
38465 + * The sequence for handling the OUT EP interrupt is shown below:
38466 + * -#  Read the Device All Endpoint Interrupt register
38467 + * -#  Repeat the following for each OUT EP interrupt bit set (from
38468 + *             LSB to MSB).
38469 + * -#  Read the Device Endpoint Interrupt (DOEPINTn) register
38470 + * -#  If "Transfer Complete" call the request complete function
38471 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
38472 + * -#  If "AHB Error Interrupt" log error
38473 + * -#  If "Setup Phase Done" process Setup Packet (See Standard USB
38474 + *             Command Processing)
38475 + */
38476 +static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
38477 +{
38478 +#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
38479 +do { \
38480 +               doepint_data_t doepint = {.d32=0}; \
38481 +               doepint.b.__intr = 1; \
38482 +               dwc_write_reg32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
38483 +               doepint.d32); \
38484 +} while (0)
38485 +
38486 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
38487 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
38488 +       uint32_t ep_intr;
38489 +       doepint_data_t doepint = {.d32 = 0 };
38490 +       dctl_data_t dctl = {.d32 = 0 };
38491 +       depctl_data_t doepctl = {.d32 = 0 };
38492 +       uint32_t epnum = 0;
38493 +       dwc_otg_pcd_ep_t *ep;
38494 +       dwc_ep_t *dwc_ep;
38495 +
38496 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
38497 +
38498 +       /* Read in the device interrupt bits */
38499 +       ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
38500 +
38501 +       while (ep_intr) {
38502 +               if (ep_intr & 0x1) {
38503 +                       /* Get EP pointer */
38504 +                       ep = get_out_ep(pcd, epnum);
38505 +                       dwc_ep = &ep->dwc_ep;
38506 +
38507 +#ifdef VERBOSE
38508 +                       DWC_DEBUGPL(DBG_PCDV,
38509 +                                   "EP%d-%s: type=%d, mps=%d\n",
38510 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
38511 +                                   dwc_ep->type, dwc_ep->maxpacket);
38512 +#endif
38513 +                       doepint.d32 =
38514 +                           dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
38515 +
38516 +                       /* Transfer complete */
38517 +                       if (doepint.b.xfercompl) {
38518 +
38519 +                               if (epnum == 0) {
38520 +                                       /* Clear the bit in DOEPINTn for this interrupt */
38521 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
38522 +                                                         xfercompl);
38523 +                                       if (core_if->dma_desc_enable == 0
38524 +                                           || pcd->ep0state != EP0_IDLE)
38525 +                                               handle_ep0(pcd);
38526 +#ifdef DWC_EN_ISOC
38527 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
38528 +                                       if (doepint.b.pktdrpsts == 0) {
38529 +                                               /* Clear the bit in DOEPINTn for this interrupt */
38530 +                                               CLEAR_OUT_EP_INTR(core_if,
38531 +                                                                 epnum,
38532 +                                                                 xfercompl);
38533 +                                               complete_iso_ep(pcd, ep);
38534 +                                       } else {
38535 +
38536 +                                               doepint_data_t doepint = {.d32 =
38537 +                                                           0 };
38538 +                                               doepint.b.xfercompl = 1;
38539 +                                               doepint.b.pktdrpsts = 1;
38540 +                                               dwc_write_reg32(&core_if->
38541 +                                                               dev_if->
38542 +                                                               out_ep_regs
38543 +                                                               [epnum]->
38544 +                                                               doepint,
38545 +                                                               doepint.d32);
38546 +                                               if (handle_iso_out_pkt_dropped
38547 +                                                   (core_if, dwc_ep)) {
38548 +                                                       complete_iso_ep(pcd,
38549 +                                                                       ep);
38550 +                                               }
38551 +                                       }
38552 +#endif                         /* DWC_EN_ISOC */
38553 +                               } else {
38554 +                                       /* Clear the bit in DOEPINTn for this interrupt */
38555 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
38556 +                                                         xfercompl);
38557 +                                       complete_ep(ep);
38558 +                               }
38559 +
38560 +                       }
38561 +
38562 +                       /* Endpoint disable      */
38563 +                       if (doepint.b.epdisabled) {
38564 +
38565 +                               /* Clear the bit in DOEPINTn for this interrupt */
38566 +                               CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
38567 +                       }
38568 +                       /* AHB Error */
38569 +                       if (doepint.b.ahberr) {
38570 +                               DWC_DEBUGPL(DBG_PCD, "EP%d OUT AHB Error\n",
38571 +                                           epnum);
38572 +                               DWC_DEBUGPL(DBG_PCD, "EP DMA REG         %d \n",
38573 +                                           core_if->dev_if->
38574 +                                           out_ep_regs[epnum]->doepdma);
38575 +                               CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
38576 +                       }
38577 +                       /* Setup Phase Done (contorl EPs) */
38578 +                       if (doepint.b.setup) {
38579 +#ifdef DEBUG_EP0
38580 +                               DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n",
38581 +                                           epnum);
38582 +#endif
38583 +                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
38584 +
38585 +                               handle_ep0(pcd);
38586 +                       }
38587 +
38588 +                       /** OUT EP BNA Intr */
38589 +                       if (doepint.b.bna) {
38590 +                               CLEAR_OUT_EP_INTR(core_if, epnum, bna);
38591 +                               if (core_if->dma_desc_enable) {
38592 +#ifdef DWC_EN_ISOC
38593 +                                       if (dwc_ep->type ==
38594 +                                           DWC_OTG_EP_TYPE_ISOC) {
38595 +                                               /*
38596 +                                                * This checking is performed to prevent first "false" BNA 
38597 +                                                * handling occuring right after reconnect 
38598 +                                                */
38599 +                                               if (dwc_ep->next_frame !=
38600 +                                                   0xffffffff)
38601 +                                                       dwc_otg_pcd_handle_iso_bna
38602 +                                                           (ep);
38603 +                                       } else
38604 +#endif                         /* DWC_EN_ISOC */
38605 +                                       {
38606 +                                               dctl.d32 =
38607 +                                                   dwc_read_reg32(&dev_if->
38608 +                                                                  dev_global_regs->
38609 +                                                                  dctl);
38610 +
38611 +                                               /* If Global Continue on BNA is disabled - disable EP */
38612 +                                               if (!dctl.b.gcontbna) {
38613 +                                                       doepctl.d32 = 0;
38614 +                                                       doepctl.b.snak = 1;
38615 +                                                       doepctl.b.epdis = 1;
38616 +                                                       dwc_modify_reg32
38617 +                                                           (&dev_if->
38618 +                                                            out_ep_regs
38619 +                                                            [epnum]->doepctl,
38620 +                                                            doepctl.d32,
38621 +                                                            doepctl.d32);
38622 +                                               } else {
38623 +                                                       start_next_request(ep);
38624 +                                               }
38625 +                                       }
38626 +                               }
38627 +                       }
38628 +                       if (doepint.b.stsphsercvd) {
38629 +                               CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
38630 +                               if (core_if->dma_desc_enable) {
38631 +                                       do_setup_in_status_phase(pcd);
38632 +                               }
38633 +                       }
38634 +                       /* Babble Interrutp */
38635 +                       if (doepint.b.babble) {
38636 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
38637 +                                           epnum);
38638 +                               handle_out_ep_babble_intr(pcd, epnum);
38639 +
38640 +                               CLEAR_OUT_EP_INTR(core_if, epnum, babble);
38641 +                       }
38642 +                       /* NAK Interrutp */
38643 +                       if (doepint.b.nak) {
38644 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
38645 +                               handle_out_ep_nak_intr(pcd, epnum);
38646 +
38647 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nak);
38648 +                       }
38649 +                       /* NYET Interrutp */
38650 +                       if (doepint.b.nyet) {
38651 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
38652 +                               handle_out_ep_nyet_intr(pcd, epnum);
38653 +
38654 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
38655 +                       }
38656 +               }
38657 +
38658 +               epnum++;
38659 +               ep_intr >>= 1;
38660 +       }
38661 +
38662 +       return 1;
38663 +
38664 +#undef CLEAR_OUT_EP_INTR
38665 +}
38666 +
38667 +/**
38668 + * Incomplete ISO IN Transfer Interrupt.
38669 + * This interrupt indicates one of the following conditions occurred
38670 + * while transmitting an ISOC transaction.
38671 + * - Corrupted IN Token for ISOC EP.
38672 + * - Packet not complete in FIFO.
38673 + * The follow actions will be taken:
38674 + *     -#      Determine the EP
38675 + *     -#      Set incomplete flag in dwc_ep structure
38676 + *     -#      Disable EP; when "Endpoint Disabled" interrupt is received
38677 + *             Flush FIFO
38678 + */
38679 +int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
38680 +{
38681 +       gintsts_data_t gintsts;
38682 +
38683 +#ifdef DWC_EN_ISOC
38684 +       dwc_otg_dev_if_t *dev_if;
38685 +       deptsiz_data_t deptsiz = {.d32 = 0 };
38686 +       depctl_data_t depctl = {.d32 = 0 };
38687 +       dsts_data_t dsts = {.d32 = 0 };
38688 +       dwc_ep_t *dwc_ep;
38689 +       int i;
38690 +
38691 +       dev_if = GET_CORE_IF(pcd)->dev_if;
38692 +
38693 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
38694 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
38695 +               if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
38696 +                       deptsiz.d32 =
38697 +                           dwc_read_reg32(&dev_if->in_ep_regs[i]->dieptsiz);
38698 +                       depctl.d32 =
38699 +                           dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl);
38700 +
38701 +                       if (depctl.b.epdis && deptsiz.d32) {
38702 +                               set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
38703 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
38704 +                                       dwc_ep->cur_pkt = 0;
38705 +                                       dwc_ep->proc_buf_num =
38706 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
38707 +
38708 +                                       if (dwc_ep->proc_buf_num) {
38709 +                                               dwc_ep->cur_pkt_addr =
38710 +                                                   dwc_ep->xfer_buff1;
38711 +                                               dwc_ep->cur_pkt_dma_addr =
38712 +                                                   dwc_ep->dma_addr1;
38713 +                                       } else {
38714 +                                               dwc_ep->cur_pkt_addr =
38715 +                                                   dwc_ep->xfer_buff0;
38716 +                                               dwc_ep->cur_pkt_dma_addr =
38717 +                                                   dwc_ep->dma_addr0;
38718 +                                       }
38719 +
38720 +                               }
38721 +
38722 +                               dsts.d32 =
38723 +                                   dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->
38724 +                                                  dev_global_regs->dsts);
38725 +                               dwc_ep->next_frame = dsts.b.soffn;
38726 +
38727 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
38728 +                                                                 (pcd),
38729 +                                                                 dwc_ep);
38730 +                       }
38731 +               }
38732 +       }
38733 +
38734 +#else
38735 +       gintmsk_data_t intr_mask = {.d32 = 0 };
38736 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
38737 +                  "IN ISOC Incomplete");
38738 +
38739 +       intr_mask.b.incomplisoin = 1;
38740 +       dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
38741 +                        intr_mask.d32, 0);
38742 +#endif                         //DWC_EN_ISOC
38743 +
38744 +       /* Clear interrupt */
38745 +       gintsts.d32 = 0;
38746 +       gintsts.b.incomplisoin = 1;
38747 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
38748 +                       gintsts.d32);
38749 +
38750 +       return 1;
38751 +}
38752 +
38753 +/**
38754 + * Incomplete ISO OUT Transfer Interrupt.
38755 + *
38756 + * This interrupt indicates that the core has dropped an ISO OUT
38757 + * packet.     The following conditions can be the cause:
38758 + * - FIFO Full, the entire packet would not fit in the FIFO.
38759 + * - CRC Error
38760 + * - Corrupted Token
38761 + * The follow actions will be taken:
38762 + *     -#      Determine the EP
38763 + *     -#      Set incomplete flag in dwc_ep structure
38764 + *     -#      Read any data from the FIFO
38765 + *     -#      Disable EP.      when "Endpoint Disabled" interrupt is received
38766 + *             re-enable EP.
38767 + */
38768 +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
38769 +{
38770 +
38771 +       gintsts_data_t gintsts;
38772 +
38773 +#ifdef DWC_EN_ISOC
38774 +       dwc_otg_dev_if_t *dev_if;
38775 +       deptsiz_data_t deptsiz = {.d32 = 0 };
38776 +       depctl_data_t depctl = {.d32 = 0 };
38777 +       dsts_data_t dsts = {.d32 = 0 };
38778 +       dwc_ep_t *dwc_ep;
38779 +       int i;
38780 +
38781 +       dev_if = GET_CORE_IF(pcd)->dev_if;
38782 +
38783 +       for (i = 1; i <= dev_if->num_out_eps; ++i) {
38784 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
38785 +               if (pcd->out_ep[i].dwc_ep.active &&
38786 +                   pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
38787 +                       deptsiz.d32 =
38788 +                           dwc_read_reg32(&dev_if->out_ep_regs[i]->doeptsiz);
38789 +                       depctl.d32 =
38790 +                           dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl);
38791 +
38792 +                       if (depctl.b.epdis && deptsiz.d32) {
38793 +                               set_current_pkt_info(GET_CORE_IF(pcd),
38794 +                                                    &pcd->out_ep[i].dwc_ep);
38795 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
38796 +                                       dwc_ep->cur_pkt = 0;
38797 +                                       dwc_ep->proc_buf_num =
38798 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
38799 +
38800 +                                       if (dwc_ep->proc_buf_num) {
38801 +                                               dwc_ep->cur_pkt_addr =
38802 +                                                   dwc_ep->xfer_buff1;
38803 +                                               dwc_ep->cur_pkt_dma_addr =
38804 +                                                   dwc_ep->dma_addr1;
38805 +                                       } else {
38806 +                                               dwc_ep->cur_pkt_addr =
38807 +                                                   dwc_ep->xfer_buff0;
38808 +                                               dwc_ep->cur_pkt_dma_addr =
38809 +                                                   dwc_ep->dma_addr0;
38810 +                                       }
38811 +
38812 +                               }
38813 +
38814 +                               dsts.d32 =
38815 +                                   dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if->
38816 +                                                  dev_global_regs->dsts);
38817 +                               dwc_ep->next_frame = dsts.b.soffn;
38818 +
38819 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
38820 +                                                                 (pcd),
38821 +                                                                 dwc_ep);
38822 +                       }
38823 +               }
38824 +       }
38825 +#else
38826 +       /** @todo implement ISR */
38827 +       gintmsk_data_t intr_mask = {.d32 = 0 };
38828 +
38829 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
38830 +                  "OUT ISOC Incomplete");
38831 +
38832 +       intr_mask.b.incomplisoout = 1;
38833 +       dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
38834 +                        intr_mask.d32, 0);
38835 +
38836 +#endif                         /* DWC_EN_ISOC */
38837 +
38838 +       /* Clear interrupt */
38839 +       gintsts.d32 = 0;
38840 +       gintsts.b.incomplisoout = 1;
38841 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
38842 +                       gintsts.d32);
38843 +
38844 +       return 1;
38845 +}
38846 +
38847 +/**
38848 + * This function handles the Global IN NAK Effective interrupt.
38849 + *
38850 + */
38851 +int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
38852 +{
38853 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
38854 +       depctl_data_t diepctl = {.d32 = 0 };
38855 +       depctl_data_t diepctl_rd = {.d32 = 0 };
38856 +       gintmsk_data_t intr_mask = {.d32 = 0 };
38857 +       gintsts_data_t gintsts;
38858 +       int i;
38859 +
38860 +       DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
38861 +
38862 +       /* Disable all active IN EPs */
38863 +       diepctl.b.epdis = 1;
38864 +       diepctl.b.snak = 1;
38865 +
38866 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
38867 +               diepctl_rd.d32 =
38868 +                   dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl);
38869 +               if (diepctl_rd.b.epena) {
38870 +                       dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl,
38871 +                                       diepctl.d32);
38872 +               }
38873 +       }
38874 +       /* Disable the Global IN NAK Effective Interrupt */
38875 +       intr_mask.b.ginnakeff = 1;
38876 +       dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
38877 +                        intr_mask.d32, 0);
38878 +
38879 +       /* Clear interrupt */
38880 +       gintsts.d32 = 0;
38881 +       gintsts.b.ginnakeff = 1;
38882 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
38883 +                       gintsts.d32);
38884 +
38885 +       return 1;
38886 +}
38887 +
38888 +/**
38889 + * OUT NAK Effective.
38890 + *
38891 + */
38892 +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
38893 +{
38894 +       gintmsk_data_t intr_mask = {.d32 = 0 };
38895 +       gintsts_data_t gintsts;
38896 +
38897 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
38898 +                  "Global IN NAK Effective\n");
38899 +       /* Disable the Global IN NAK Effective Interrupt */
38900 +       intr_mask.b.goutnakeff = 1;
38901 +       dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
38902 +                        intr_mask.d32, 0);
38903 +
38904 +       /* Clear interrupt */
38905 +       gintsts.d32 = 0;
38906 +       gintsts.b.goutnakeff = 1;
38907 +       dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
38908 +                       gintsts.d32);
38909 +
38910 +       return 1;
38911 +}
38912 +
38913 +/**
38914 + * PCD interrupt handler.
38915 + *
38916 + * The PCD handles the device interrupts.  Many conditions can cause a
38917 + * device interrupt. When an interrupt occurs, the device interrupt
38918 + * service routine determines the cause of the interrupt and
38919 + * dispatches handling to the appropriate function. These interrupt
38920 + * handling functions are described below.
38921 + *
38922 + * All interrupt registers are processed from LSB to MSB.
38923 + *
38924 + */
38925 +int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
38926 +{
38927 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
38928 +#ifdef VERBOSE
38929 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
38930 +#endif
38931 +       gintsts_data_t gintr_status;
38932 +       int32_t retval = 0;
38933 +
38934 +#ifdef VERBOSE
38935 +       DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x  gintmsk=%08x\n",
38936 +                   __func__,
38937 +                   dwc_read_reg32(&global_regs->gintsts),
38938 +                   dwc_read_reg32(&global_regs->gintmsk));
38939 +#endif
38940 +
38941 +       if (dwc_otg_is_device_mode(core_if)) {
38942 +               DWC_SPINLOCK(pcd->lock);
38943 +#ifdef VERBOSE
38944 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x  gintmsk=%08x\n",
38945 +                           __func__,
38946 +                           dwc_read_reg32(&global_regs->gintsts),
38947 +                           dwc_read_reg32(&global_regs->gintmsk));
38948 +#endif
38949 +
38950 +               gintr_status.d32 = dwc_otg_read_core_intr(core_if);
38951 +
38952 +               DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
38953 +                           __func__, gintr_status.d32);
38954 +
38955 +               if (gintr_status.b.sofintr) {
38956 +                       retval |= dwc_otg_pcd_handle_sof_intr(pcd);
38957 +               }
38958 +               if (gintr_status.b.rxstsqlvl) {
38959 +                       retval |=
38960 +                           dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
38961 +               }
38962 +               if (gintr_status.b.nptxfempty) {
38963 +                       retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
38964 +               }
38965 +               if (gintr_status.b.ginnakeff) {
38966 +                       retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
38967 +               }
38968 +               if (gintr_status.b.goutnakeff) {
38969 +                       retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
38970 +               }
38971 +               if (gintr_status.b.i2cintr) {
38972 +                       retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
38973 +               }
38974 +               if (gintr_status.b.erlysuspend) {
38975 +                       retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
38976 +               }
38977 +               if (gintr_status.b.usbreset) {
38978 +                       retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
38979 +               }
38980 +               if (gintr_status.b.enumdone) {
38981 +                       retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
38982 +               }
38983 +               if (gintr_status.b.isooutdrop) {
38984 +                       retval |=
38985 +                           dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
38986 +                           (pcd);
38987 +               }
38988 +               if (gintr_status.b.eopframe) {
38989 +                       retval |=
38990 +                           dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
38991 +               }
38992 +               if (gintr_status.b.epmismatch) {
38993 +                       retval |= dwc_otg_pcd_handle_ep_mismatch_intr(core_if);
38994 +               }
38995 +               if (gintr_status.b.inepint) {
38996 +                       if (!core_if->multiproc_int_enable) {
38997 +                               retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
38998 +                       }
38999 +               }
39000 +               if (gintr_status.b.outepintr) {
39001 +                       if (!core_if->multiproc_int_enable) {
39002 +                               retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
39003 +                       }
39004 +               }
39005 +               if (gintr_status.b.incomplisoin) {
39006 +                       retval |=
39007 +                           dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
39008 +               }
39009 +               if (gintr_status.b.incomplisoout) {
39010 +                       retval |=
39011 +                           dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
39012 +               }
39013 +
39014 +               /* In MPI mode De vice Endpoints intterrupts are asserted 
39015 +                * without setting outepintr and inepint bits set, so these
39016 +                * Interrupt handlers are called without checking these bit-fields
39017 +                */
39018 +               if (core_if->multiproc_int_enable) {
39019 +                       retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
39020 +                       retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
39021 +               }
39022 +#ifdef VERBOSE
39023 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
39024 +                           dwc_read_reg32(&global_regs->gintsts));
39025 +#endif
39026 +               DWC_SPINUNLOCK(pcd->lock);
39027 +       }
39028 +       return retval;
39029 +}
39030 +
39031 +#endif                         /* DWC_HOST_ONLY */
39032 --- /dev/null
39033 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
39034 @@ -0,0 +1,1288 @@
39035 + /* ==========================================================================
39036 +  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
39037 +  * $Revision: #7 $
39038 +  * $Date: 2009/04/03 $
39039 +  * $Change: 1225160 $
39040 +  *
39041 +  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39042 +  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39043 +  * otherwise expressly agreed to in writing between Synopsys and you.
39044 +  *
39045 +  * The Software IS NOT an item of Licensed Software or Licensed Product under
39046 +  * any End User Software License Agreement or Agreement for Licensed Product
39047 +  * with Synopsys or any supplement thereto. You are permitted to use and
39048 +  * redistribute this Software in source and binary forms, with or without
39049 +  * modification, provided that redistributions of source code must retain this
39050 +  * notice. You may not view, use, disclose, copy or distribute this file or
39051 +  * any information contained herein except pursuant to this license grant from
39052 +  * Synopsys. If you do not agree with this notice, including the disclaimer
39053 +  * below, then you are not authorized to use the Software.
39054 +  *
39055 +  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39056 +  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39057 +  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39058 +  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39059 +  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39060 +  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39061 +  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39062 +  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39063 +  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39064 +  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39065 +  * DAMAGE.
39066 +  * ========================================================================== */
39067 +#ifndef DWC_HOST_ONLY
39068 +
39069 +/** @file
39070 + * This file implements the Peripheral Controller Driver.
39071 + *
39072 + * The Peripheral Controller Driver (PCD) is responsible for
39073 + * translating requests from the Function Driver into the appropriate
39074 + * actions on the DWC_otg controller. It isolates the Function Driver
39075 + * from the specifics of the controller by providing an API to the
39076 + * Function Driver.
39077 + *
39078 + * The Peripheral Controller Driver for Linux will implement the
39079 + * Gadget API, so that the existing Gadget drivers can be used.
39080 + * (Gadget Driver is the Linux terminology for a Function Driver.)
39081 + *
39082 + * The Linux Gadget API is defined in the header file
39083 + * <code><linux/usb_gadget.h></code>.  The USB EP operations API is
39084 + * defined in the structure <code>usb_ep_ops</code> and the USB
39085 + * Controller API is defined in the structure
39086 + * <code>usb_gadget_ops</code>.
39087 + *
39088 + */
39089 +
39090 +#include <linux/kernel.h>
39091 +#include <linux/module.h>
39092 +#include <linux/moduleparam.h>
39093 +#include <linux/init.h>
39094 +#include <linux/device.h>
39095 +#include <linux/errno.h>
39096 +#include <linux/list.h>
39097 +#include <linux/interrupt.h>
39098 +#include <linux/string.h>
39099 +#include <linux/dma-mapping.h>
39100 +#include <linux/version.h>
39101 +
39102 +#if defined(LM_INTERFACE)
39103 +//# include <asm/arch/regs-irq.h>
39104 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
39105 +#include <asm/arch/lm.h>
39106 +#else
39107 +/* by 2.6.31, at least, the location of some headers has changed
39108 +*/
39109 +#include <mach/lm.h>
39110 +#endif
39111 +
39112 +#elif defined(PLATFORM_INTERFACE)
39113 +#include <linux/platform_device.h>
39114 +#endif
39115 +
39116 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
39117 +#include <asm/arch/irqs.h>
39118 +#include <linux/usb_ch9.h>
39119 +#include <linux/usb_gadget.h>
39120 +#else
39121 +/* by 2.6.31, at least, the location of some headers has changed
39122 +*/
39123 +#include <mach/irqs.h>
39124 +#include <linux/usb/ch9.h>
39125 +#include <linux/usb/gadget.h>
39126 +#endif
39127 +
39128 +#include <asm/io.h>
39129 +
39130 +#include "dwc_otg_pcd_if.h"
39131 +#include "dwc_otg_driver.h"
39132 +#include "dwc_otg_dbg.h"
39133 +
39134 +static struct gadget_wrapper {
39135 +       dwc_otg_pcd_t *pcd;
39136 +
39137 +       struct usb_gadget gadget;
39138 +       struct usb_gadget_driver *driver;
39139 +
39140 +       struct usb_ep ep0;
39141 +       struct usb_ep in_ep[16];
39142 +       struct usb_ep out_ep[16];
39143 +
39144 +} *gadget_wrapper;
39145 +
39146 +/* Display the contents of the buffer */
39147 +extern void dump_msg(const u8 * buf, unsigned int length);
39148 +
39149 +/* USB Endpoint Operations */
39150 +/*
39151 + * The following sections briefly describe the behavior of the Gadget
39152 + * API endpoint operations implemented in the DWC_otg driver
39153 + * software. Detailed descriptions of the generic behavior of each of
39154 + * these functions can be found in the Linux header file
39155 + * include/linux/usb_gadget.h.
39156 + *
39157 + * The Gadget API provides wrapper functions for each of the function
39158 + * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
39159 + * function, which then calls the underlying PCD function. The
39160 + * following sections are named according to the wrapper
39161 + * functions. Within each section, the corresponding DWC_otg PCD
39162 + * function name is specified.
39163 + *
39164 + */
39165 +
39166 +/**
39167 + * This function is called by the Gadget Driver for each EP to be
39168 + * configured for the current configuration (SET_CONFIGURATION).
39169 + *
39170 + * This function initializes the dwc_otg_ep_t data structure, and then
39171 + * calls dwc_otg_ep_activate.
39172 + */
39173 +static int ep_enable(struct usb_ep *usb_ep,
39174 +                    const struct usb_endpoint_descriptor *ep_desc)
39175 +{
39176 +       int retval;
39177 +
39178 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
39179 +
39180 +       if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
39181 +               DWC_WARN("%s, bad ep or descriptor\n", __func__);
39182 +               return -EINVAL;
39183 +       }
39184 +       if (usb_ep == &gadget_wrapper->ep0) {
39185 +               DWC_WARN("%s, bad ep(0)\n", __func__);
39186 +               return -EINVAL;
39187 +       }
39188 +
39189 +       /* Check FIFO size? */
39190 +       if (!ep_desc->wMaxPacketSize) {
39191 +               DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
39192 +               return -ERANGE;
39193 +       }
39194 +
39195 +       if (!gadget_wrapper->driver ||
39196 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
39197 +               DWC_WARN("%s, bogus device state\n", __func__);
39198 +               return -ESHUTDOWN;
39199 +       }
39200 +
39201 +       retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
39202 +                                      (const uint8_t *)ep_desc,
39203 +                                      (void *)usb_ep);
39204 +       if (retval) {
39205 +               DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
39206 +               return -EINVAL;
39207 +       }
39208 +
39209 +       usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
39210 +
39211 +       return 0;
39212 +}
39213 +
39214 +/**
39215 + * This function is called when an EP is disabled due to disconnect or
39216 + * change in configuration. Any pending requests will terminate with a
39217 + * status of -ESHUTDOWN.
39218 + *
39219 + * This function modifies the dwc_otg_ep_t data structure for this EP,
39220 + * and then calls dwc_otg_ep_deactivate.
39221 + */
39222 +static int ep_disable(struct usb_ep *usb_ep)
39223 +{
39224 +       int retval;
39225 +
39226 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
39227 +       if (!usb_ep) {
39228 +               DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
39229 +                           usb_ep ? usb_ep->name : NULL);
39230 +               return -EINVAL;
39231 +       }
39232 +
39233 +       retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
39234 +       if (retval) {
39235 +               retval = -EINVAL;
39236 +       }
39237 +
39238 +       return retval;
39239 +}
39240 +
39241 +/**
39242 + * This function allocates a request object to use with the specified
39243 + * endpoint.
39244 + *
39245 + * @param ep The endpoint to be used with with the request
39246 + * @param gfp_flags the GFP_* flags to use.
39247 + */
39248 +static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
39249 +                                                    gfp_t gfp_flags)
39250 +{
39251 +       struct usb_request *usb_req;
39252 +
39253 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
39254 +       if (0 == ep) {
39255 +               DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
39256 +               return 0;
39257 +       }
39258 +       usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
39259 +       if (0 == usb_req) {
39260 +               DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
39261 +               return 0;
39262 +       }
39263 +       memset(usb_req, 0, sizeof(*usb_req));
39264 +       usb_req->dma = DWC_INVALID_DMA_ADDR;
39265 +
39266 +       return usb_req;
39267 +}
39268 +
39269 +/**
39270 + * This function frees a request object.
39271 + *
39272 + * @param ep The endpoint associated with the request
39273 + * @param req The request being freed
39274 + */
39275 +static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
39276 +{
39277 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
39278 +
39279 +       if (0 == ep || 0 == req) {
39280 +               DWC_WARN("%s() %s\n", __func__,
39281 +                        "Invalid ep or req argument!\n");
39282 +               return;
39283 +       }
39284 +
39285 +       kfree(req);
39286 +}
39287 +
39288 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
39289 +/**
39290 + * This function allocates an I/O buffer to be used for a transfer
39291 + * to/from the specified endpoint.
39292 + *
39293 + * @param usb_ep The endpoint to be used with with the request
39294 + * @param bytes The desired number of bytes for the buffer
39295 + * @param dma Pointer to the buffer's DMA address; must be valid
39296 + * @param gfp_flags the GFP_* flags to use.
39297 + * @return address of a new buffer or null is buffer could not be allocated.
39298 + */
39299 +static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
39300 +                                     dma_addr_t * dma, gfp_t gfp_flags)
39301 +{
39302 +       void *buf;
39303 +       dwc_otg_pcd_t *pcd = 0;
39304 +
39305 +       pcd = gadget_wrapper->pcd;
39306 +
39307 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
39308 +                   dma, gfp_flags);
39309 +
39310 +       /* Check dword alignment */
39311 +       if ((bytes & 0x3UL) != 0) {
39312 +               DWC_WARN("%s() Buffer size is not a multiple of"
39313 +                        "DWORD size (%d)", __func__, bytes);
39314 +       }
39315 +
39316 +       buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
39317 +
39318 +       /* Check dword alignment */
39319 +       if (((int)buf & 0x3UL) != 0) {
39320 +               DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
39321 +                        __func__, buf);
39322 +       }
39323 +
39324 +       return buf;
39325 +}
39326 +
39327 +/**
39328 + * This function frees an I/O buffer that was allocated by alloc_buffer.
39329 + *
39330 + * @param usb_ep the endpoint associated with the buffer
39331 + * @param buf address of the buffer
39332 + * @param dma The buffer's DMA address
39333 + * @param bytes The number of bytes of the buffer
39334 + */
39335 +static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
39336 +                                   dma_addr_t dma, unsigned bytes)
39337 +{
39338 +       dwc_otg_pcd_t *pcd = 0;
39339 +
39340 +       pcd = gadget_wrapper->pcd;
39341 +
39342 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
39343 +
39344 +       dma_free_coherent(NULL, bytes, buf, dma);
39345 +}
39346 +#endif
39347 +
39348 +/**
39349 + * This function is used to submit an I/O Request to an EP.
39350 + *
39351 + *     - When the request completes the request's completion callback
39352 + *       is called to return the request to the driver.
39353 + *     - An EP, except control EPs, may have multiple requests
39354 + *       pending.
39355 + *     - Once submitted the request cannot be examined or modified.
39356 + *     - Each request is turned into one or more packets.
39357 + *     - A BULK EP can queue any amount of data; the transfer is
39358 + *       packetized.
39359 + *     - Zero length Packets are specified with the request 'zero'
39360 + *       flag.
39361 + */
39362 +static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
39363 +                   gfp_t gfp_flags)
39364 +{
39365 +       dwc_otg_pcd_t *pcd;
39366 +       int retval;
39367 +
39368 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
39369 +                   __func__, usb_ep, usb_req, gfp_flags);
39370 +
39371 +       if (!usb_req || !usb_req->complete || !usb_req->buf) {
39372 +               DWC_WARN("bad params\n");
39373 +               return -EINVAL;
39374 +       }
39375 +
39376 +       if (!usb_ep) {
39377 +               DWC_WARN("bad ep\n");
39378 +               return -EINVAL;
39379 +       }
39380 +
39381 +       pcd = gadget_wrapper->pcd;
39382 +       if (!gadget_wrapper->driver ||
39383 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
39384 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
39385 +                           gadget_wrapper->gadget.speed);
39386 +               DWC_WARN("bogus device state\n");
39387 +               return -ESHUTDOWN;
39388 +       }
39389 +
39390 +       DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
39391 +                   usb_ep->name, usb_req, usb_req->length, usb_req->buf);
39392 +
39393 +       usb_req->status = -EINPROGRESS;
39394 +       usb_req->actual = 0;
39395 +
39396 +       retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, usb_req->dma,
39397 +                                     usb_req->length, usb_req->zero, usb_req,
39398 +                                     gfp_flags == GFP_ATOMIC ? 1 : 0);
39399 +       if (retval) {
39400 +               return -EINVAL;
39401 +       }
39402 +
39403 +       return 0;
39404 +}
39405 +
39406 +/**
39407 + * This function cancels an I/O request from an EP.
39408 + */
39409 +static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
39410 +{
39411 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
39412 +
39413 +       if (!usb_ep || !usb_req) {
39414 +               DWC_WARN("bad argument\n");
39415 +               return -EINVAL;
39416 +       }
39417 +       if (!gadget_wrapper->driver ||
39418 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
39419 +               DWC_WARN("bogus device state\n");
39420 +               return -ESHUTDOWN;
39421 +       }
39422 +       if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
39423 +               return -EINVAL;
39424 +       }
39425 +
39426 +       return 0;
39427 +}
39428 +
39429 +/**
39430 + * usb_ep_set_halt stalls an endpoint.
39431 + *
39432 + * usb_ep_clear_halt clears an endpoint halt and resets its data
39433 + * toggle.
39434 + *
39435 + * Both of these functions are implemented with the same underlying
39436 + * function. The behavior depends on the value argument.
39437 + *
39438 + * @param[in] usb_ep the Endpoint to halt or clear halt.
39439 + * @param[in] value
39440 + *     - 0 means clear_halt.
39441 + *     - 1 means set_halt,
39442 + *     - 2 means clear stall lock flag.
39443 + *     - 3 means set  stall lock flag.
39444 + */
39445 +static int ep_halt(struct usb_ep *usb_ep, int value)
39446 +{
39447 +       int retval = 0;
39448 +
39449 +       DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
39450 +
39451 +       if (!usb_ep) {
39452 +               DWC_WARN("bad ep\n");
39453 +               return -EINVAL;
39454 +       }
39455 +
39456 +       retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
39457 +       if (retval == -DWC_E_AGAIN) {
39458 +               return -EAGAIN;
39459 +       } else if (retval) {
39460 +               retval = -EINVAL;
39461 +       }
39462 +
39463 +       return retval;
39464 +}
39465 +
39466 +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
39467 +#if 0
39468 +/**
39469 + * ep_wedge: sets the halt feature and ignores clear requests
39470 + *
39471 + * @usb_ep: the endpoint being wedged
39472 + *
39473 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
39474 + * requests. If the gadget driver clears the halt status, it will
39475 + * automatically unwedge the endpoint.
39476 + *
39477 + * Returns zero on success, else negative errno. *
39478 + * Check usb_ep_set_wedge() at "usb_gadget.h" for details
39479 + */
39480 +static int ep_wedge(struct usb_ep *usb_ep)
39481 +{
39482 +       int retval = 0;
39483 +
39484 +       DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
39485 +
39486 +       if (!usb_ep) {
39487 +               DWC_WARN("bad ep\n");
39488 +               return -EINVAL;
39489 +       }
39490 +
39491 +       retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep);
39492 +       if (retval == -DWC_E_AGAIN) {
39493 +               retval = -EAGAIN;
39494 +       } else if (retval) {
39495 +               retval = -EINVAL;
39496 +       }
39497 +
39498 +       return retval;
39499 +}
39500 +#endif
39501 +
39502 +#ifdef DWC_EN_ISOC
39503 +/**
39504 + * This function is used to submit an ISOC Transfer Request to an EP.
39505 + *
39506 + *     - Every time a sync period completes the request's completion callback
39507 + *       is called to provide data to the gadget driver.
39508 + *     - Once submitted the request cannot be modified.
39509 + *     - Each request is turned into periodic data packets untill ISO
39510 + *       Transfer is stopped..
39511 + */
39512 +static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
39513 +                       gfp_t gfp_flags)
39514 +{
39515 +       int retval = 0;
39516 +
39517 +       if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
39518 +               DWC_WARN("bad params\n");
39519 +               return -EINVAL;
39520 +       }
39521 +
39522 +       if (!usb_ep) {
39523 +               DWC_PRINTF("bad params\n");
39524 +               return -EINVAL;
39525 +       }
39526 +
39527 +       req->status = -EINPROGRESS;
39528 +
39529 +       retval =
39530 +           dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
39531 +                                    req->buf1, req->dma0, req->dma1,
39532 +                                    req->sync_frame, req->data_pattern_frame,
39533 +                                    req->data_per_frame,
39534 +                                    req->flags & USB_REQ_ISO_ASAP ? -1 : req->
39535 +                                    start_frame, req->buf_proc_intrvl, req,
39536 +                                    gfp_flags == GFP_ATOMIC ? 1 : 0);
39537 +
39538 +       if (retval) {
39539 +               return -EINVAL;
39540 +       }
39541 +
39542 +       return retval;
39543 +}
39544 +
39545 +/**
39546 + * This function stops ISO EP Periodic Data Transfer.
39547 + */
39548 +static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
39549 +{
39550 +       int retval = 0;
39551 +       if (!usb_ep) {
39552 +               DWC_WARN("bad ep\n");
39553 +       }
39554 +
39555 +       if (!gadget_wrapper->driver ||
39556 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
39557 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
39558 +                           gadget_wrapper->gadget.speed);
39559 +               DWC_WARN("bogus device state\n");
39560 +       }
39561 +
39562 +       dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
39563 +       if (retval) {
39564 +               retval = -EINVAL;
39565 +       }
39566 +
39567 +       return retval;
39568 +}
39569 +
39570 +static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
39571 +                                                int packets, gfp_t gfp_flags)
39572 +{
39573 +       struct usb_iso_request *pReq = NULL;
39574 +       uint32_t req_size;
39575 +
39576 +       req_size = sizeof(struct usb_iso_request);
39577 +       req_size +=
39578 +           (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
39579 +
39580 +       pReq = kmalloc(req_size, gfp_flags);
39581 +       if (!pReq) {
39582 +               DWC_WARN("Can't allocate Iso Request\n");
39583 +               return 0;
39584 +       }
39585 +       pReq->iso_packet_desc0 = (void *)(pReq + 1);
39586 +
39587 +       pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
39588 +
39589 +       return pReq;
39590 +}
39591 +
39592 +static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
39593 +{
39594 +       kfree(req);
39595 +}
39596 +
39597 +static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
39598 +       .ep_ops = {
39599 +                  .enable = ep_enable,
39600 +                  .disable = ep_disable,
39601 +
39602 +                  .alloc_request = dwc_otg_pcd_alloc_request,
39603 +                  .free_request = dwc_otg_pcd_free_request,
39604 +
39605 +                  .alloc_buffer = dwc_otg_pcd_alloc_buffer,
39606 +                  .free_buffer = dwc_otg_pcd_free_buffer,
39607 +
39608 +                  .queue = ep_queue,
39609 +                  .dequeue = ep_dequeue,
39610 +
39611 +                  .set_halt = ep_halt,
39612 +                  .fifo_status = 0,
39613 +                  .fifo_flush = 0,
39614 +                  },
39615 +       .iso_ep_start = iso_ep_start,
39616 +       .iso_ep_stop = iso_ep_stop,
39617 +       .alloc_iso_request = alloc_iso_request,
39618 +       .free_iso_request = free_iso_request,
39619 +};
39620 +
39621 +#else
39622 +
39623 +       int (*enable) (struct usb_ep *ep,
39624 +               const struct usb_endpoint_descriptor *desc);
39625 +       int (*disable) (struct usb_ep *ep);
39626 +
39627 +       struct usb_request *(*alloc_request) (struct usb_ep *ep,
39628 +               gfp_t gfp_flags);
39629 +       void (*free_request) (struct usb_ep *ep, struct usb_request *req);
39630 +
39631 +       int (*queue) (struct usb_ep *ep, struct usb_request *req,
39632 +               gfp_t gfp_flags);
39633 +       int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
39634 +
39635 +       int (*set_halt) (struct usb_ep *ep, int value);
39636 +       int (*set_wedge) (struct usb_ep *ep);
39637 +
39638 +       int (*fifo_status) (struct usb_ep *ep);
39639 +       void (*fifo_flush) (struct usb_ep *ep);
39640 +static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
39641 +       .enable = ep_enable,
39642 +       .disable = ep_disable,
39643 +
39644 +       .alloc_request = dwc_otg_pcd_alloc_request,
39645 +       .free_request = dwc_otg_pcd_free_request,
39646 +
39647 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
39648 +       .alloc_buffer = dwc_otg_pcd_alloc_buffer,
39649 +       .free_buffer = dwc_otg_pcd_free_buffer,
39650 +#else
39651 +       /* .set_wedge = ep_wedge, */
39652 +        .set_wedge = NULL, /* uses set_halt instead */
39653 +#endif
39654 +        
39655 +       .queue = ep_queue,
39656 +       .dequeue = ep_dequeue,
39657 +
39658 +       .set_halt = ep_halt,
39659 +       .fifo_status = 0,
39660 +       .fifo_flush = 0,
39661 +
39662 +};
39663 +
39664 +#endif                         /* _EN_ISOC_ */
39665 +/*     Gadget Operations */
39666 +/**
39667 + * The following gadget operations will be implemented in the DWC_otg
39668 + * PCD. Functions in the API that are not described below are not
39669 + * implemented.
39670 + *
39671 + * The Gadget API provides wrapper functions for each of the function
39672 + * pointers defined in usb_gadget_ops. The Gadget Driver calls the
39673 + * wrapper function, which then calls the underlying PCD function. The
39674 + * following sections are named according to the wrapper functions
39675 + * (except for ioctl, which doesn't have a wrapper function). Within
39676 + * each section, the corresponding DWC_otg PCD function name is
39677 + * specified.
39678 + *
39679 + */
39680 +
39681 +/**
39682 + *Gets the USB Frame number of the last SOF.
39683 + */
39684 +static int get_frame_number(struct usb_gadget *gadget)
39685 +{
39686 +       struct gadget_wrapper *d;
39687 +
39688 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
39689 +
39690 +       if (gadget == 0) {
39691 +               return -ENODEV;
39692 +       }
39693 +
39694 +       d = container_of(gadget, struct gadget_wrapper, gadget);
39695 +       return dwc_otg_pcd_get_frame_number(d->pcd);
39696 +}
39697 +
39698 +#ifdef CONFIG_USB_DWC_OTG_LPM
39699 +static int test_lpm_enabled(struct usb_gadget *gadget)
39700 +{
39701 +       struct gadget_wrapper *d;
39702 +
39703 +       d = container_of(gadget, struct gadget_wrapper, gadget);
39704 +
39705 +       return dwc_otg_pcd_is_lpm_enabled(d->pcd);
39706 +}
39707 +#endif
39708 +
39709 +/**
39710 + * Initiates Session Request Protocol (SRP) to wakeup the host if no
39711 + * session is in progress. If a session is already in progress, but
39712 + * the device is suspended, remote wakeup signaling is started.
39713 + *
39714 + */
39715 +static int wakeup(struct usb_gadget *gadget)
39716 +{
39717 +       struct gadget_wrapper *d;
39718 +
39719 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
39720 +
39721 +       if (gadget == 0) {
39722 +               return -ENODEV;
39723 +       } else {
39724 +               d = container_of(gadget, struct gadget_wrapper, gadget);
39725 +       }
39726 +       dwc_otg_pcd_wakeup(d->pcd);
39727 +       return 0;
39728 +}
39729 +
39730 +static const struct usb_gadget_ops dwc_otg_pcd_ops = {
39731 +       .get_frame = get_frame_number,
39732 +       .wakeup = wakeup,
39733 +#ifdef CONFIG_USB_DWC_OTG_LPM
39734 +       .lpm_support = test_lpm_enabled,
39735 +#endif
39736 +       // current versions must always be self-powered
39737 +};
39738 +
39739 +static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
39740 +{
39741 +       int retval = -DWC_E_NOT_SUPPORTED;
39742 +       if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
39743 +               retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
39744 +                                                      (struct usb_ctrlrequest
39745 +                                                       *)bytes);
39746 +       }
39747 +
39748 +       if (retval == -ENOTSUPP) {
39749 +               retval = -DWC_E_NOT_SUPPORTED;
39750 +       } else if (retval < 0) {
39751 +               retval = -DWC_E_INVALID;
39752 +       }
39753 +
39754 +       return retval;
39755 +}
39756 +
39757 +#ifdef DWC_EN_ISOC
39758 +static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
39759 +                         void *req_handle, int proc_buf_num)
39760 +{
39761 +       int i, packet_count;
39762 +       struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
39763 +       struct usb_iso_request *iso_req = req_handle;
39764 +
39765 +       if (proc_buf_num) {
39766 +               iso_packet = iso_req->iso_packet_desc1;
39767 +       } else {
39768 +               iso_packet = iso_req->iso_packet_desc0;
39769 +       }
39770 +       packet_count =
39771 +           dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
39772 +       for (i = 0; i < packet_count; ++i) {
39773 +               int status;
39774 +               int actual;
39775 +               int offset;
39776 +               dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
39777 +                                                 i, &status, &actual, &offset);
39778 +               switch (status) {
39779 +               case -DWC_E_NO_DATA:
39780 +                       status = -ENODATA;
39781 +                       break;
39782 +               default:
39783 +                       if (status) {
39784 +                               DWC_PRINTF("unknown status in isoc packet\n");
39785 +                       }
39786 +
39787 +               }
39788 +               iso_packet[i].status = status;
39789 +               iso_packet[i].offset = offset;
39790 +               iso_packet[i].actual_length = actual;
39791 +       }
39792 +
39793 +       iso_req->status = 0;
39794 +       iso_req->process_buffer(ep_handle, iso_req);
39795 +
39796 +       return 0;
39797 +}
39798 +#endif                         /* DWC_EN_ISOC */
39799 +
39800 +static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
39801 +                    void *req_handle, int32_t status, uint32_t actual)
39802 +{
39803 +       struct usb_request *req = (struct usb_request *)req_handle;
39804 +
39805 +       if (req && req->complete) {
39806 +               switch (status) {
39807 +               case -DWC_E_SHUTDOWN:
39808 +                       req->status = -ESHUTDOWN;
39809 +                       break;
39810 +               case -DWC_E_RESTART:
39811 +                       req->status = -ECONNRESET;
39812 +                       break;
39813 +               case -DWC_E_INVALID:
39814 +                       req->status = -EINVAL;
39815 +                       break;
39816 +               case -DWC_E_TIMEOUT:
39817 +                       req->status = -ETIMEDOUT;
39818 +                       break;
39819 +               default:
39820 +                       req->status = status;
39821 +
39822 +               }
39823 +               req->actual = actual;
39824 +               req->complete(ep_handle, req);
39825 +       }
39826 +
39827 +       return 0;
39828 +}
39829 +
39830 +static int _connect(dwc_otg_pcd_t * pcd, int speed)
39831 +{
39832 +       gadget_wrapper->gadget.speed = speed;
39833 +       return 0;
39834 +}
39835 +
39836 +static int _disconnect(dwc_otg_pcd_t * pcd)
39837 +{
39838 +       if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
39839 +               gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
39840 +       }
39841 +       return 0;
39842 +}
39843 +
39844 +static int _resume(dwc_otg_pcd_t * pcd)
39845 +{
39846 +       if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
39847 +               gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
39848 +       }
39849 +
39850 +       return 0;
39851 +}
39852 +
39853 +static int _suspend(dwc_otg_pcd_t * pcd)
39854 +{
39855 +       if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
39856 +               gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
39857 +       }
39858 +       return 0;
39859 +}
39860 +
39861 +/**
39862 + * This function updates the otg values in the gadget structure.
39863 + */
39864 +static int _hnp_changed(dwc_otg_pcd_t * pcd)
39865 +{
39866 +
39867 +       if (!gadget_wrapper->gadget.is_otg)
39868 +               return 0;
39869 +
39870 +       gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
39871 +       gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
39872 +       gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
39873 +       return 0;
39874 +}
39875 +
39876 +static int _reset(dwc_otg_pcd_t * pcd)
39877 +{
39878 +       return 0;
39879 +}
39880 +
39881 +#ifdef DWC_UTE_CFI
39882 +static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
39883 +{
39884 +       int retval = -DWC_E_INVALID;
39885 +       if (gadget_wrapper->driver->cfi_feature_setup) {
39886 +               retval =
39887 +                   gadget_wrapper->driver->cfi_feature_setup(&gadget_wrapper->
39888 +                                                             gadget,
39889 +                                                             (struct
39890 +                                                              cfi_usb_ctrlrequest
39891 +                                                              *)cfi_req);
39892 +       }
39893 +
39894 +       return retval;
39895 +}
39896 +#endif
39897 +
39898 +static const struct dwc_otg_pcd_function_ops fops = {
39899 +       .complete = _complete,
39900 +#ifdef DWC_EN_ISOC
39901 +       .isoc_complete = _isoc_complete,
39902 +#endif
39903 +       .setup = _setup,
39904 +       .disconnect = _disconnect,
39905 +       .connect = _connect,
39906 +       .resume = _resume,
39907 +       .suspend = _suspend,
39908 +       .hnp_changed = _hnp_changed,
39909 +       .reset = _reset,
39910 +#ifdef DWC_UTE_CFI
39911 +       .cfi_setup = _cfi_setup,
39912 +#endif
39913 +};
39914 +
39915 +/**
39916 + * This function is the top level PCD interrupt handler.
39917 + */
39918 +static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
39919 +{
39920 +       dwc_otg_pcd_t *pcd = dev;
39921 +       int32_t retval = IRQ_NONE;
39922 +
39923 +       retval = dwc_otg_pcd_handle_intr(pcd);
39924 +       if (retval != 0) {
39925 +               S3C2410X_CLEAR_EINTPEND();
39926 +       }
39927 +       return IRQ_RETVAL(retval);
39928 +}
39929 +
39930 +/**
39931 + * This function initialized the usb_ep structures to there default
39932 + * state.
39933 + *
39934 + * @param d Pointer on gadget_wrapper.
39935 + */
39936 +void gadget_add_eps(struct gadget_wrapper *d)
39937 +{
39938 +       static const char *names[] = {
39939 +
39940 +               "ep0",
39941 +               "ep1in",
39942 +               "ep2in",
39943 +               "ep3in",
39944 +               "ep4in",
39945 +               "ep5in",
39946 +               "ep6in",
39947 +               "ep7in",
39948 +               "ep8in",
39949 +               "ep9in",
39950 +               "ep10in",
39951 +               "ep11in",
39952 +               "ep12in",
39953 +               "ep13in",
39954 +               "ep14in",
39955 +               "ep15in",
39956 +               "ep1out",
39957 +               "ep2out",
39958 +               "ep3out",
39959 +               "ep4out",
39960 +               "ep5out",
39961 +               "ep6out",
39962 +               "ep7out",
39963 +               "ep8out",
39964 +               "ep9out",
39965 +               "ep10out",
39966 +               "ep11out",
39967 +               "ep12out",
39968 +               "ep13out",
39969 +               "ep14out",
39970 +               "ep15out"
39971 +       };
39972 +
39973 +       int i;
39974 +       struct usb_ep *ep;
39975 +
39976 +       DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
39977 +
39978 +       INIT_LIST_HEAD(&d->gadget.ep_list);
39979 +       d->gadget.ep0 = &d->ep0;
39980 +       d->gadget.speed = USB_SPEED_UNKNOWN;
39981 +
39982 +       INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
39983 +
39984 +       /**
39985 +        * Initialize the EP0 structure.
39986 +        */
39987 +       ep = &d->ep0;
39988 +
39989 +       /* Init the usb_ep structure. */
39990 +       ep->name = names[0];
39991 +       ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
39992 +
39993 +       /**
39994 +        * @todo NGS: What should the max packet size be set to
39995 +        * here?  Before EP type is set?
39996 +        */
39997 +       ep->maxpacket = MAX_PACKET_SIZE;
39998 +       dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
39999 +
40000 +       list_add_tail(&ep->ep_list, &d->gadget.ep_list);
40001 +
40002 +       /**
40003 +        * Initialize the EP structures.
40004 +        */
40005 +
40006 +       for (i = 0; i < 15; i++) {
40007 +               ep = &d->in_ep[i];
40008 +
40009 +               /* Init the usb_ep structure. */
40010 +               ep->name = names[i + 1];
40011 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
40012 +
40013 +               /**
40014 +                * @todo NGS: What should the max packet size be set to
40015 +                * here?  Before EP type is set?
40016 +                */
40017 +               ep->maxpacket = MAX_PACKET_SIZE;
40018 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
40019 +       }
40020 +
40021 +       for (i = 0; i < 15; i++) {
40022 +               ep = &d->out_ep[i];
40023 +
40024 +               /* Init the usb_ep structure. */
40025 +               ep->name = names[15 + i + 1];
40026 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
40027 +
40028 +               /**
40029 +                * @todo NGS: What should the max packet size be set to
40030 +                * here?  Before EP type is set?
40031 +                */
40032 +               ep->maxpacket = MAX_PACKET_SIZE;
40033 +
40034 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
40035 +       }
40036 +
40037 +       /* remove ep0 from the list.  There is a ep0 pointer. */
40038 +       list_del_init(&d->ep0.ep_list);
40039 +
40040 +       d->ep0.maxpacket = MAX_EP0_SIZE;
40041 +}
40042 +
40043 +/**
40044 + * This function releases the Gadget device.
40045 + * required by device_unregister().
40046 + *
40047 + * @todo Should this do something?     Should it free the PCD?
40048 + */
40049 +static void dwc_otg_pcd_gadget_release(struct device *dev)
40050 +{
40051 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
40052 +}
40053 +
40054 +static struct gadget_wrapper *alloc_wrapper(
40055 +#ifdef LM_INTERFACE
40056 +       struct lm_device *_dev
40057 +#elif  defined(PCI_INTERFACE)
40058 +       struct pci_dev *_dev
40059 +#elif  defined(PLATFORM_INTERFACE)
40060 +       struct platform_device *_dev
40061 +#endif
40062 +       )
40063 +{
40064 +#ifdef LM_INTERFACE
40065 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
40066 +#elif defined(PCI_INTERFACE)
40067 +       dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
40068 +#elif defined(PLATFORM_INTERFACE)
40069 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
40070 +#endif
40071 +       static char pcd_name[] = "dwc_otg_pcd";
40072 +
40073 +       struct gadget_wrapper *d;
40074 +       int retval;
40075 +
40076 +       d = dwc_alloc(sizeof(*d));
40077 +       if (d == NULL) {
40078 +               return NULL;
40079 +       }
40080 +
40081 +       memset(d, 0, sizeof(*d));
40082 +
40083 +       d->gadget.name = pcd_name;
40084 +       d->pcd = otg_dev->pcd;
40085 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
40086 +       strcpy(d->gadget.dev.bus_id, "gadget");
40087 +#else
40088 +       /*d->gadget.dev.bus = NULL;*/
40089 +        d->gadget.dev.init_name = "gadget";
40090 +#endif
40091 +       d->gadget.dev.parent = &_dev->dev;
40092 +       d->gadget.dev.release = dwc_otg_pcd_gadget_release;
40093 +       d->gadget.ops = &dwc_otg_pcd_ops;
40094 +       d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd)?USB_SPEED_HIGH:0;
40095 +       d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
40096 +
40097 +       d->driver = 0;
40098 +       /* Register the gadget device */
40099 +       retval = device_register(&d->gadget.dev);
40100 +       if (retval != 0) {
40101 +               DWC_ERROR("device_register failed\n");
40102 +               dwc_free(d);
40103 +               return NULL;
40104 +       }
40105 +
40106 +       return d;
40107 +}
40108 +
40109 +static void free_wrapper(struct gadget_wrapper *d)
40110 +{
40111 +       if (d->driver) {
40112 +               /* should have been done already by driver model core */
40113 +               DWC_WARN("driver '%s' is still registered\n",
40114 +                        d->driver->driver.name);
40115 +               usb_gadget_unregister_driver(d->driver);
40116 +       }
40117 +
40118 +       device_unregister(&d->gadget.dev);
40119 +       dwc_free(d);
40120 +}
40121 +
40122 +/**
40123 + * This function initialized the PCD portion of the driver.
40124 + *
40125 + */
40126 +int pcd_init(
40127 +#ifdef LM_INTERFACE
40128 +       struct lm_device *_dev
40129 +#elif  defined(PCI_INTERFACE)
40130 +       struct pci_dev *_dev
40131 +#elif  defined(PLATFORM_INTERFACE)
40132 +       struct platform_device *_dev
40133 +#endif
40134 +       )
40135 +
40136 +{
40137 +#ifdef LM_INTERFACE
40138 +        dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
40139 +#elif  defined(PCI_INTERFACE)
40140 +        dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
40141 +#elif  defined(PLATFORM_INTERFACE)
40142 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
40143 +#endif
40144 +        int devirq;
40145 +
40146 +       int retval = 0;
40147 +
40148 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev);
40149 +
40150 +       otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
40151 +
40152 +       if (!otg_dev->pcd) {
40153 +               DWC_ERROR("dwc_otg_pcd_init failed\n");
40154 +               return -ENOMEM;
40155 +       }
40156 +
40157 +       gadget_wrapper = alloc_wrapper(_dev);
40158 +
40159 +       /*
40160 +        * Initialize EP structures
40161 +        */
40162 +       gadget_add_eps(gadget_wrapper);
40163 +
40164 +       /*
40165 +        * Setup interupt handler
40166 +        */
40167 +#ifdef PLATFORM_INTERFACE
40168 +        devirq = platform_get_irq(_dev, 0);
40169 +#else
40170 +        devirq = _dev->irq;
40171 +#endif
40172 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", devirq);
40173 +       retval = request_irq(devirq, dwc_otg_pcd_irq,
40174 +                            IRQF_SHARED, gadget_wrapper->gadget.name,
40175 +                            otg_dev->pcd);
40176 +       if (retval != 0) {
40177 +                DWC_ERROR("request of irq%d failed\n", devirq);
40178 +               free_wrapper(gadget_wrapper);
40179 +               return -EBUSY;
40180 +       }
40181 +
40182 +       dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
40183 +
40184 +       return retval;
40185 +}
40186 +
40187 +/**
40188 + * Cleanup the PCD.
40189 + */
40190 +void pcd_remove(
40191 +#ifdef LM_INTERFACE
40192 +       struct lm_device *_dev
40193 +#elif  defined(PCI_INTERFACE)
40194 +       struct pci_dev *_dev
40195 +#elif  defined(PLATFORM_INTERFACE)
40196 +       struct platform_device *_dev
40197 +#endif
40198 +       )
40199 +{
40200 +#ifdef LM_INTERFACE
40201 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
40202 +#elif  defined(PCI_INTERFACE)
40203 +       dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
40204 +#elif  defined(PLATFORM_INTERFACE)
40205 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
40206 +#endif
40207 +       dwc_otg_pcd_t *pcd = otg_dev->pcd;
40208 +
40209 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
40210 +
40211 +       /*
40212 +        * Free the IRQ
40213 +        */
40214 +#ifdef PLATFORM_INTERFACE
40215 +       free_irq(platform_get_irq(_dev, 0), pcd);
40216 +#else
40217 +       free_irq(_dev->irq, pcd);
40218 +#endif
40219 +       dwc_otg_pcd_remove(otg_dev->pcd);
40220 +       free_wrapper(gadget_wrapper);
40221 +       otg_dev->pcd = 0;
40222 +}
40223 +
40224 +/**
40225 + * This function registers a gadget driver with the PCD.
40226 + *
40227 + * When a driver is successfully registered, it will receive control
40228 + * requests including set_configuration(), which enables non-control
40229 + * requests.  then usb traffic follows until a disconnect is reported.
40230 + * then a host may connect again, or the driver might get unbound.
40231 + *
40232 + * @param driver The driver being registered
40233 + */
40234 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
40235 +int usb_gadget_register_driver(struct usb_gadget_driver *driver)
40236 +#else
40237 +int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
40238 +               int (*bind)(struct usb_gadget *))
40239 +#endif
40240 +{
40241 +       int retval;
40242 +
40243 +       DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
40244 +                   driver->driver.name);
40245 +
40246 +       if (!driver || driver->max_speed == USB_SPEED_UNKNOWN ||
40247 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
40248 +           !driver->bind ||
40249 +#else
40250 +            !bind ||
40251 +#endif
40252 +           !driver->unbind || !driver->disconnect || !driver->setup) {
40253 +               DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
40254 +               return -EINVAL;
40255 +       }
40256 +       if (gadget_wrapper == 0) {
40257 +               DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
40258 +               return -ENODEV;
40259 +       }
40260 +       if (gadget_wrapper->driver != 0) {
40261 +               DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
40262 +               return -EBUSY;
40263 +       }
40264 +
40265 +       /* hook up the driver */
40266 +       gadget_wrapper->driver = driver;
40267 +       gadget_wrapper->gadget.dev.driver = &driver->driver;
40268 +
40269 +       DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
40270 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
40271 +       retval = driver->bind(&gadget_wrapper->gadget);
40272 +#else
40273 +       retval = bind(&gadget_wrapper->gadget);
40274 +#endif
40275 +       if (retval) {
40276 +               DWC_ERROR("bind to driver %s --> error %d\n",
40277 +                         driver->driver.name, retval);
40278 +               gadget_wrapper->driver = 0;
40279 +               gadget_wrapper->gadget.dev.driver = 0;
40280 +               return retval;
40281 +       }
40282 +       DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
40283 +                   driver->driver.name);
40284 +       return 0;
40285 +}
40286 +
40287 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
40288 +EXPORT_SYMBOL(usb_gadget_register_driver);
40289 +#else
40290 +EXPORT_SYMBOL(usb_gadget_probe_driver);
40291 +#endif
40292 +
40293 +/**
40294 + * This function unregisters a gadget driver
40295 + *
40296 + * @param driver The driver being unregistered
40297 + */
40298 +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
40299 +{
40300 +       //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);
40301 +
40302 +       if (gadget_wrapper == 0) {
40303 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
40304 +                           -ENODEV);
40305 +               return -ENODEV;
40306 +       }
40307 +       if (driver == 0 || driver != gadget_wrapper->driver) {
40308 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
40309 +                           -EINVAL);
40310 +               return -EINVAL;
40311 +       }
40312 +
40313 +       driver->unbind(&gadget_wrapper->gadget);
40314 +       gadget_wrapper->driver = 0;
40315 +
40316 +       DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
40317 +       return 0;
40318 +}
40319 +
40320 +EXPORT_SYMBOL(usb_gadget_unregister_driver);
40321 +
40322 +#endif                         /* DWC_HOST_ONLY */
40323 --- /dev/null
40324 +++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h
40325 @@ -0,0 +1,2237 @@
40326 +/* ==========================================================================
40327 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
40328 + * $Revision: #76 $
40329 + * $Date: 2009/04/02 $
40330 + * $Change: 1224216 $
40331 + *
40332 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
40333 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
40334 + * otherwise expressly agreed to in writing between Synopsys and you.
40335 + * 
40336 + * The Software IS NOT an item of Licensed Software or Licensed Product under
40337 + * any End User Software License Agreement or Agreement for Licensed Product
40338 + * with Synopsys or any supplement thereto. You are permitted to use and
40339 + * redistribute this Software in source and binary forms, with or without
40340 + * modification, provided that redistributions of source code must retain this
40341 + * notice. You may not view, use, disclose, copy or distribute this file or
40342 + * any information contained herein except pursuant to this license grant from
40343 + * Synopsys. If you do not agree with this notice, including the disclaimer
40344 + * below, then you are not authorized to use the Software.
40345 + * 
40346 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
40347 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40348 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40349 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
40350 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40351 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40352 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40353 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40354 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40355 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
40356 + * DAMAGE.
40357 + * ========================================================================== */
40358 +
40359 +#ifndef __DWC_OTG_REGS_H__
40360 +#define __DWC_OTG_REGS_H__
40361 +
40362 +#include "dwc_otg_core_if.h"
40363 +
40364 +/**
40365 + * @file
40366 + *
40367 + * This file contains the data structures for accessing the DWC_otg core registers.
40368 + *
40369 + * The application interfaces with the HS OTG core by reading from and
40370 + * writing to the Control and Status Register (CSR) space through the
40371 + * AHB Slave interface. These registers are 32 bits wide, and the
40372 + * addresses are 32-bit-block aligned.
40373 + * CSRs are classified as follows:
40374 + * - Core Global Registers
40375 + * - Device Mode Registers
40376 + * - Device Global Registers
40377 + * - Device Endpoint Specific Registers
40378 + * - Host Mode Registers
40379 + * - Host Global Registers
40380 + * - Host Port CSRs
40381 + * - Host Channel Specific Registers
40382 + *
40383 + * Only the Core Global registers can be accessed in both Device and
40384 + * Host modes. When the HS OTG core is operating in one mode, either
40385 + * Device or Host, the application must not access registers from the
40386 + * other mode. When the core switches from one mode to another, the
40387 + * registers in the new mode of operation must be reprogrammed as they
40388 + * would be after a power-on reset.
40389 + */
40390 +
40391 +/****************************************************************************/
40392 +/** DWC_otg Core registers .  
40393 + * The dwc_otg_core_global_regs structure defines the size
40394 + * and relative field offsets for the Core Global registers.
40395 + */
40396 +typedef struct dwc_otg_core_global_regs {
40397 +       /** OTG Control and Status Register.  <i>Offset: 000h</i> */
40398 +       volatile uint32_t gotgctl;
40399 +       /** OTG Interrupt Register.      <i>Offset: 004h</i> */
40400 +       volatile uint32_t gotgint;
40401 +       /**Core AHB Configuration Register.      <i>Offset: 008h</i> */
40402 +       volatile uint32_t gahbcfg;
40403 +
40404 +#define DWC_GLBINTRMASK                0x0001
40405 +#define DWC_DMAENABLE          0x0020
40406 +#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
40407 +#define DWC_NPTXEMPTYLVL_HALFEMPTY     0x0000
40408 +#define DWC_PTXEMPTYLVL_EMPTY  0x0100
40409 +#define DWC_PTXEMPTYLVL_HALFEMPTY      0x0000
40410 +
40411 +       /**Core USB Configuration Register.      <i>Offset: 00Ch</i> */
40412 +       volatile uint32_t gusbcfg;
40413 +       /**Core Reset Register.  <i>Offset: 010h</i> */
40414 +       volatile uint32_t grstctl;
40415 +       /**Core Interrupt Register.      <i>Offset: 014h</i> */
40416 +       volatile uint32_t gintsts;
40417 +       /**Core Interrupt Mask Register.  <i>Offset: 018h</i> */
40418 +       volatile uint32_t gintmsk;
40419 +       /**Receive Status Queue Read Register (Read Only).      <i>Offset: 01Ch</i> */
40420 +       volatile uint32_t grxstsr;
40421 +       /**Receive Status Queue Read & POP Register (Read Only).  <i>Offset: 020h</i>*/
40422 +       volatile uint32_t grxstsp;
40423 +       /**Receive FIFO Size Register.  <i>Offset: 024h</i> */
40424 +       volatile uint32_t grxfsiz;
40425 +       /**Non Periodic Transmit FIFO Size Register.  <i>Offset: 028h</i> */
40426 +       volatile uint32_t gnptxfsiz;
40427 +       /**Non Periodic Transmit FIFO/Queue Status Register (Read
40428 +        * Only). <i>Offset: 02Ch</i> */
40429 +       volatile uint32_t gnptxsts;
40430 +       /**I2C Access Register.  <i>Offset: 030h</i> */
40431 +       volatile uint32_t gi2cctl;
40432 +       /**PHY Vendor Control Register.  <i>Offset: 034h</i> */
40433 +       volatile uint32_t gpvndctl;
40434 +       /**General Purpose Input/Output Register.  <i>Offset: 038h</i> */
40435 +       volatile uint32_t ggpio;
40436 +       /**User ID Register.  <i>Offset: 03Ch</i> */
40437 +       volatile uint32_t guid;
40438 +       /**Synopsys ID Register (Read Only).  <i>Offset: 040h</i> */
40439 +       volatile uint32_t gsnpsid;
40440 +       /**User HW Config1 Register (Read Only).  <i>Offset: 044h</i> */
40441 +       volatile uint32_t ghwcfg1;
40442 +       /**User HW Config2 Register (Read Only).  <i>Offset: 048h</i> */
40443 +       volatile uint32_t ghwcfg2;
40444 +#define DWC_SLAVE_ONLY_ARCH 0
40445 +#define DWC_EXT_DMA_ARCH 1
40446 +#define DWC_INT_DMA_ARCH 2
40447 +
40448 +#define DWC_MODE_HNP_SRP_CAPABLE       0
40449 +#define DWC_MODE_SRP_ONLY_CAPABLE      1
40450 +#define DWC_MODE_NO_HNP_SRP_CAPABLE            2
40451 +#define DWC_MODE_SRP_CAPABLE_DEVICE            3
40452 +#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
40453 +#define DWC_MODE_SRP_CAPABLE_HOST      5
40454 +#define DWC_MODE_NO_SRP_CAPABLE_HOST   6
40455 +
40456 +       /**User HW Config3 Register (Read Only).  <i>Offset: 04Ch</i> */
40457 +       volatile uint32_t ghwcfg3;
40458 +       /**User HW Config4 Register (Read Only).  <i>Offset: 050h</i>*/
40459 +       volatile uint32_t ghwcfg4;
40460 +       /** Core LPM Configuration register */
40461 +       volatile uint32_t glpmcfg;
40462 +       /** Reserved  <i>Offset: 058h-0FFh</i> */
40463 +       volatile uint32_t reserved[42];
40464 +       /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
40465 +       volatile uint32_t hptxfsiz;
40466 +       /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, 
40467 +               otherwise Device Transmit FIFO#n Register. 
40468 +        * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
40469 +       volatile uint32_t dptxfsiz_dieptxf[15];
40470 +} dwc_otg_core_global_regs_t;
40471 +
40472 +/**
40473 + * This union represents the bit fields of the Core OTG Control
40474 + * and Status Register (GOTGCTL).  Set the bits using the bit 
40475 + * fields then write the <i>d32</i> value to the register.
40476 + */
40477 +typedef union gotgctl_data {
40478 +       /** raw register data */
40479 +       uint32_t d32;
40480 +       /** register bits */
40481 +       struct {
40482 +               unsigned sesreqscs:1;
40483 +               unsigned sesreq:1;
40484 +               unsigned reserved2_7:6;
40485 +               unsigned hstnegscs:1;
40486 +               unsigned hnpreq:1;
40487 +               unsigned hstsethnpen:1;
40488 +               unsigned devhnpen:1;
40489 +               unsigned reserved12_15:4;
40490 +               unsigned conidsts:1;
40491 +               unsigned reserved17:1;
40492 +               unsigned asesvld:1;
40493 +               unsigned bsesvld:1;
40494 +               unsigned currmod:1;
40495 +               unsigned reserved21_31:11;
40496 +       } b;
40497 +} gotgctl_data_t;
40498 +
40499 +/**
40500 + * This union represents the bit fields of the Core OTG Interrupt Register
40501 + * (GOTGINT).  Set/clear the bits using the bit fields then write the <i>d32</i>
40502 + * value to the register.
40503 + */
40504 +typedef union gotgint_data {
40505 +       /** raw register data */
40506 +       uint32_t d32;
40507 +       /** register bits */
40508 +       struct {
40509 +               /** Current Mode */
40510 +               unsigned reserved0_1:2;
40511 +
40512 +               /** Session End Detected */
40513 +               unsigned sesenddet:1;
40514 +
40515 +               unsigned reserved3_7:5;
40516 +
40517 +               /** Session Request Success Status Change */
40518 +               unsigned sesreqsucstschng:1;
40519 +               /** Host Negotiation Success Status Change */
40520 +               unsigned hstnegsucstschng:1;
40521 +
40522 +               unsigned reserver10_16:7;
40523 +
40524 +               /** Host Negotiation Detected */
40525 +               unsigned hstnegdet:1;
40526 +               /** A-Device Timeout Change */
40527 +               unsigned adevtoutchng:1;
40528 +               /** Debounce Done */
40529 +               unsigned debdone:1;
40530 +
40531 +               unsigned reserved31_20:12;
40532 +
40533 +       } b;
40534 +} gotgint_data_t;
40535 +
40536 +/**
40537 + * This union represents the bit fields of the Core AHB Configuration
40538 + * Register (GAHBCFG). Set/clear the bits using the bit fields then
40539 + * write the <i>d32</i> value to the register.
40540 + */
40541 +typedef union gahbcfg_data {
40542 +       /** raw register data */
40543 +       uint32_t d32;
40544 +       /** register bits */
40545 +       struct {
40546 +               unsigned glblintrmsk:1;
40547 +#define DWC_GAHBCFG_GLBINT_ENABLE              1
40548 +
40549 +               unsigned hburstlen:4;
40550 +#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE       0
40551 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR         1
40552 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR4                3
40553 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR8                5
40554 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR16       7
40555 +
40556 +               unsigned dmaenable:1;
40557 +#define DWC_GAHBCFG_DMAENABLE                  1
40558 +               unsigned reserved:1;
40559 +               unsigned nptxfemplvl_txfemplvl:1;
40560 +               unsigned ptxfemplvl:1;
40561 +#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY          1
40562 +#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY      0
40563 +               unsigned reserved9_31:23;
40564 +       } b;
40565 +} gahbcfg_data_t;
40566 +
40567 +/**
40568 + * This union represents the bit fields of the Core USB Configuration
40569 + * Register (GUSBCFG). Set the bits using the bit fields then write
40570 + * the <i>d32</i> value to the register.
40571 + */
40572 +typedef union gusbcfg_data {
40573 +       /** raw register data */
40574 +       uint32_t d32;
40575 +       /** register bits */
40576 +       struct {
40577 +               unsigned toutcal:3;
40578 +               unsigned phyif:1;
40579 +               unsigned ulpi_utmi_sel:1;
40580 +               unsigned fsintf:1;
40581 +               unsigned physel:1;
40582 +               unsigned ddrsel:1;
40583 +               unsigned srpcap:1;
40584 +               unsigned hnpcap:1;
40585 +               unsigned usbtrdtim:4;
40586 +               unsigned nptxfrwnden:1;
40587 +               unsigned phylpwrclksel:1;
40588 +               unsigned otgutmifssel:1;
40589 +               unsigned ulpi_fsls:1;
40590 +               unsigned ulpi_auto_res:1;
40591 +               unsigned ulpi_clk_sus_m:1;
40592 +               unsigned ulpi_ext_vbus_drv:1;
40593 +               unsigned ulpi_int_vbus_indicator:1;
40594 +               unsigned term_sel_dl_pulse:1;
40595 +               unsigned reserved23_25:3;
40596 +               unsigned ic_usb_cap:1;
40597 +               unsigned ic_traffic_pull_remove:1;
40598 +               unsigned tx_end_delay:1;
40599 +               unsigned reserved29_31:3;
40600 +       } b;
40601 +} gusbcfg_data_t;
40602 +
40603 +/**
40604 + * This union represents the bit fields of the Core LPM Configuration 
40605 + * Register (GLPMCFG). Set the bits using bit fields then write
40606 + * the <i>d32</i> value to the register.
40607 + */
40608 +typedef union glpmctl_data {
40609 +       /** raw register data */
40610 +       uint32_t d32;
40611 +       /** register bits */
40612 +       struct {
40613 +               /** LPM-Capable (LPMCap) (Device and Host)
40614 +                * The application uses this bit to control 
40615 +                * the DWC_otg core LPM capabilities.
40616 +                */
40617 +               unsigned lpm_cap_en:1;
40618 +               /** LPM response programmed by application (AppL1Res) (Device)
40619 +                * Handshake response to LPM token pre-programmed 
40620 +                * by device application software.
40621 +                */
40622 +               unsigned appl_resp:1;
40623 +               /** Host Initiated Resume Duration (HIRD) (Device and Host)
40624 +                * In Host mode this field indicates the value of HIRD 
40625 +                * to be sent in an LPM transaction.
40626 +                * In Device mode this field is updated with the 
40627 +                * Received LPM Token HIRD bmAttribute 
40628 +                * when an ACK/NYET/STALL response is sent 
40629 +                * to an LPM transaction.
40630 +                */
40631 +               unsigned hird:4;
40632 +               /** RemoteWakeEnable (bRemoteWake) (Device and Host)
40633 +                * In Host mode this bit indicates the value of remote 
40634 +                * wake up to be sent in wIndex field of LPM transaction.
40635 +                * In Device mode this field is updated with the 
40636 +                * Received LPM Token bRemoteWake bmAttribute 
40637 +                * when an ACK/NYET/STALL response is sent 
40638 +                * to an LPM transaction.
40639 +                */
40640 +               unsigned rem_wkup_en:1;
40641 +               /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
40642 +                * The application uses this bit to control 
40643 +                * the utmi_sleep_n assertion to the PHY when in L1 state.
40644 +                */
40645 +               unsigned en_utmi_sleep:1;
40646 +               /** HIRD Threshold (HIRD_Thres) (Device and Host)
40647 +                */
40648 +               unsigned hird_thres:5;
40649 +               /** LPM Response (CoreL1Res) (Device and Host)
40650 +                * In Host mode this bit contains handsake response to 
40651 +                * LPM transaction.
40652 +                * In Device mode the response of the core to 
40653 +                * LPM transaction received is reflected in these two bits.
40654 +                       - 0x0 : ERROR (No handshake response)
40655 +                       - 0x1 : STALL
40656 +                       - 0x2 : NYET
40657 +                       - 0x3 : ACK                     
40658 +                */
40659 +               unsigned lpm_resp:2;
40660 +               /** Port Sleep Status (SlpSts) (Device and Host)
40661 +                * This bit is set as long as a Sleep condition 
40662 +                * is present on the USB bus.
40663 +                */
40664 +               unsigned prt_sleep_sts:1;
40665 +               /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
40666 +                * Indicates that the application or host 
40667 +                * can start resume from Sleep state.
40668 +                */
40669 +               unsigned sleep_state_resumeok:1;
40670 +               /** LPM channel Index (LPM_Chnl_Indx) (Host)
40671 +                * The channel number on which the LPM transaction 
40672 +                * has to be applied while sending 
40673 +                * an LPM transaction to the local device.
40674 +                */
40675 +               unsigned lpm_chan_index:4;
40676 +               /** LPM Retry Count (LPM_Retry_Cnt) (Host)
40677 +                * Number host retries that would be performed
40678 +                * if the device response was not valid response.
40679 +                */
40680 +               unsigned retry_count:3;
40681 +               /** Send LPM Transaction (SndLPM) (Host)
40682 +                * When set by application software, 
40683 +                * an LPM transaction containing two tokens 
40684 +                * is sent.
40685 +                */
40686 +               unsigned send_lpm:1;
40687 +               /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
40688 +                * Number of LPM Host Retries still remaining 
40689 +                * to be transmitted for the current LPM sequence
40690 +                */
40691 +               unsigned retry_count_sts:3;
40692 +               unsigned reserved28_29:2;
40693 +               /** In host mode once this bit is set, the host
40694 +                * configures to drive the HSIC Idle state on the bus. 
40695 +                * It then waits for the  device to initiate the Connect sequence.
40696 +                * In device mode once this bit is set, the device waits for 
40697 +                * the HSIC Idle line state on the bus. Upon receving the Idle 
40698 +                * line state, it initiates the HSIC Connect sequence.
40699 +                */
40700 +               unsigned hsic_connect:1;
40701 +               /** This bit overrides and functionally inverts 
40702 +                * the if_select_hsic input port signal.
40703 +                */
40704 +               unsigned inv_sel_hsic:1;
40705 +       } b;
40706 +} glpmcfg_data_t;
40707 +
40708 +/**
40709 + * This union represents the bit fields of the Core Reset Register
40710 + * (GRSTCTL).  Set/clear the bits using the bit fields then write the
40711 + * <i>d32</i> value to the register.
40712 + */
40713 +typedef union grstctl_data {
40714 +       /** raw register data */
40715 +       uint32_t d32;
40716 +       /** register bits */
40717 +       struct {
40718 +               /** Core Soft Reset (CSftRst) (Device and Host)
40719 +                *
40720 +                * The application can flush the control logic in the
40721 +                * entire core using this bit. This bit resets the
40722 +                * pipelines in the AHB Clock domain as well as the
40723 +                * PHY Clock domain.
40724 +                *
40725 +                * The state machines are reset to an IDLE state, the
40726 +                * control bits in the CSRs are cleared, all the
40727 +                * transmit FIFOs and the receive FIFO are flushed.
40728 +                *
40729 +                * The status mask bits that control the generation of
40730 +                * the interrupt, are cleared, to clear the
40731 +                * interrupt. The interrupt status bits are not
40732 +                * cleared, so the application can get the status of
40733 +                * any events that occurred in the core after it has
40734 +                * set this bit.
40735 +                *
40736 +                * Any transactions on the AHB are terminated as soon
40737 +                * as possible following the protocol. Any
40738 +                * transactions on the USB are terminated immediately.
40739 +                *
40740 +                * The configuration settings in the CSRs are
40741 +                * unchanged, so the software doesn't have to
40742 +                * reprogram these registers (Device
40743 +                * Configuration/Host Configuration/Core System
40744 +                * Configuration/Core PHY Configuration).
40745 +                *
40746 +                * The application can write to this bit, any time it
40747 +                * wants to reset the core. This is a self clearing
40748 +                * bit and the core clears this bit after all the
40749 +                * necessary logic is reset in the core, which may
40750 +                * take several clocks, depending on the current state
40751 +                * of the core.
40752 +                */
40753 +               unsigned csftrst:1;
40754 +               /** Hclk Soft Reset
40755 +                *
40756 +                * The application uses this bit to reset the control logic in
40757 +                * the AHB clock domain. Only AHB clock domain pipelines are
40758 +                * reset.
40759 +                */
40760 +               unsigned hsftrst:1;
40761 +               /** Host Frame Counter Reset (Host Only)<br>
40762 +                * 
40763 +                * The application can reset the (micro)frame number
40764 +                * counter inside the core, using this bit. When the
40765 +                * (micro)frame counter is reset, the subsequent SOF
40766 +                * sent out by the core, will have a (micro)frame
40767 +                * number of 0.
40768 +                */
40769 +               unsigned hstfrm:1;
40770 +               /** In Token Sequence Learning Queue Flush
40771 +                * (INTknQFlsh) (Device Only)
40772 +                */
40773 +               unsigned intknqflsh:1;
40774 +               /** RxFIFO Flush (RxFFlsh) (Device and Host)
40775 +                *
40776 +                * The application can flush the entire Receive FIFO
40777 +                * using this bit.      <p>The application must first
40778 +                * ensure that the core is not in the middle of a
40779 +                * transaction.  <p>The application should write into
40780 +                * this bit, only after making sure that neither the
40781 +                * DMA engine is reading from the RxFIFO nor the MAC
40782 +                * is writing the data in to the FIFO.  <p>The
40783 +                * application should wait until the bit is cleared
40784 +                * before performing any other operations. This bit
40785 +                * will takes 8 clocks (slowest of PHY or AHB clock)
40786 +                * to clear.
40787 +                */
40788 +               unsigned rxfflsh:1;
40789 +               /** TxFIFO Flush (TxFFlsh) (Device and Host).  
40790 +                *
40791 +                * This bit is used to selectively flush a single or
40792 +                * all transmit FIFOs.  The application must first
40793 +                * ensure that the core is not in the middle of a
40794 +                * transaction.  <p>The application should write into
40795 +                * this bit, only after making sure that neither the
40796 +                * DMA engine is writing into the TxFIFO nor the MAC
40797 +                * is reading the data out of the FIFO.  <p>The
40798 +                * application should wait until the core clears this
40799 +                * bit, before performing any operations. This bit
40800 +                * will takes 8 clocks (slowest of PHY or AHB clock)
40801 +                * to clear.
40802 +                */
40803 +               unsigned txfflsh:1;
40804 +
40805 +               /** TxFIFO Number (TxFNum) (Device and Host).
40806 +                * 
40807 +                * This is the FIFO number which needs to be flushed,
40808 +                * using the TxFIFO Flush bit. This field should not
40809 +                * be changed until the TxFIFO Flush bit is cleared by
40810 +                * the core.
40811 +                *       - 0x0 : Non Periodic TxFIFO Flush
40812 +                *       - 0x1 : Periodic TxFIFO #1 Flush in device mode
40813 +                *         or Periodic TxFIFO in host mode
40814 +                *       - 0x2 : Periodic TxFIFO #2 Flush in device mode.
40815 +                *       - ...
40816 +                *       - 0xF : Periodic TxFIFO #15 Flush in device mode
40817 +                *       - 0x10: Flush all the Transmit NonPeriodic and
40818 +                *         Transmit Periodic FIFOs in the core
40819 +                */
40820 +               unsigned txfnum:5;
40821 +               /** Reserved */
40822 +               unsigned reserved11_29:19;
40823 +               /** DMA Request Signal.  Indicated DMA request is in
40824 +                * probress.  Used for debug purpose. */
40825 +               unsigned dmareq:1;
40826 +               /** AHB Master Idle.  Indicates the AHB Master State
40827 +                * Machine is in IDLE condition. */
40828 +               unsigned ahbidle:1;
40829 +       } b;
40830 +} grstctl_t;
40831 +
40832 +/**
40833 + * This union represents the bit fields of the Core Interrupt Mask
40834 + * Register (GINTMSK). Set/clear the bits using the bit fields then
40835 + * write the <i>d32</i> value to the register.
40836 + */
40837 +typedef union gintmsk_data {
40838 +       /** raw register data */
40839 +       uint32_t d32;
40840 +       /** register bits */
40841 +       struct {
40842 +               unsigned reserved0:1;
40843 +               unsigned modemismatch:1;
40844 +               unsigned otgintr:1;
40845 +               unsigned sofintr:1;
40846 +               unsigned rxstsqlvl:1;
40847 +               unsigned nptxfempty:1;
40848 +               unsigned ginnakeff:1;
40849 +               unsigned goutnakeff:1;
40850 +               unsigned reserved8:1;
40851 +               unsigned i2cintr:1;
40852 +               unsigned erlysuspend:1;
40853 +               unsigned usbsuspend:1;
40854 +               unsigned usbreset:1;
40855 +               unsigned enumdone:1;
40856 +               unsigned isooutdrop:1;
40857 +               unsigned eopframe:1;
40858 +               unsigned reserved16:1;
40859 +               unsigned epmismatch:1;
40860 +               unsigned inepintr:1;
40861 +               unsigned outepintr:1;
40862 +               unsigned incomplisoin:1;
40863 +               unsigned incomplisoout:1;
40864 +               unsigned reserved22_23:2;
40865 +               unsigned portintr:1;
40866 +               unsigned hcintr:1;
40867 +               unsigned ptxfempty:1;
40868 +               unsigned lpmtranrcvd:1;
40869 +               unsigned conidstschng:1;
40870 +               unsigned disconnect:1;
40871 +               unsigned sessreqintr:1;
40872 +               unsigned wkupintr:1;
40873 +       } b;
40874 +} gintmsk_data_t;
40875 +/**
40876 + * This union represents the bit fields of the Core Interrupt Register
40877 + * (GINTSTS).  Set/clear the bits using the bit fields then write the
40878 + * <i>d32</i> value to the register.
40879 + */
40880 +typedef union gintsts_data {
40881 +       /** raw register data */
40882 +       uint32_t d32;
40883 +#define DWC_SOF_INTR_MASK 0x0008
40884 +       /** register bits */
40885 +       struct {
40886 +#define DWC_HOST_MODE 1
40887 +               unsigned curmode:1;
40888 +               unsigned modemismatch:1;
40889 +               unsigned otgintr:1;
40890 +               unsigned sofintr:1;
40891 +               unsigned rxstsqlvl:1;
40892 +               unsigned nptxfempty:1;
40893 +               unsigned ginnakeff:1;
40894 +               unsigned goutnakeff:1;
40895 +               unsigned reserved8:1;
40896 +               unsigned i2cintr:1;
40897 +               unsigned erlysuspend:1;
40898 +               unsigned usbsuspend:1;
40899 +               unsigned usbreset:1;
40900 +               unsigned enumdone:1;
40901 +               unsigned isooutdrop:1;
40902 +               unsigned eopframe:1;
40903 +               unsigned intokenrx:1;
40904 +               unsigned epmismatch:1;
40905 +               unsigned inepint:1;
40906 +               unsigned outepintr:1;
40907 +               unsigned incomplisoin:1;
40908 +               unsigned incomplisoout:1;
40909 +               unsigned reserved22_23:2;
40910 +               unsigned portintr:1;
40911 +               unsigned hcintr:1;
40912 +               unsigned ptxfempty:1;
40913 +               unsigned lpmtranrcvd:1;
40914 +               unsigned conidstschng:1;
40915 +               unsigned disconnect:1;
40916 +               unsigned sessreqintr:1;
40917 +               unsigned wkupintr:1;
40918 +       } b;
40919 +} gintsts_data_t;
40920 +
40921 +/**
40922 + * This union represents the bit fields in the Device Receive Status Read and 
40923 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i> 
40924 + * element then read out the bits using the <i>b</i>it elements.
40925 + */
40926 +typedef union device_grxsts_data {
40927 +       /** raw register data */
40928 +       uint32_t d32;
40929 +       /** register bits */
40930 +       struct {
40931 +               unsigned epnum:4;
40932 +               unsigned bcnt:11;
40933 +               unsigned dpid:2;
40934 +
40935 +#define DWC_STS_DATA_UPDT              0x2     // OUT Data Packet
40936 +#define DWC_STS_XFER_COMP              0x3     // OUT Data Transfer Complete
40937 +
40938 +#define DWC_DSTS_GOUT_NAK              0x1     // Global OUT NAK
40939 +#define DWC_DSTS_SETUP_COMP            0x4     // Setup Phase Complete
40940 +#define DWC_DSTS_SETUP_UPDT 0x6        // SETUP Packet
40941 +               unsigned pktsts:4;
40942 +               unsigned fn:4;
40943 +               unsigned reserved:7;
40944 +       } b;
40945 +} device_grxsts_data_t;
40946 +
40947 +/**
40948 + * This union represents the bit fields in the Host Receive Status Read and 
40949 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i> 
40950 + * element then read out the bits using the <i>b</i>it elements.
40951 + */
40952 +typedef union host_grxsts_data {
40953 +       /** raw register data */
40954 +       uint32_t d32;
40955 +       /** register bits */
40956 +       struct {
40957 +               unsigned chnum:4;
40958 +               unsigned bcnt:11;
40959 +               unsigned dpid:2;
40960 +
40961 +               unsigned pktsts:4;
40962 +#define DWC_GRXSTS_PKTSTS_IN                     0x2
40963 +#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP   0x3
40964 +#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
40965 +#define DWC_GRXSTS_PKTSTS_CH_HALTED              0x7
40966 +
40967 +               unsigned reserved:11;
40968 +       } b;
40969 +} host_grxsts_data_t;
40970 +
40971 +/**
40972 + * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
40973 + * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element then
40974 + * read out the bits using the <i>b</i>it elements.
40975 + */
40976 +typedef union fifosize_data {
40977 +       /** raw register data */
40978 +       uint32_t d32;
40979 +       /** register bits */
40980 +       struct {
40981 +               unsigned startaddr:16;
40982 +               unsigned depth:16;
40983 +       } b;
40984 +} fifosize_data_t;
40985 +
40986 +/**
40987 + * This union represents the bit fields in the Non-Periodic Transmit
40988 + * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
40989 + * <i>d32</i> element then read out the bits using the <i>b</i>it
40990 + * elements.
40991 + */
40992 +typedef union gnptxsts_data {
40993 +       /** raw register data */
40994 +       uint32_t d32;
40995 +       /** register bits */
40996 +       struct {
40997 +               unsigned nptxfspcavail:16;
40998 +               unsigned nptxqspcavail:8;
40999 +               /** Top of the Non-Periodic Transmit Request Queue 
41000 +                *      - bit 24 - Terminate (Last entry for the selected
41001 +                *        channel/EP)
41002 +                *      - bits 26:25 - Token Type 
41003 +                *        - 2'b00 - IN/OUT
41004 +                *        - 2'b01 - Zero Length OUT
41005 +                *        - 2'b10 - PING/Complete Split
41006 +                *        - 2'b11 - Channel Halt
41007 +                *      - bits 30:27 - Channel/EP Number
41008 +                */
41009 +               unsigned nptxqtop_terminate:1;
41010 +               unsigned nptxqtop_token:2;
41011 +               unsigned nptxqtop_chnep:4;
41012 +               unsigned reserved:1;
41013 +       } b;
41014 +} gnptxsts_data_t;
41015 +
41016 +/**
41017 + * This union represents the bit fields in the Transmit
41018 + * FIFO Status Register (DTXFSTS). Read the register into the
41019 + * <i>d32</i> element then read out the bits using the <i>b</i>it
41020 + * elements.
41021 + */
41022 +typedef union dtxfsts_data {
41023 +       /** raw register data */
41024 +       uint32_t d32;
41025 +       /** register bits */
41026 +       struct {
41027 +               unsigned txfspcavail:16;
41028 +               unsigned reserved:16;
41029 +       } b;
41030 +} dtxfsts_data_t;
41031 +
41032 +/**
41033 + * This union represents the bit fields in the I2C Control Register
41034 + * (I2CCTL). Read the register into the <i>d32</i> element then read out the
41035 + * bits using the <i>b</i>it elements.
41036 + */
41037 +typedef union gi2cctl_data {
41038 +       /** raw register data */
41039 +       uint32_t d32;
41040 +       /** register bits */
41041 +       struct {
41042 +               unsigned rwdata:8;
41043 +               unsigned regaddr:8;
41044 +               unsigned addr:7;
41045 +               unsigned i2cen:1;
41046 +               unsigned ack:1;
41047 +               unsigned i2csuspctl:1;
41048 +               unsigned i2cdevaddr:2;
41049 +               unsigned reserved:2;
41050 +               unsigned rw:1;
41051 +               unsigned bsydne:1;
41052 +       } b;
41053 +} gi2cctl_data_t;
41054 +
41055 +/**
41056 + * This union represents the bit fields in the User HW Config1
41057 + * Register.  Read the register into the <i>d32</i> element then read
41058 + * out the bits using the <i>b</i>it elements.
41059 + */
41060 +typedef union hwcfg1_data {
41061 +       /** raw register data */
41062 +       uint32_t d32;
41063 +       /** register bits */
41064 +       struct {
41065 +               unsigned ep_dir0:2;
41066 +               unsigned ep_dir1:2;
41067 +               unsigned ep_dir2:2;
41068 +               unsigned ep_dir3:2;
41069 +               unsigned ep_dir4:2;
41070 +               unsigned ep_dir5:2;
41071 +               unsigned ep_dir6:2;
41072 +               unsigned ep_dir7:2;
41073 +               unsigned ep_dir8:2;
41074 +               unsigned ep_dir9:2;
41075 +               unsigned ep_dir10:2;
41076 +               unsigned ep_dir11:2;
41077 +               unsigned ep_dir12:2;
41078 +               unsigned ep_dir13:2;
41079 +               unsigned ep_dir14:2;
41080 +               unsigned ep_dir15:2;
41081 +       } b;
41082 +} hwcfg1_data_t;
41083 +
41084 +/**
41085 + * This union represents the bit fields in the User HW Config2
41086 + * Register.  Read the register into the <i>d32</i> element then read
41087 + * out the bits using the <i>b</i>it elements.
41088 + */
41089 +typedef union hwcfg2_data {
41090 +       /** raw register data */
41091 +       uint32_t d32;
41092 +       /** register bits */
41093 +       struct {
41094 +               /* GHWCFG2 */
41095 +               unsigned op_mode:3;
41096 +#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
41097 +#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
41098 +#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
41099 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
41100 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
41101 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
41102 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
41103 +
41104 +               unsigned architecture:2;
41105 +               unsigned point2point:1;
41106 +               unsigned hs_phy_type:2;
41107 +#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
41108 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
41109 +#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
41110 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
41111 +
41112 +               unsigned fs_phy_type:2;
41113 +               unsigned num_dev_ep:4;
41114 +               unsigned num_host_chan:4;
41115 +               unsigned perio_ep_supported:1;
41116 +               unsigned dynamic_fifo:1;
41117 +               unsigned multi_proc_int:1;
41118 +               unsigned reserved21:1;
41119 +               unsigned nonperio_tx_q_depth:2;
41120 +               unsigned host_perio_tx_q_depth:2;
41121 +               unsigned dev_token_q_depth:5;
41122 +               unsigned reserved31:1;
41123 +       } b;
41124 +} hwcfg2_data_t;
41125 +
41126 +/**
41127 + * This union represents the bit fields in the User HW Config3
41128 + * Register.  Read the register into the <i>d32</i> element then read
41129 + * out the bits using the <i>b</i>it elements.
41130 + */
41131 +typedef union hwcfg3_data {
41132 +       /** raw register data */
41133 +       uint32_t d32;
41134 +       /** register bits */
41135 +       struct {
41136 +               /* GHWCFG3 */
41137 +               unsigned xfer_size_cntr_width:4;
41138 +               unsigned packet_size_cntr_width:3;
41139 +               unsigned otg_func:1;
41140 +               unsigned i2c:1;
41141 +               unsigned vendor_ctrl_if:1;
41142 +               unsigned optional_features:1;
41143 +               unsigned synch_reset_type:1;
41144 +               unsigned otg_enable_ic_usb:1;
41145 +               unsigned otg_enable_hsic:1;
41146 +               unsigned reserved14:1;
41147 +               unsigned otg_lpm_en:1;
41148 +               unsigned dfifo_depth:16;
41149 +       } b;
41150 +} hwcfg3_data_t;
41151 +
41152 +/**
41153 + * This union represents the bit fields in the User HW Config4
41154 + * Register.  Read the register into the <i>d32</i> element then read
41155 + * out the bits using the <i>b</i>it elements.
41156 + */
41157 +typedef union hwcfg4_data {
41158 +       /** raw register data */
41159 +       uint32_t d32;
41160 +       /** register bits */
41161 +       struct {
41162 +               unsigned num_dev_perio_in_ep:4;
41163 +               unsigned power_optimiz:1;
41164 +               unsigned min_ahb_freq:9;
41165 +               unsigned utmi_phy_data_width:2;
41166 +               unsigned num_dev_mode_ctrl_ep:4;
41167 +               unsigned iddig_filt_en:1;
41168 +               unsigned vbus_valid_filt_en:1;
41169 +               unsigned a_valid_filt_en:1;
41170 +               unsigned b_valid_filt_en:1;
41171 +               unsigned session_end_filt_en:1;
41172 +               unsigned ded_fifo_en:1;
41173 +               unsigned num_in_eps:4;
41174 +               unsigned desc_dma:1;
41175 +               unsigned desc_dma_dyn:1;
41176 +       } b;
41177 +} hwcfg4_data_t;
41178 +
41179 +////////////////////////////////////////////
41180 +// Device Registers
41181 +/**
41182 + * Device Global Registers. <i>Offsets 800h-BFFh</i>
41183 + *
41184 + * The following structures define the size and relative field offsets
41185 + * for the Device Mode Registers.
41186 + *
41187 + * <i>These registers are visible only in Device mode and must not be
41188 + * accessed in Host mode, as the results are unknown.</i>
41189 + */
41190 +typedef struct dwc_otg_dev_global_regs {
41191 +       /** Device Configuration Register. <i>Offset 800h</i> */
41192 +       volatile uint32_t dcfg;
41193 +       /** Device Control Register. <i>Offset: 804h</i> */
41194 +       volatile uint32_t dctl;
41195 +       /** Device Status Register (Read Only). <i>Offset: 808h</i> */
41196 +       volatile uint32_t dsts;
41197 +       /** Reserved. <i>Offset: 80Ch</i> */
41198 +       uint32_t unused;
41199 +       /** Device IN Endpoint Common Interrupt Mask
41200 +        * Register. <i>Offset: 810h</i> */
41201 +       volatile uint32_t diepmsk;
41202 +       /** Device OUT Endpoint Common Interrupt Mask
41203 +        * Register. <i>Offset: 814h</i> */
41204 +       volatile uint32_t doepmsk;
41205 +       /** Device All Endpoints Interrupt Register.  <i>Offset: 818h</i> */
41206 +       volatile uint32_t daint;
41207 +       /** Device All Endpoints Interrupt Mask Register.  <i>Offset:
41208 +        * 81Ch</i> */
41209 +       volatile uint32_t daintmsk;
41210 +       /** Device IN Token Queue Read Register-1 (Read Only).
41211 +        * <i>Offset: 820h</i> */
41212 +       volatile uint32_t dtknqr1;
41213 +       /** Device IN Token Queue Read Register-2 (Read Only).
41214 +        * <i>Offset: 824h</i> */
41215 +       volatile uint32_t dtknqr2;
41216 +       /** Device VBUS  discharge Register.  <i>Offset: 828h</i> */
41217 +       volatile uint32_t dvbusdis;
41218 +       /** Device VBUS Pulse Register.  <i>Offset: 82Ch</i> */
41219 +       volatile uint32_t dvbuspulse;
41220 +       /** Device IN Token Queue Read Register-3 (Read Only). /
41221 +        *      Device Thresholding control register (Read/Write)
41222 +        * <i>Offset: 830h</i> */
41223 +       volatile uint32_t dtknqr3_dthrctl;
41224 +       /** Device IN Token Queue Read Register-4 (Read Only). /
41225 +        *      Device IN EPs empty Inr. Mask Register (Read/Write)
41226 +        * <i>Offset: 834h</i> */
41227 +       volatile uint32_t dtknqr4_fifoemptymsk;
41228 +       /** Device Each Endpoint Interrupt Register (Read Only). /
41229 +        * <i>Offset: 838h</i> */
41230 +       volatile uint32_t deachint;
41231 +       /** Device Each Endpoint Interrupt mask Register (Read/Write). /
41232 +        * <i>Offset: 83Ch</i> */
41233 +       volatile uint32_t deachintmsk;
41234 +       /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
41235 +        * <i>Offset: 840h</i> */
41236 +       volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
41237 +       /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
41238 +        * <i>Offset: 880h</i> */
41239 +       volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
41240 +} dwc_otg_device_global_regs_t;
41241 +
41242 +/**
41243 + * This union represents the bit fields in the Device Configuration
41244 + * Register.  Read the register into the <i>d32</i> member then
41245 + * set/clear the bits using the <i>b</i>it elements.  Write the
41246 + * <i>d32</i> member to the dcfg register.
41247 + */
41248 +typedef union dcfg_data {
41249 +       /** raw register data */
41250 +       uint32_t d32;
41251 +       /** register bits */
41252 +       struct {
41253 +               /** Device Speed */
41254 +               unsigned devspd:2;
41255 +               /** Non Zero Length Status OUT Handshake */
41256 +               unsigned nzstsouthshk:1;
41257 +#define DWC_DCFG_SEND_STALL 1
41258 +
41259 +               unsigned reserved3:1;
41260 +               /** Device Addresses */
41261 +               unsigned devaddr:7;
41262 +               /** Periodic Frame Interval */
41263 +               unsigned perfrint:2;
41264 +#define DWC_DCFG_FRAME_INTERVAL_80 0
41265 +#define DWC_DCFG_FRAME_INTERVAL_85 1
41266 +#define DWC_DCFG_FRAME_INTERVAL_90 2
41267 +#define DWC_DCFG_FRAME_INTERVAL_95 3
41268 +
41269 +               unsigned reserved13_17:5;
41270 +               /** In Endpoint Mis-match count */
41271 +               unsigned epmscnt:5;
41272 +               /** Enable Descriptor DMA in Device mode */
41273 +               unsigned descdma:1;
41274 +       } b;
41275 +} dcfg_data_t;
41276 +
41277 +/**
41278 + * This union represents the bit fields in the Device Control
41279 + * Register.  Read the register into the <i>d32</i> member then
41280 + * set/clear the bits using the <i>b</i>it elements.
41281 + */
41282 +typedef union dctl_data {
41283 +       /** raw register data */
41284 +       uint32_t d32;
41285 +       /** register bits */
41286 +       struct {
41287 +               /** Remote Wakeup */
41288 +               unsigned rmtwkupsig:1;
41289 +               /** Soft Disconnect */
41290 +               unsigned sftdiscon:1;
41291 +               /** Global Non-Periodic IN NAK Status */
41292 +               unsigned gnpinnaksts:1;
41293 +               /** Global OUT NAK Status */
41294 +               unsigned goutnaksts:1;
41295 +               /** Test Control */
41296 +               unsigned tstctl:3;
41297 +               /** Set Global Non-Periodic IN NAK */
41298 +               unsigned sgnpinnak:1;
41299 +               /** Clear Global Non-Periodic IN NAK */
41300 +               unsigned cgnpinnak:1;
41301 +               /** Set Global OUT NAK */
41302 +               unsigned sgoutnak:1;
41303 +               /** Clear Global OUT NAK */
41304 +               unsigned cgoutnak:1;
41305 +
41306 +               /** Power-On Programming Done */
41307 +               unsigned pwronprgdone:1;
41308 +               /** Global Continue on BNA */
41309 +               unsigned gcontbna:1;
41310 +               /** Global Multi Count */
41311 +               unsigned gmc:2;
41312 +               /** Ignore Frame Number for ISOC EPs */
41313 +               unsigned ifrmnum:1;
41314 +               /** NAK on Babble */
41315 +               unsigned nakonbble:1;
41316 +
41317 +               unsigned reserved17_31:15;
41318 +       } b;
41319 +} dctl_data_t;
41320 +
41321 +/**
41322 + * This union represents the bit fields in the Device Status
41323 + * Register.  Read the register into the <i>d32</i> member then
41324 + * set/clear the bits using the <i>b</i>it elements.
41325 + */
41326 +typedef union dsts_data {
41327 +       /** raw register data */
41328 +       uint32_t d32;
41329 +       /** register bits */
41330 +       struct {
41331 +               /** Suspend Status */
41332 +               unsigned suspsts:1;
41333 +               /** Enumerated Speed */
41334 +               unsigned enumspd:2;
41335 +#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
41336 +#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
41337 +#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ              2
41338 +#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ             3
41339 +               /** Erratic Error */
41340 +               unsigned errticerr:1;
41341 +               unsigned reserved4_7:4;
41342 +               /** Frame or Microframe Number of the received SOF */
41343 +               unsigned soffn:14;
41344 +               unsigned reserved22_31:10;
41345 +       } b;
41346 +} dsts_data_t;
41347 +
41348 +/**
41349 + * This union represents the bit fields in the Device IN EP Interrupt
41350 + * Register and the Device IN EP Common Mask Register.
41351 + *
41352 + * - Read the register into the <i>d32</i> member then set/clear the
41353 + *      bits using the <i>b</i>it elements.
41354 + */
41355 +typedef union diepint_data {
41356 +       /** raw register data */
41357 +       uint32_t d32;
41358 +       /** register bits */
41359 +       struct {
41360 +               /** Transfer complete mask */
41361 +               unsigned xfercompl:1;
41362 +               /** Endpoint disable mask */
41363 +               unsigned epdisabled:1;
41364 +               /** AHB Error mask */
41365 +               unsigned ahberr:1;
41366 +               /** TimeOUT Handshake mask (non-ISOC EPs) */
41367 +               unsigned timeout:1;
41368 +               /** IN Token received with TxF Empty mask */
41369 +               unsigned intktxfemp:1;
41370 +               /** IN Token Received with EP mismatch mask */
41371 +               unsigned intknepmis:1;
41372 +               /** IN Endpoint HAK Effective mask */
41373 +               unsigned inepnakeff:1;
41374 +               /** IN Endpoint HAK Effective mask */
41375 +               unsigned emptyintr:1;
41376 +
41377 +               unsigned txfifoundrn:1;
41378 +
41379 +               /** BNA Interrupt mask */
41380 +               unsigned bna:1;
41381 +
41382 +               unsigned reserved10_12:3;
41383 +               /** BNA Interrupt mask */
41384 +               unsigned nak:1;
41385 +
41386 +               unsigned reserved14_31:18;
41387 +       } b;
41388 +} diepint_data_t;
41389 +
41390 +/**
41391 + * This union represents the bit fields in the Device IN EP 
41392 + * Common/Dedicated Interrupt Mask Register.
41393 + */
41394 +typedef union diepint_data diepmsk_data_t;
41395 +
41396 +/**
41397 + * This union represents the bit fields in the Device OUT EP Interrupt
41398 + * Registerand Device OUT EP Common Interrupt Mask Register.
41399 + *
41400 + * - Read the register into the <i>d32</i> member then set/clear the
41401 + *      bits using the <i>b</i>it elements.
41402 + */
41403 +typedef union doepint_data {
41404 +       /** raw register data */
41405 +       uint32_t d32;
41406 +       /** register bits */
41407 +       struct {
41408 +               /** Transfer complete */
41409 +               unsigned xfercompl:1;
41410 +               /** Endpoint disable  */
41411 +               unsigned epdisabled:1;
41412 +               /** AHB Error */
41413 +               unsigned ahberr:1;
41414 +               /** Setup Phase Done (contorl EPs) */
41415 +               unsigned setup:1;
41416 +               /** OUT Token Received when Endpoint Disabled */
41417 +               unsigned outtknepdis:1;
41418 +
41419 +               unsigned stsphsercvd:1;
41420 +               /** Back-to-Back SETUP Packets Received */
41421 +               unsigned back2backsetup:1;
41422 +
41423 +               unsigned reserved7:1;
41424 +               /** OUT packet Error */
41425 +               unsigned outpkterr:1;
41426 +               /** BNA Interrupt */
41427 +               unsigned bna:1;
41428 +
41429 +               unsigned reserved10:1;
41430 +               /** Packet Drop Status */
41431 +               unsigned pktdrpsts:1;
41432 +               /** Babble Interrupt */
41433 +               unsigned babble:1;
41434 +               /** NAK Interrupt */
41435 +               unsigned nak:1;
41436 +               /** NYET Interrupt */
41437 +               unsigned nyet:1;
41438 +
41439 +               unsigned reserved15_31:17;
41440 +       } b;
41441 +} doepint_data_t;
41442 +
41443 +/**
41444 + * This union represents the bit fields in the Device OUT EP 
41445 + * Common/Dedicated Interrupt Mask Register.
41446 + */
41447 +typedef union doepint_data doepmsk_data_t;
41448 +
41449 +/**
41450 + * This union represents the bit fields in the Device All EP Interrupt
41451 + * and Mask Registers.
41452 + * - Read the register into the <i>d32</i> member then set/clear the
41453 + *      bits using the <i>b</i>it elements.
41454 + */
41455 +typedef union daint_data {
41456 +       /** raw register data */
41457 +       uint32_t d32;
41458 +       /** register bits */
41459 +       struct {
41460 +               /** IN Endpoint bits */
41461 +               unsigned in:16;
41462 +               /** OUT Endpoint bits */
41463 +               unsigned out:16;
41464 +       } ep;
41465 +       struct {
41466 +               /** IN Endpoint bits */
41467 +               unsigned inep0:1;
41468 +               unsigned inep1:1;
41469 +               unsigned inep2:1;
41470 +               unsigned inep3:1;
41471 +               unsigned inep4:1;
41472 +               unsigned inep5:1;
41473 +               unsigned inep6:1;
41474 +               unsigned inep7:1;
41475 +               unsigned inep8:1;
41476 +               unsigned inep9:1;
41477 +               unsigned inep10:1;
41478 +               unsigned inep11:1;
41479 +               unsigned inep12:1;
41480 +               unsigned inep13:1;
41481 +               unsigned inep14:1;
41482 +               unsigned inep15:1;
41483 +               /** OUT Endpoint bits */
41484 +               unsigned outep0:1;
41485 +               unsigned outep1:1;
41486 +               unsigned outep2:1;
41487 +               unsigned outep3:1;
41488 +               unsigned outep4:1;
41489 +               unsigned outep5:1;
41490 +               unsigned outep6:1;
41491 +               unsigned outep7:1;
41492 +               unsigned outep8:1;
41493 +               unsigned outep9:1;
41494 +               unsigned outep10:1;
41495 +               unsigned outep11:1;
41496 +               unsigned outep12:1;
41497 +               unsigned outep13:1;
41498 +               unsigned outep14:1;
41499 +               unsigned outep15:1;
41500 +       } b;
41501 +} daint_data_t;
41502 +
41503 +/**
41504 + * This union represents the bit fields in the Device IN Token Queue
41505 + * Read Registers.
41506 + * - Read the register into the <i>d32</i> member.
41507 + * - READ-ONLY Register
41508 + */
41509 +typedef union dtknq1_data {
41510 +       /** raw register data */
41511 +       uint32_t d32;
41512 +       /** register bits */
41513 +       struct {
41514 +               /** In Token Queue Write Pointer */
41515 +               unsigned intknwptr:5;
41516 +               /** Reserved */
41517 +               unsigned reserved05_06:2;
41518 +               /** write pointer has wrapped. */
41519 +               unsigned wrap_bit:1;
41520 +               /** EP Numbers of IN Tokens 0 ... 4 */
41521 +               unsigned epnums0_5:24;
41522 +       } b;
41523 +} dtknq1_data_t;
41524 +
41525 +/**
41526 + * This union represents Threshold control Register
41527 + * - Read and write the register into the <i>d32</i> member.
41528 + * - READ-WRITABLE Register
41529 + */
41530 +typedef union dthrctl_data {
41531 +       /** raw register data */
41532 +       uint32_t d32;
41533 +       /** register bits */
41534 +       struct {
41535 +               /** non ISO Tx Thr. Enable */
41536 +               unsigned non_iso_thr_en:1;
41537 +               /** ISO Tx Thr. Enable */
41538 +               unsigned iso_thr_en:1;
41539 +               /** Tx Thr. Length */
41540 +               unsigned tx_thr_len:9;
41541 +               /** AHB Threshold ratio */
41542 +               unsigned ahb_thr_ratio:2;
41543 +               /** Reserved */
41544 +               unsigned reserved13_15:3;
41545 +               /** Rx Thr. Enable */
41546 +               unsigned rx_thr_en:1;
41547 +               /** Rx Thr. Length */
41548 +               unsigned rx_thr_len:9;
41549 +               /** Reserved */
41550 +               unsigned reserved26_31:6;
41551 +       } b;
41552 +} dthrctl_data_t;
41553 +
41554 +/**
41555 + * Device Logical IN Endpoint-Specific Registers. <i>Offsets
41556 + * 900h-AFCh</i>
41557 + *
41558 + * There will be one set of endpoint registers per logical endpoint
41559 + * implemented.
41560 + *
41561 + * <i>These registers are visible only in Device mode and must not be
41562 + * accessed in Host mode, as the results are unknown.</i>
41563 + */
41564 +typedef struct dwc_otg_dev_in_ep_regs {
41565 +       /** Device IN Endpoint Control Register. <i>Offset:900h +
41566 +        * (ep_num * 20h) + 00h</i> */
41567 +       volatile uint32_t diepctl;
41568 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
41569 +       uint32_t reserved04;
41570 +       /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
41571 +        * (ep_num * 20h) + 08h</i> */
41572 +       volatile uint32_t diepint;
41573 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
41574 +       uint32_t reserved0C;
41575 +       /** Device IN Endpoint Transfer Size
41576 +        * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
41577 +       volatile uint32_t dieptsiz;
41578 +       /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
41579 +        * (ep_num * 20h) + 14h</i> */
41580 +       volatile uint32_t diepdma;
41581 +       /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
41582 +        * (ep_num * 20h) + 18h</i> */
41583 +       volatile uint32_t dtxfsts;
41584 +       /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h +
41585 +        * (ep_num * 20h) + 1Ch</i> */
41586 +       volatile uint32_t diepdmab;
41587 +} dwc_otg_dev_in_ep_regs_t;
41588 +
41589 +/**
41590 + * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
41591 + * B00h-CFCh</i>
41592 + *
41593 + * There will be one set of endpoint registers per logical endpoint
41594 + * implemented.
41595 + *
41596 + * <i>These registers are visible only in Device mode and must not be
41597 + * accessed in Host mode, as the results are unknown.</i>
41598 + */
41599 +typedef struct dwc_otg_dev_out_ep_regs {
41600 +       /** Device OUT Endpoint Control Register. <i>Offset:B00h +
41601 +        * (ep_num * 20h) + 00h</i> */
41602 +       volatile uint32_t doepctl;
41603 +       /** Device OUT Endpoint Frame number Register.  <i>Offset:
41604 +        * B00h + (ep_num * 20h) + 04h</i> */
41605 +       volatile uint32_t doepfn;
41606 +       /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
41607 +        * (ep_num * 20h) + 08h</i> */
41608 +       volatile uint32_t doepint;
41609 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
41610 +       uint32_t reserved0C;
41611 +       /** Device OUT Endpoint Transfer Size Register. <i>Offset:
41612 +        * B00h + (ep_num * 20h) + 10h</i> */
41613 +       volatile uint32_t doeptsiz;
41614 +       /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
41615 +        * + (ep_num * 20h) + 14h</i> */
41616 +       volatile uint32_t doepdma;
41617 +       /** Reserved. <i>Offset:B00h +   * (ep_num * 20h) + 18h</i> */
41618 +       uint32_t unused;
41619 +       /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h
41620 +        * + (ep_num * 20h) + 1Ch</i> */
41621 +       uint32_t doepdmab;
41622 +} dwc_otg_dev_out_ep_regs_t;
41623 +
41624 +/**
41625 + * This union represents the bit fields in the Device EP Control
41626 + * Register.  Read the register into the <i>d32</i> member then
41627 + * set/clear the bits using the <i>b</i>it elements.
41628 + */
41629 +typedef union depctl_data {
41630 +       /** raw register data */
41631 +       uint32_t d32;
41632 +       /** register bits */
41633 +       struct {
41634 +               /** Maximum Packet Size 
41635 +                * IN/OUT EPn
41636 +                * IN/OUT EP0 - 2 bits
41637 +                *       2'b00: 64 Bytes
41638 +                *       2'b01: 32
41639 +                *       2'b10: 16
41640 +                *       2'b11: 8 */
41641 +               unsigned mps:11;
41642 +#define DWC_DEP0CTL_MPS_64      0
41643 +#define DWC_DEP0CTL_MPS_32      1
41644 +#define DWC_DEP0CTL_MPS_16      2
41645 +#define DWC_DEP0CTL_MPS_8       3
41646 +
41647 +               /** Next Endpoint 
41648 +                * IN EPn/IN EP0 
41649 +                * OUT EPn/OUT EP0 - reserved */
41650 +               unsigned nextep:4;
41651 +
41652 +               /** USB Active Endpoint */
41653 +               unsigned usbactep:1;
41654 +
41655 +               /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
41656 +                * This field contains the PID of the packet going to
41657 +                * be received or transmitted on this endpoint. The
41658 +                * application should program the PID of the first
41659 +                * packet going to be received or transmitted on this
41660 +                * endpoint , after the endpoint is
41661 +                * activated. Application use the SetD1PID and
41662 +                * SetD0PID fields of this register to program either
41663 +                * D0 or D1 PID.
41664 +                * 
41665 +                * The encoding for this field is
41666 +                *       - 0: D0
41667 +                *       - 1: D1
41668 +                */
41669 +               unsigned dpid:1;
41670 +
41671 +               /** NAK Status */
41672 +               unsigned naksts:1;
41673 +
41674 +               /** Endpoint Type 
41675 +                *      2'b00: Control
41676 +                *      2'b01: Isochronous
41677 +                *      2'b10: Bulk
41678 +                *      2'b11: Interrupt */
41679 +               unsigned eptype:2;
41680 +
41681 +               /** Snoop Mode 
41682 +                * OUT EPn/OUT EP0
41683 +                * IN EPn/IN EP0 - reserved */
41684 +               unsigned snp:1;
41685 +
41686 +               /** Stall Handshake */
41687 +               unsigned stall:1;
41688 +
41689 +               /** Tx Fifo Number 
41690 +                * IN EPn/IN EP0
41691 +                * OUT EPn/OUT EP0 - reserved */
41692 +               unsigned txfnum:4;
41693 +
41694 +               /** Clear NAK */
41695 +               unsigned cnak:1;
41696 +               /** Set NAK */
41697 +               unsigned snak:1;
41698 +               /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
41699 +                * Writing to this field sets the Endpoint DPID (DPID)
41700 +                * field in this register to DATA0. Set Even
41701 +                * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
41702 +                * Writing to this field sets the Even/Odd
41703 +                * (micro)frame (EO_FrNum) field to even (micro)
41704 +                * frame.
41705 +                */
41706 +               unsigned setd0pid:1;
41707 +               /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
41708 +                * Writing to this field sets the Endpoint DPID (DPID)
41709 +                * field in this register to DATA1 Set Odd
41710 +                * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
41711 +                * Writing to this field sets the Even/Odd
41712 +                * (micro)frame (EO_FrNum) field to odd (micro) frame.
41713 +                */
41714 +               unsigned setd1pid:1;
41715 +
41716 +               /** Endpoint Disable */
41717 +               unsigned epdis:1;
41718 +               /** Endpoint Enable */
41719 +               unsigned epena:1;
41720 +       } b;
41721 +} depctl_data_t;
41722 +
41723 +/**
41724 + * This union represents the bit fields in the Device EP Transfer
41725 + * Size Register.  Read the register into the <i>d32</i> member then
41726 + * set/clear the bits using the <i>b</i>it elements.
41727 + */
41728 +typedef union deptsiz_data {
41729 +               /** raw register data */
41730 +       uint32_t d32;
41731 +               /** register bits */
41732 +       struct {
41733 +               /** Transfer size */
41734 +               unsigned xfersize:19;
41735 +               /** Packet Count */
41736 +               unsigned pktcnt:10;
41737 +               /** Multi Count - Periodic IN endpoints */
41738 +               unsigned mc:2;
41739 +               unsigned reserved:1;
41740 +       } b;
41741 +} deptsiz_data_t;
41742 +
41743 +/**
41744 + * This union represents the bit fields in the Device EP 0 Transfer
41745 + * Size Register.  Read the register into the <i>d32</i> member then
41746 + * set/clear the bits using the <i>b</i>it elements.
41747 + */
41748 +typedef union deptsiz0_data {
41749 +               /** raw register data */
41750 +       uint32_t d32;
41751 +               /** register bits */
41752 +       struct {
41753 +               /** Transfer size */
41754 +               unsigned xfersize:7;
41755 +                               /** Reserved */
41756 +               unsigned reserved7_18:12;
41757 +               /** Packet Count */
41758 +               unsigned pktcnt:1;
41759 +                               /** Reserved */
41760 +               unsigned reserved20_28:9;
41761 +                               /**Setup Packet Count (DOEPTSIZ0 Only) */
41762 +               unsigned supcnt:2;
41763 +               unsigned reserved31;
41764 +       } b;
41765 +} deptsiz0_data_t;
41766 +
41767 +/////////////////////////////////////////////////
41768 +// DMA Descriptor Specific Structures
41769 +//
41770 +
41771 +/** Buffer status definitions */
41772 +
41773 +#define BS_HOST_READY  0x0
41774 +#define BS_DMA_BUSY            0x1
41775 +#define BS_DMA_DONE            0x2
41776 +#define BS_HOST_BUSY   0x3
41777 +
41778 +/** Receive/Transmit status definitions */
41779 +
41780 +#define RTS_SUCCESS            0x0
41781 +#define RTS_BUFFLUSH   0x1
41782 +#define RTS_RESERVED   0x2
41783 +#define RTS_BUFERR             0x3
41784 +
41785 +/**
41786 + * This union represents the bit fields in the DMA Descriptor
41787 + * status quadlet. Read the quadlet into the <i>d32</i> member then
41788 + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and 
41789 + * <i>b_iso_in</i> elements.
41790 + */
41791 +typedef union dev_dma_desc_sts {
41792 +               /** raw register data */
41793 +       uint32_t d32;
41794 +               /** quadlet bits */
41795 +       struct {
41796 +               /** Received number of bytes */
41797 +               unsigned bytes:16;
41798 +
41799 +               unsigned reserved16_22:7;
41800 +               /** Multiple Transfer - only for OUT EPs */
41801 +               unsigned mtrf:1;
41802 +               /** Setup Packet received - only for OUT EPs */
41803 +               unsigned sr:1;
41804 +               /** Interrupt On Complete */
41805 +               unsigned ioc:1;
41806 +               /** Short Packet */
41807 +               unsigned sp:1;
41808 +               /** Last */
41809 +               unsigned l:1;
41810 +               /** Receive Status */
41811 +               unsigned sts:2;
41812 +               /** Buffer Status */
41813 +               unsigned bs:2;
41814 +       } b;
41815 +
41816 +#ifdef DWC_EN_ISOC
41817 +               /** iso out quadlet bits */
41818 +       struct {
41819 +               /** Received number of bytes */
41820 +               unsigned rxbytes:11;
41821 +
41822 +               unsigned reserved11:1;
41823 +               /** Frame Number */
41824 +               unsigned framenum:11;
41825 +               /** Received ISO Data PID */
41826 +               unsigned pid:2;
41827 +               /** Interrupt On Complete */
41828 +               unsigned ioc:1;
41829 +               /** Short Packet */
41830 +               unsigned sp:1;
41831 +               /** Last */
41832 +               unsigned l:1;
41833 +               /** Receive Status */
41834 +               unsigned rxsts:2;
41835 +               /** Buffer Status */
41836 +               unsigned bs:2;
41837 +       } b_iso_out;
41838 +
41839 +               /** iso in quadlet bits */
41840 +       struct {
41841 +               /** Transmited number of bytes */
41842 +               unsigned txbytes:12;
41843 +               /** Frame Number */
41844 +               unsigned framenum:11;
41845 +               /** Transmited ISO Data PID */
41846 +               unsigned pid:2;
41847 +               /** Interrupt On Complete */
41848 +               unsigned ioc:1;
41849 +               /** Short Packet */
41850 +               unsigned sp:1;
41851 +               /** Last */
41852 +               unsigned l:1;
41853 +               /** Transmit Status */
41854 +               unsigned txsts:2;
41855 +               /** Buffer Status */
41856 +               unsigned bs:2;
41857 +       } b_iso_in;
41858 +#endif                         /* DWC_EN_ISOC */
41859 +} dev_dma_desc_sts_t;
41860 +
41861 +/** 
41862 + * DMA Descriptor structure 
41863 + *
41864 + * DMA Descriptor structure contains two quadlets:
41865 + * Status quadlet and Data buffer pointer.
41866 + */
41867 +typedef struct dwc_otg_dev_dma_desc {
41868 +       /** DMA Descriptor status quadlet */
41869 +       dev_dma_desc_sts_t status;
41870 +       /** DMA Descriptor data buffer pointer */
41871 +       uint32_t buf;
41872 +} dwc_otg_dev_dma_desc_t;
41873 +
41874 +/**
41875 + * The dwc_otg_dev_if structure contains information needed to manage
41876 + * the DWC_otg controller acting in device mode. It represents the
41877 + * programming view of the device-specific aspects of the controller.
41878 + */
41879 +typedef struct dwc_otg_dev_if {
41880 +       /** Pointer to device Global registers.
41881 +        * Device Global Registers starting at offset 800h
41882 +        */
41883 +       dwc_otg_device_global_regs_t *dev_global_regs;
41884 +#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
41885 +
41886 +       /** 
41887 +        * Device Logical IN Endpoint-Specific Registers 900h-AFCh 
41888 +        */
41889 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
41890 +#define DWC_DEV_IN_EP_REG_OFFSET 0x900
41891 +#define DWC_EP_REG_OFFSET 0x20
41892 +
41893 +       /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
41894 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
41895 +#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
41896 +
41897 +       /* Device configuration information */
41898 +       uint8_t speed;                           /**< Device Speed      0: Unknown, 1: LS, 2:FS, 3: HS */
41899 +       uint8_t num_in_eps;              /**< Number # of Tx EP range: 0-15 exept ep0 */
41900 +       uint8_t num_out_eps;             /**< Number # of Rx EP range: 0-15 exept ep 0*/
41901 +
41902 +       /** Size of periodic FIFOs (Bytes) */
41903 +       uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];
41904 +
41905 +       /** Size of Tx FIFOs (Bytes) */
41906 +       uint16_t tx_fifo_size[MAX_TX_FIFOS];
41907 +
41908 +       /** Thresholding enable flags and length varaiables **/
41909 +       uint16_t rx_thr_en;
41910 +       uint16_t iso_tx_thr_en;
41911 +       uint16_t non_iso_tx_thr_en;
41912 +
41913 +       uint16_t rx_thr_length;
41914 +       uint16_t tx_thr_length;
41915 +
41916 +       /**
41917 +        * Pointers to the DMA Descriptors for EP0 Control
41918 +        * transfers (virtual and physical)
41919 +        */
41920 +
41921 +       /** 2 descriptors for SETUP packets */
41922 +       dwc_dma_t dma_setup_desc_addr[2];
41923 +       dwc_otg_dev_dma_desc_t *setup_desc_addr[2];
41924 +
41925 +       /** Pointer to Descriptor with latest SETUP packet */
41926 +       dwc_otg_dev_dma_desc_t *psetup;
41927 +
41928 +       /** Index of current SETUP handler descriptor */
41929 +       uint32_t setup_desc_index;
41930 +
41931 +       /** Descriptor for Data In or Status In phases */
41932 +       dwc_dma_t dma_in_desc_addr;
41933 +       dwc_otg_dev_dma_desc_t *in_desc_addr;
41934 +
41935 +       /** Descriptor for Data Out or Status Out phases */
41936 +       dwc_dma_t dma_out_desc_addr;
41937 +       dwc_otg_dev_dma_desc_t *out_desc_addr;
41938 +
41939 +       /** Setup Packet Detected - if set clear NAK when queueing */
41940 +       uint32_t spd;
41941 +
41942 +} dwc_otg_dev_if_t;
41943 +
41944 +/////////////////////////////////////////////////
41945 +// Host Mode Register Structures
41946 +//
41947 +/**
41948 + * The Host Global Registers structure defines the size and relative
41949 + * field offsets for the Host Mode Global Registers.  Host Global
41950 + * Registers offsets 400h-7FFh.
41951 +*/
41952 +typedef struct dwc_otg_host_global_regs {
41953 +       /** Host Configuration Register.   <i>Offset: 400h</i> */
41954 +       volatile uint32_t hcfg;
41955 +       /** Host Frame Interval Register.       <i>Offset: 404h</i> */
41956 +       volatile uint32_t hfir;
41957 +       /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
41958 +       volatile uint32_t hfnum;
41959 +       /** Reserved.   <i>Offset: 40Ch</i> */
41960 +       uint32_t reserved40C;
41961 +       /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
41962 +       volatile uint32_t hptxsts;
41963 +       /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
41964 +       volatile uint32_t haint;
41965 +       /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
41966 +       volatile uint32_t haintmsk;
41967 +       /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
41968 +       volatile uint32_t hflbaddr;
41969 +} dwc_otg_host_global_regs_t;
41970 +
41971 +
41972 +/**
41973 + * This union represents the bit fields in the Host Configuration Register.
41974 + * Read the register into the <i>d32</i> member then set/clear the bits using
41975 + * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
41976 + */
41977 +typedef union hcfg_data
41978 +{
41979 +       /** raw register data */
41980 +       uint32_t d32;
41981 +
41982 +       /** register bits */
41983 +       struct 
41984 +       {
41985 +               /** FS/LS Phy Clock Select */
41986 +               unsigned fslspclksel:2;
41987 +#define DWC_HCFG_30_60_MHZ 0
41988 +#define DWC_HCFG_48_MHZ           1
41989 +#define DWC_HCFG_6_MHZ    2
41990 +
41991 +               /** FS/LS Only Support */
41992 +               unsigned fslssupp:1;
41993 +               unsigned reserved3_22 : 20;
41994 +               /** Enable Scatter/gather DMA in Host mode */
41995 +               unsigned descdma : 1;
41996 +               /** Frame List Entries */
41997 +               unsigned frlisten: 2;
41998 +               /** Enable Periodic Scheduling */
41999 +               unsigned perschedena: 1;
42000 +               /** Periodic Scheduling Enabled Status */
42001 +               unsigned perschedstat: 1;
42002 +       } b;
42003 +} hcfg_data_t;
42004 +
42005 +/**
42006 + * This union represents the bit fields in the Host Frame Remaing/Number
42007 + * Register.  
42008 + */
42009 +typedef union hfir_data {
42010 +       /** raw register data */
42011 +       uint32_t d32;
42012 +
42013 +       /** register bits */
42014 +       struct {
42015 +               unsigned frint:16;
42016 +               unsigned reserved:16;
42017 +       } b;
42018 +} hfir_data_t;
42019 +
42020 +/**
42021 + * This union represents the bit fields in the Host Frame Remaing/Number
42022 + * Register.  
42023 + */
42024 +typedef union hfnum_data {
42025 +       /** raw register data */
42026 +       uint32_t d32;
42027 +
42028 +       /** register bits */
42029 +       struct {
42030 +               unsigned frnum:16;
42031 +#define DWC_HFNUM_MAX_FRNUM 0x3FFF
42032 +               unsigned frrem:16;
42033 +       } b;
42034 +} hfnum_data_t;
42035 +
42036 +typedef union hptxsts_data {
42037 +       /** raw register data */
42038 +       uint32_t d32;
42039 +
42040 +       /** register bits */
42041 +       struct {
42042 +               unsigned ptxfspcavail:16;
42043 +               unsigned ptxqspcavail:8;
42044 +               /** Top of the Periodic Transmit Request Queue
42045 +                *      - bit 24 - Terminate (last entry for the selected channel)
42046 +                *      - bits 26:25 - Token Type
42047 +                *        - 2'b00 - Zero length
42048 +                *        - 2'b01 - Ping
42049 +                *        - 2'b10 - Disable
42050 +                *      - bits 30:27 - Channel Number
42051 +                *      - bit 31 - Odd/even microframe
42052 +                */
42053 +               unsigned ptxqtop_terminate:1;
42054 +               unsigned ptxqtop_token:2;
42055 +               unsigned ptxqtop_chnum:4;
42056 +               unsigned ptxqtop_odd:1;
42057 +       } b;
42058 +} hptxsts_data_t;
42059 +
42060 +/**
42061 + * This union represents the bit fields in the Host Port Control and Status
42062 + * Register. Read the register into the <i>d32</i> member then set/clear the
42063 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
42064 + * hprt0 register.
42065 + */
42066 +typedef union hprt0_data {
42067 +       /** raw register data */
42068 +       uint32_t d32;
42069 +       /** register bits */
42070 +       struct {
42071 +               unsigned prtconnsts:1;
42072 +               unsigned prtconndet:1;
42073 +               unsigned prtena:1;
42074 +               unsigned prtenchng:1;
42075 +               unsigned prtovrcurract:1;
42076 +               unsigned prtovrcurrchng:1;
42077 +               unsigned prtres:1;
42078 +               unsigned prtsusp:1;
42079 +               unsigned prtrst:1;
42080 +               unsigned reserved9:1;
42081 +               unsigned prtlnsts:2;
42082 +               unsigned prtpwr:1;
42083 +               unsigned prttstctl:4;
42084 +               unsigned prtspd:2;
42085 +#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
42086 +#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
42087 +#define DWC_HPRT0_PRTSPD_LOW_SPEED     2
42088 +               unsigned reserved19_31:13;
42089 +       } b;
42090 +} hprt0_data_t;
42091 +
42092 +/**
42093 + * This union represents the bit fields in the Host All Interrupt 
42094 + * Register.  
42095 + */
42096 +typedef union haint_data {
42097 +       /** raw register data */
42098 +       uint32_t d32;
42099 +       /** register bits */
42100 +       struct {
42101 +               unsigned ch0:1;
42102 +               unsigned ch1:1;
42103 +               unsigned ch2:1;
42104 +               unsigned ch3:1;
42105 +               unsigned ch4:1;
42106 +               unsigned ch5:1;
42107 +               unsigned ch6:1;
42108 +               unsigned ch7:1;
42109 +               unsigned ch8:1;
42110 +               unsigned ch9:1;
42111 +               unsigned ch10:1;
42112 +               unsigned ch11:1;
42113 +               unsigned ch12:1;
42114 +               unsigned ch13:1;
42115 +               unsigned ch14:1;
42116 +               unsigned ch15:1;
42117 +               unsigned reserved:16;
42118 +       } b;
42119 +
42120 +       struct {
42121 +               unsigned chint:16;
42122 +               unsigned reserved:16;
42123 +       } b2;
42124 +} haint_data_t;
42125 +
42126 +/**
42127 + * This union represents the bit fields in the Host All Interrupt 
42128 + * Register.  
42129 + */
42130 +typedef union haintmsk_data {
42131 +       /** raw register data */
42132 +       uint32_t d32;
42133 +       /** register bits */
42134 +       struct {
42135 +               unsigned ch0:1;
42136 +               unsigned ch1:1;
42137 +               unsigned ch2:1;
42138 +               unsigned ch3:1;
42139 +               unsigned ch4:1;
42140 +               unsigned ch5:1;
42141 +               unsigned ch6:1;
42142 +               unsigned ch7:1;
42143 +               unsigned ch8:1;
42144 +               unsigned ch9:1;
42145 +               unsigned ch10:1;
42146 +               unsigned ch11:1;
42147 +               unsigned ch12:1;
42148 +               unsigned ch13:1;
42149 +               unsigned ch14:1;
42150 +               unsigned ch15:1;
42151 +               unsigned reserved:16;
42152 +       } b;
42153 +
42154 +       struct {
42155 +               unsigned chint:16;
42156 +               unsigned reserved:16;
42157 +       } b2;
42158 +} haintmsk_data_t;
42159 +
42160 +/** 
42161 + * Host Channel Specific Registers. <i>500h-5FCh</i>
42162 + */
42163 +typedef struct dwc_otg_hc_regs 
42164 +{
42165 +       /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
42166 +       volatile uint32_t hcchar;
42167 +       /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
42168 +       volatile uint32_t hcsplt;
42169 +       /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
42170 +       volatile uint32_t hcint;
42171 +       /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
42172 +       volatile uint32_t hcintmsk;
42173 +       /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
42174 +       volatile uint32_t hctsiz;
42175 +       /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
42176 +       volatile uint32_t hcdma;
42177 +       volatile uint32_t reserved;
42178 +       /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
42179 +       volatile uint32_t hcdmab;
42180 +} dwc_otg_hc_regs_t;
42181 +
42182 +/**
42183 + * This union represents the bit fields in the Host Channel Characteristics
42184 + * Register. Read the register into the <i>d32</i> member then set/clear the
42185 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
42186 + * hcchar register.
42187 + */
42188 +typedef union hcchar_data {
42189 +       /** raw register data */
42190 +       uint32_t d32;
42191 +
42192 +       /** register bits */
42193 +       struct {
42194 +               /** Maximum packet size in bytes */
42195 +               unsigned mps:11;
42196 +
42197 +               /** Endpoint number */
42198 +               unsigned epnum:4;
42199 +
42200 +               /** 0: OUT, 1: IN */
42201 +               unsigned epdir:1;
42202 +
42203 +               unsigned reserved:1;
42204 +
42205 +               /** 0: Full/high speed device, 1: Low speed device */
42206 +               unsigned lspddev:1;
42207 +
42208 +               /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
42209 +               unsigned eptype:2;
42210 +
42211 +               /** Packets per frame for periodic transfers. 0 is reserved. */
42212 +               unsigned multicnt:2;
42213 +
42214 +               /** Device address */
42215 +               unsigned devaddr:7;
42216 +
42217 +               /**
42218 +                * Frame to transmit periodic transaction.
42219 +                * 0: even, 1: odd
42220 +                */
42221 +               unsigned oddfrm:1;
42222 +
42223 +               /** Channel disable */
42224 +               unsigned chdis:1;
42225 +
42226 +               /** Channel enable */
42227 +               unsigned chen:1;
42228 +       } b;
42229 +} hcchar_data_t;
42230 +
42231 +typedef union hcsplt_data {
42232 +       /** raw register data */
42233 +       uint32_t d32;
42234 +
42235 +       /** register bits */
42236 +       struct {
42237 +               /** Port Address */
42238 +               unsigned prtaddr:7;
42239 +
42240 +               /** Hub Address */
42241 +               unsigned hubaddr:7;
42242 +
42243 +               /** Transaction Position */
42244 +               unsigned xactpos:2;
42245 +#define DWC_HCSPLIT_XACTPOS_MID 0
42246 +#define DWC_HCSPLIT_XACTPOS_END 1
42247 +#define DWC_HCSPLIT_XACTPOS_BEGIN 2
42248 +#define DWC_HCSPLIT_XACTPOS_ALL 3
42249 +
42250 +               /** Do Complete Split */
42251 +               unsigned compsplt:1;
42252 +
42253 +               /** Reserved */
42254 +               unsigned reserved:14;
42255 +
42256 +               /** Split Enble */
42257 +               unsigned spltena:1;
42258 +       } b;
42259 +} hcsplt_data_t;
42260 +
42261 +/**
42262 + * This union represents the bit fields in the Host All Interrupt 
42263 + * Register.  
42264 + */
42265 +typedef union hcint_data
42266 +{
42267 +       /** raw register data */
42268 +       uint32_t d32;
42269 +       /** register bits */
42270 +       struct 
42271 +       {
42272 +               /** Transfer Complete */
42273 +               unsigned xfercomp:1;
42274 +               /** Channel Halted */
42275 +               unsigned chhltd:1;
42276 +               /** AHB Error */
42277 +               unsigned ahberr:1;
42278 +               /** STALL Response Received */
42279 +               unsigned stall:1;
42280 +               /** NAK Response Received */
42281 +               unsigned nak:1;
42282 +               /** ACK Response Received */
42283 +               unsigned ack:1;
42284 +               /** NYET Response Received */
42285 +               unsigned nyet:1;
42286 +               /** Transaction Err */
42287 +               unsigned xacterr:1;
42288 +               /** Babble Error */
42289 +               unsigned bblerr:1;
42290 +               /** Frame Overrun */
42291 +               unsigned frmovrun:1;
42292 +               /** Data Toggle Error */
42293 +               unsigned datatglerr:1;
42294 +               /** Buffer Not Available (only for DDMA mode) */
42295 +               unsigned bna : 1;
42296 +               /** Exessive transaction error (only for DDMA mode) */
42297 +               unsigned xcs_xact : 1;
42298 +               /** Frame List Rollover interrupt */
42299 +               unsigned frm_list_roll : 1;
42300 +               /** Reserved */
42301 +               unsigned reserved14_31 : 18;
42302 +       } b;
42303 +} hcint_data_t;
42304 +
42305 +/**
42306 + * This union represents the bit fields in the Host Channel Interrupt Mask
42307 + * Register. Read the register into the <i>d32</i> member then set/clear the
42308 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
42309 + * hcintmsk register.
42310 + */
42311 +typedef union hcintmsk_data
42312 +{
42313 +       /** raw register data */
42314 +       uint32_t d32;
42315 +
42316 +       /** register bits */
42317 +       struct 
42318 +       {
42319 +               unsigned xfercompl : 1;
42320 +               unsigned chhltd : 1;
42321 +               unsigned ahberr : 1;
42322 +               unsigned stall : 1;
42323 +               unsigned nak : 1;
42324 +               unsigned ack : 1;
42325 +               unsigned nyet : 1;
42326 +               unsigned xacterr : 1;
42327 +               unsigned bblerr : 1;
42328 +               unsigned frmovrun : 1;
42329 +               unsigned datatglerr : 1;
42330 +               unsigned bna : 1;
42331 +               unsigned xcs_xact : 1;
42332 +               unsigned frm_list_roll : 1;
42333 +               unsigned reserved14_31 : 18;
42334 +       } b;
42335 +} hcintmsk_data_t;
42336 +
42337 +/**
42338 + * This union represents the bit fields in the Host Channel Transfer Size
42339 + * Register. Read the register into the <i>d32</i> member then set/clear the
42340 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
42341 + * hcchar register.
42342 + */
42343 +
42344 +typedef union hctsiz_data
42345 +{
42346 +       /** raw register data */
42347 +       uint32_t d32;
42348 +
42349 +       /** register bits */
42350 +       struct 
42351 +       {
42352 +               /** Total transfer size in bytes */
42353 +               unsigned xfersize:19;
42354 +
42355 +               /** Data packets to transfer */
42356 +               unsigned pktcnt:10;
42357 +
42358 +               /**
42359 +                * Packet ID for next data packet
42360 +                * 0: DATA0
42361 +                * 1: DATA2
42362 +                * 2: DATA1
42363 +                * 3: MDATA (non-Control), SETUP (Control)
42364 +                */
42365 +               unsigned pid:2;
42366 +#define DWC_HCTSIZ_DATA0 0
42367 +#define DWC_HCTSIZ_DATA1 2
42368 +#define DWC_HCTSIZ_DATA2 1
42369 +#define DWC_HCTSIZ_MDATA 3
42370 +#define DWC_HCTSIZ_SETUP 3
42371 +
42372 +               /** Do PING protocol when 1 */
42373 +               unsigned dopng:1;
42374 +       } b;
42375 +       
42376 +       /** register bits */
42377 +       struct 
42378 +       {
42379 +               /** Scheduling information */
42380 +               unsigned schinfo : 8;
42381 +               
42382 +               /** Number of transfer descriptors. 
42383 +                * Max value:
42384 +                * 64 in general, 
42385 +                * 256 only for HS isochronous endpoint.
42386 +                */
42387 +               unsigned ntd : 8;
42388 +
42389 +               /** Data packets to transfer */
42390 +               unsigned reserved16_28 : 13;
42391 +
42392 +               /**
42393 +                * Packet ID for next data packet
42394 +                * 0: DATA0
42395 +                * 1: DATA2
42396 +                * 2: DATA1
42397 +                * 3: MDATA (non-Control)
42398 +                */
42399 +               unsigned pid : 2;
42400 +
42401 +               /** Do PING protocol when 1 */
42402 +               unsigned dopng : 1;
42403 +       } b_ddma;
42404 +} hctsiz_data_t;
42405 +
42406 +
42407 +/**
42408 + * This union represents the bit fields in the Host DMA Address  
42409 + * Register used in Descriptor DMA mode.
42410 + */
42411 +typedef union hcdma_data
42412 +{
42413 +       /** raw register data */
42414 +       uint32_t d32;
42415 +       /** register bits */
42416 +       struct 
42417 +       {
42418 +               unsigned reserved0_2 : 3;
42419 +               /** Current Transfer Descriptor. Not used for ISOC */
42420 +               unsigned ctd : 8;
42421 +               /** Start Address of Descriptor List */
42422 +               unsigned dma_addr : 21;
42423 +       } b;
42424 +} hcdma_data_t;
42425 +
42426 +/**
42427 + * This union represents the bit fields in the DMA Descriptor
42428 + * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
42429 + * set/clear the bits using the <i>b</i>it elements.
42430 + */
42431 +typedef union host_dma_desc_sts
42432 +{
42433 +       /** raw register data */
42434 +       uint32_t d32;
42435 +       /** quadlet bits */
42436 +
42437 +       /* for non-isochronous  */
42438 +       struct {
42439 +               /** Number of bytes */
42440 +               unsigned n_bytes : 17;
42441 +               /** QTD offset to jump when Short Packet received - only for IN EPs */
42442 +               unsigned qtd_offset : 6;
42443 +               /** 
42444 +                * Set to request the core to jump to alternate QTD if 
42445 +                * Short Packet received - only for IN EPs 
42446 +                */
42447 +               unsigned a_qtd : 1;
42448 +                /** 
42449 +                 * Setup Packet bit. When set indicates that buffer contains
42450 +                 * setup packet. 
42451 +                 */
42452 +               unsigned sup : 1;
42453 +               /** Interrupt On Complete */
42454 +               unsigned ioc : 1;
42455 +               /** End of List */
42456 +               unsigned eol : 1;
42457 +               unsigned reserved27 : 1;
42458 +               /** Rx/Tx Status */
42459 +               unsigned sts : 2;
42460 +       #define DMA_DESC_STS_PKTERR     1
42461 +               unsigned reserved30 : 1;
42462 +               /** Active Bit */
42463 +               unsigned a : 1;
42464 +       } b;
42465 +       /* for isochronous */
42466 +       struct {
42467 +               /** Number of bytes */
42468 +               unsigned n_bytes : 12;
42469 +               unsigned reserved12_24 : 13;
42470 +               /** Interrupt On Complete */
42471 +               unsigned ioc : 1;
42472 +               unsigned reserved26_27 : 2;
42473 +               /** Rx/Tx Status */
42474 +               unsigned sts : 2;
42475 +               unsigned reserved30 : 1;
42476 +               /** Active Bit */
42477 +               unsigned a : 1;
42478 +       } b_isoc;
42479 +} host_dma_desc_sts_t;
42480 +
42481 +#define        MAX_DMA_DESC_SIZE               131071
42482 +#define MAX_DMA_DESC_NUM_GENERIC       64
42483 +#define MAX_DMA_DESC_NUM_HS_ISOC       256
42484 +#define MAX_FRLIST_EN_NUM              64
42485 +/** 
42486 + * Host-mode DMA Descriptor structure 
42487 + *
42488 + * DMA Descriptor structure contains two quadlets:
42489 + * Status quadlet and Data buffer pointer.
42490 + */
42491 +typedef struct dwc_otg_host_dma_desc
42492 +{
42493 +       /** DMA Descriptor status quadlet */
42494 +       host_dma_desc_sts_t     status;
42495 +       /** DMA Descriptor data buffer pointer */
42496 +       uint32_t        buf;
42497 +} dwc_otg_host_dma_desc_t;
42498 +
42499 +/** OTG Host Interface Structure.
42500 + *
42501 + * The OTG Host Interface Structure structure contains information
42502 + * needed to manage the DWC_otg controller acting in host mode. It
42503 + * represents the programming view of the host-specific aspects of the
42504 + * controller.
42505 + */
42506 +typedef struct dwc_otg_host_if {
42507 +       /** Host Global Registers starting at offset 400h.*/
42508 +       dwc_otg_host_global_regs_t *host_global_regs;
42509 +#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
42510 +
42511 +       /** Host Port 0 Control and Status Register */
42512 +       volatile uint32_t *hprt0;
42513 +#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
42514 +
42515 +       /** Host Channel Specific Registers at offsets 500h-5FCh. */
42516 +       dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
42517 +#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
42518 +#define DWC_OTG_CHAN_REGS_OFFSET 0x20
42519 +
42520 +       /* Host configuration information */
42521 +       /** Number of Host Channels (range: 1-16) */
42522 +       uint8_t num_host_channels;
42523 +       /** Periodic EPs supported (0: no, 1: yes) */
42524 +       uint8_t perio_eps_supported;
42525 +       /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
42526 +       uint16_t perio_tx_fifo_size;
42527 +
42528 +} dwc_otg_host_if_t;
42529 +
42530 +/**
42531 + * This union represents the bit fields in the Power and Clock Gating Control
42532 + * Register. Read the register into the <i>d32</i> member then set/clear the
42533 + * bits using the <i>b</i>it elements. 
42534 + */
42535 +typedef union pcgcctl_data {
42536 +       /** raw register data */
42537 +       uint32_t d32;
42538 +
42539 +       /** register bits */
42540 +       struct {
42541 +               /** Stop Pclk */
42542 +               unsigned stoppclk:1;
42543 +               /** Gate Hclk */
42544 +               unsigned gatehclk:1;
42545 +               /** Power Clamp */
42546 +               unsigned pwrclmp:1;
42547 +               /** Reset Power Down Modules */
42548 +               unsigned rstpdwnmodule:1;
42549 +               /** PHY Suspended */
42550 +               unsigned physuspended:1;
42551 +               /** Enable Sleep Clock Gating (Enbl_L1Gating) */
42552 +               unsigned enbl_sleep_gating:1;
42553 +               /** PHY In Sleep (PhySleep) */
42554 +               unsigned phy_in_sleep:1;
42555 +               /** Deep Sleep*/
42556 +               unsigned deep_sleep:1;
42557 +
42558 +               unsigned reserved31_8:24;
42559 +       } b;
42560 +} pcgcctl_data_t;
42561 +
42562 +#endif
42563 --- /dev/null
42564 +++ b/drivers/usb/host/dwc_otg/test/Makefile
42565 @@ -0,0 +1,16 @@
42566 +
42567 +PERL=/usr/bin/perl
42568 +PL_TESTS=test_sysfs.pl test_mod_param.pl
42569 +
42570 +.PHONY : test
42571 +test : perl_tests
42572 +
42573 +perl_tests :
42574 +       @echo
42575 +       @echo Running perl tests
42576 +       @for test in $(PL_TESTS); do \
42577 +         if $(PERL) ./$$test ; then \
42578 +           echo "=======> $$test, PASSED" ; \
42579 +         else echo "=======> $$test, FAILED" ; \
42580 +         fi \
42581 +       done
42582 --- /dev/null
42583 +++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
42584 @@ -0,0 +1,337 @@
42585 +package dwc_otg_test;
42586 +
42587 +use strict;
42588 +use Exporter ();
42589 +
42590 +use vars qw(@ISA @EXPORT
42591 +$sysfsdir $paramdir $errors $params 
42592 +);
42593 +
42594 +@ISA = qw(Exporter);
42595 +
42596 +#
42597 +# Globals
42598 +#
42599 +$sysfsdir = "/sys/devices/lm0";
42600 +$paramdir = "/sys/module/dwc_otg";
42601 +$errors = 0;
42602 +
42603 +$params = [
42604 +          {
42605 +           NAME => "otg_cap",
42606 +           DEFAULT => 0,
42607 +           ENUM => [],
42608 +           LOW => 0,
42609 +           HIGH => 2
42610 +          },
42611 +          {
42612 +           NAME => "dma_enable",
42613 +           DEFAULT => 0,
42614 +           ENUM => [],
42615 +           LOW => 0,
42616 +           HIGH => 1
42617 +          },
42618 +          { 
42619 +           NAME => "dma_burst_size",
42620 +           DEFAULT => 32,
42621 +           ENUM => [1, 4, 8, 16, 32, 64, 128, 256],
42622 +           LOW => 1,
42623 +           HIGH => 256
42624 +          },
42625 +          { 
42626 +           NAME => "host_speed",
42627 +           DEFAULT => 0,
42628 +           ENUM => [],
42629 +           LOW => 0,
42630 +           HIGH => 1
42631 +          },
42632 +          { 
42633 +           NAME => "host_support_fs_ls_low_power",
42634 +           DEFAULT => 0,
42635 +           ENUM => [],
42636 +           LOW => 0,
42637 +           HIGH => 1
42638 +          },
42639 +          { 
42640 +           NAME => "host_ls_low_power_phy_clk",
42641 +           DEFAULT => 0,
42642 +           ENUM => [],
42643 +           LOW => 0,
42644 +           HIGH => 1
42645 +          },
42646 +          { 
42647 +           NAME => "dev_speed",
42648 +           DEFAULT => 0,
42649 +           ENUM => [],
42650 +           LOW => 0,
42651 +           HIGH => 1
42652 +          },
42653 +          { 
42654 +           NAME => "enable_dynamic_fifo",
42655 +           DEFAULT => 1,
42656 +           ENUM => [],
42657 +           LOW => 0,
42658 +           HIGH => 1
42659 +          },
42660 +          { 
42661 +           NAME => "data_fifo_size",
42662 +           DEFAULT => 8192,
42663 +           ENUM => [],
42664 +           LOW => 32,
42665 +           HIGH => 32768
42666 +          },
42667 +          { 
42668 +           NAME => "dev_rx_fifo_size",
42669 +           DEFAULT => 1064,
42670 +           ENUM => [],
42671 +           LOW => 16,
42672 +           HIGH => 32768
42673 +          },
42674 +          { 
42675 +           NAME => "dev_nperio_tx_fifo_size",
42676 +           DEFAULT => 1024,
42677 +           ENUM => [],
42678 +           LOW => 16,
42679 +           HIGH => 32768
42680 +          },
42681 +          { 
42682 +           NAME => "dev_perio_tx_fifo_size_1",
42683 +           DEFAULT => 256,
42684 +           ENUM => [],
42685 +           LOW => 4,
42686 +           HIGH => 768
42687 +          },
42688 +          { 
42689 +           NAME => "dev_perio_tx_fifo_size_2",
42690 +           DEFAULT => 256,
42691 +           ENUM => [],
42692 +           LOW => 4,
42693 +           HIGH => 768
42694 +          },
42695 +          { 
42696 +           NAME => "dev_perio_tx_fifo_size_3",
42697 +           DEFAULT => 256,
42698 +           ENUM => [],
42699 +           LOW => 4,
42700 +           HIGH => 768
42701 +          },
42702 +          { 
42703 +           NAME => "dev_perio_tx_fifo_size_4",
42704 +           DEFAULT => 256,
42705 +           ENUM => [],
42706 +           LOW => 4,
42707 +           HIGH => 768
42708 +          },
42709 +          { 
42710 +           NAME => "dev_perio_tx_fifo_size_5",
42711 +           DEFAULT => 256,
42712 +           ENUM => [],
42713 +           LOW => 4,
42714 +           HIGH => 768
42715 +          },
42716 +          { 
42717 +           NAME => "dev_perio_tx_fifo_size_6",
42718 +           DEFAULT => 256,
42719 +           ENUM => [],
42720 +           LOW => 4,
42721 +           HIGH => 768
42722 +          },
42723 +          { 
42724 +           NAME => "dev_perio_tx_fifo_size_7",
42725 +           DEFAULT => 256,
42726 +           ENUM => [],
42727 +           LOW => 4,
42728 +           HIGH => 768
42729 +          },
42730 +          { 
42731 +           NAME => "dev_perio_tx_fifo_size_8",
42732 +           DEFAULT => 256,
42733 +           ENUM => [],
42734 +           LOW => 4,
42735 +           HIGH => 768
42736 +          },
42737 +          { 
42738 +           NAME => "dev_perio_tx_fifo_size_9",
42739 +           DEFAULT => 256,
42740 +           ENUM => [],
42741 +           LOW => 4,
42742 +           HIGH => 768
42743 +          },
42744 +          { 
42745 +           NAME => "dev_perio_tx_fifo_size_10",
42746 +           DEFAULT => 256,
42747 +           ENUM => [],
42748 +           LOW => 4,
42749 +           HIGH => 768
42750 +          },
42751 +          { 
42752 +           NAME => "dev_perio_tx_fifo_size_11",
42753 +           DEFAULT => 256,
42754 +           ENUM => [],
42755 +           LOW => 4,
42756 +           HIGH => 768
42757 +          },
42758 +          { 
42759 +           NAME => "dev_perio_tx_fifo_size_12",
42760 +           DEFAULT => 256,
42761 +           ENUM => [],
42762 +           LOW => 4,
42763 +           HIGH => 768
42764 +          },
42765 +          { 
42766 +           NAME => "dev_perio_tx_fifo_size_13",
42767 +           DEFAULT => 256,
42768 +           ENUM => [],
42769 +           LOW => 4,
42770 +           HIGH => 768
42771 +          },
42772 +          { 
42773 +           NAME => "dev_perio_tx_fifo_size_14",
42774 +           DEFAULT => 256,
42775 +           ENUM => [],
42776 +           LOW => 4,
42777 +           HIGH => 768
42778 +          },
42779 +          { 
42780 +           NAME => "dev_perio_tx_fifo_size_15",
42781 +           DEFAULT => 256,
42782 +           ENUM => [],
42783 +           LOW => 4,
42784 +           HIGH => 768
42785 +          },
42786 +          { 
42787 +           NAME => "host_rx_fifo_size",
42788 +           DEFAULT => 1024,
42789 +           ENUM => [],
42790 +           LOW => 16,
42791 +           HIGH => 32768
42792 +          },
42793 +          { 
42794 +           NAME => "host_nperio_tx_fifo_size",
42795 +           DEFAULT => 1024,
42796 +           ENUM => [],
42797 +           LOW => 16,
42798 +           HIGH => 32768
42799 +          },
42800 +          { 
42801 +           NAME => "host_perio_tx_fifo_size",
42802 +           DEFAULT => 1024,
42803 +           ENUM => [],
42804 +           LOW => 16,
42805 +           HIGH => 32768
42806 +          },
42807 +          { 
42808 +           NAME => "max_transfer_size",
42809 +           DEFAULT => 65535,
42810 +           ENUM => [],
42811 +           LOW => 2047,
42812 +           HIGH => 65535
42813 +          },
42814 +          { 
42815 +           NAME => "max_packet_count",
42816 +           DEFAULT => 511,
42817 +           ENUM => [],
42818 +           LOW => 15,
42819 +           HIGH => 511
42820 +          },
42821 +          { 
42822 +           NAME => "host_channels",
42823 +           DEFAULT => 12,
42824 +           ENUM => [],
42825 +           LOW => 1,
42826 +           HIGH => 16
42827 +          },
42828 +          { 
42829 +           NAME => "dev_endpoints",
42830 +           DEFAULT => 6,
42831 +           ENUM => [],
42832 +           LOW => 1,
42833 +           HIGH => 15
42834 +          },
42835 +          { 
42836 +           NAME => "phy_type",
42837 +           DEFAULT => 1,
42838 +           ENUM => [],
42839 +           LOW => 0,
42840 +           HIGH => 2
42841 +          },
42842 +          { 
42843 +           NAME => "phy_utmi_width",
42844 +           DEFAULT => 16,
42845 +           ENUM => [8, 16],
42846 +           LOW => 8,
42847 +           HIGH => 16
42848 +          },
42849 +          { 
42850 +           NAME => "phy_ulpi_ddr",
42851 +           DEFAULT => 0,
42852 +           ENUM => [],
42853 +           LOW => 0,
42854 +           HIGH => 1
42855 +          },
42856 +         ];
42857 +
42858 +
42859 +#
42860 +#
42861 +sub check_arch {
42862 +  $_ = `uname -m`;
42863 +  chomp;
42864 +  unless (m/armv4tl/) {
42865 +    warn "# \n# Can't execute on $_.  Run on integrator platform.\n# \n";
42866 +    return 0;
42867 +  }
42868 +  return 1;
42869 +}
42870 +
42871 +#
42872 +#
42873 +sub load_module {
42874 +  my $params = shift;
42875 +  print "\nRemoving Module\n";
42876 +  system "rmmod dwc_otg";
42877 +  print "Loading Module\n";
42878 +  if ($params ne "") {
42879 +    print "Module Parameters: $params\n";
42880 +  }
42881 +  if (system("modprobe dwc_otg $params")) { 
42882 +    warn "Unable to load module\n";
42883 +    return 0; 
42884 +  }
42885 +  return 1;
42886 +}
42887 +
42888 +#
42889 +#
42890 +sub test_status {
42891 +  my $arg = shift;
42892 +
42893 +  print "\n";
42894 +
42895 +  if (defined $arg) {
42896 +    warn "WARNING: $arg\n";
42897 +  }
42898 +  
42899 +  if ($errors > 0) {
42900 +    warn "TEST FAILED with $errors errors\n";
42901 +    return 0;
42902 +  } else {
42903 +    print "TEST PASSED\n";
42904 +    return 0 if (defined $arg);
42905 +  }
42906 +  return 1;
42907 +}
42908 +
42909 +#
42910 +#
42911 +@EXPORT = qw(
42912 +$sysfsdir
42913 +$paramdir
42914 +$params
42915 +$errors
42916 +check_arch
42917 +load_module
42918 +test_status
42919 +);
42920 +
42921 +1;
42922 --- /dev/null
42923 +++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl
42924 @@ -0,0 +1,133 @@
42925 +#!/usr/bin/perl -w
42926 +# 
42927 +# Run this program on the integrator.
42928 +#
42929 +# - Tests module parameter default values.
42930 +# - Tests setting of valid module parameter values via modprobe.
42931 +# - Tests invalid module parameter values.
42932 +# -----------------------------------------------------------------------------
42933 +use strict;
42934 +use dwc_otg_test;
42935 +
42936 +check_arch() or die;
42937 +
42938 +#
42939 +#
42940 +sub test {
42941 +  my ($param,$expected) = @_;
42942 +  my $value = get($param);
42943 +
42944 +  if ($value == $expected) {
42945 +    print "$param = $value, okay\n";
42946 +  }
42947 +
42948 +  else {
42949 +    warn "ERROR: value of $param != $expected, $value\n";
42950 +    $errors ++;
42951 +  }
42952 +}
42953 +
42954 +#
42955 +#
42956 +sub get {
42957 +  my $param = shift;
42958 +  my $tmp = `cat $paramdir/$param`;
42959 +  chomp $tmp;
42960 +  return $tmp;
42961 +}
42962 +
42963 +#
42964 +#
42965 +sub test_main {
42966 +
42967 +  print "\nTesting Module Parameters\n";
42968 +
42969 +  load_module("") or die;
42970 +
42971 +  # Test initial values
42972 +  print "\nTesting Default Values\n";
42973 +  foreach (@{$params}) {
42974 +    test ($_->{NAME}, $_->{DEFAULT});
42975 +  }
42976 +
42977 +  # Test low value
42978 +  print "\nTesting Low Value\n";
42979 +  my $cmd_params = "";
42980 +  foreach (@{$params}) {
42981 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} ";
42982 +  }
42983 +  load_module($cmd_params) or die;
42984 +
42985 +  foreach (@{$params}) {
42986 +    test ($_->{NAME}, $_->{LOW});
42987 +  }
42988 +
42989 +  # Test high value
42990 +  print "\nTesting High Value\n";
42991 +  $cmd_params = "";
42992 +  foreach (@{$params}) {
42993 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} ";
42994 +  }
42995 +  load_module($cmd_params) or die;
42996 +
42997 +  foreach (@{$params}) {
42998 +    test ($_->{NAME}, $_->{HIGH});
42999 +  }
43000 +
43001 +  # Test Enum
43002 +  print "\nTesting Enumerated\n";
43003 +  foreach (@{$params}) {
43004 +    if (defined $_->{ENUM}) {
43005 +      my $value;
43006 +      foreach $value (@{$_->{ENUM}}) {
43007 +       $cmd_params = "$_->{NAME}=$value";
43008 +       load_module($cmd_params) or die;
43009 +       test ($_->{NAME}, $value);
43010 +      }
43011 +    }
43012 +  }
43013 +
43014 +  # Test Invalid Values
43015 +  print "\nTesting Invalid Values\n";
43016 +  $cmd_params = "";
43017 +  foreach (@{$params}) {
43018 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1;
43019 +  }
43020 +  load_module($cmd_params) or die;
43021 +
43022 +  foreach (@{$params}) {
43023 +    test ($_->{NAME}, $_->{DEFAULT});
43024 +  }
43025 +
43026 +  $cmd_params = "";
43027 +  foreach (@{$params}) {
43028 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1;
43029 +  }
43030 +  load_module($cmd_params) or die;
43031 +
43032 +  foreach (@{$params}) {
43033 +    test ($_->{NAME}, $_->{DEFAULT});
43034 +  }
43035 +
43036 +  print "\nTesting Enumerated\n";
43037 +  foreach (@{$params}) {
43038 +    if (defined $_->{ENUM}) {
43039 +      my $value;
43040 +      foreach $value (@{$_->{ENUM}}) {
43041 +       $value = $value + 1;
43042 +       $cmd_params = "$_->{NAME}=$value";
43043 +       load_module($cmd_params) or die;
43044 +       test ($_->{NAME}, $_->{DEFAULT});
43045 +       $value = $value - 2;
43046 +       $cmd_params = "$_->{NAME}=$value";
43047 +       load_module($cmd_params) or die;
43048 +       test ($_->{NAME}, $_->{DEFAULT});
43049 +      }
43050 +    }
43051 +  }
43052 +
43053 +  test_status() or die;
43054 +}
43055 +
43056 +test_main();
43057 +0;
43058 --- /dev/null
43059 +++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl
43060 @@ -0,0 +1,193 @@
43061 +#!/usr/bin/perl -w
43062 +# 
43063 +# Run this program on the integrator
43064 +# - Tests select sysfs attributes.
43065 +# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc.
43066 +# -----------------------------------------------------------------------------
43067 +use strict;
43068 +use dwc_otg_test;
43069 +
43070 +check_arch() or die;
43071 +
43072 +#
43073 +#
43074 +sub test {
43075 +  my ($attr,$expected) = @_;
43076 +  my $string = get($attr);
43077 +
43078 +  if ($string eq $expected) {
43079 +    printf("$attr = $string, okay\n");
43080 +  }
43081 +  else {
43082 +    warn "ERROR: value of $attr != $expected, $string\n";
43083 +    $errors ++;
43084 +  }
43085 +}
43086 +
43087 +#
43088 +#
43089 +sub set {
43090 +  my ($reg, $value) = @_;
43091 +  system "echo $value > $sysfsdir/$reg";
43092 +}
43093 +
43094 +#
43095 +#
43096 +sub get {
43097 +  my $attr = shift;
43098 +  my $string = `cat $sysfsdir/$attr`;
43099 +  chomp $string;
43100 +  if ($string =~ m/\s\=\s/) {
43101 +    my $tmp;
43102 +    ($tmp, $string) = split /\s=\s/, $string;
43103 +  }
43104 +  return $string;
43105 +}
43106 +
43107 +#
43108 +#
43109 +sub test_main {
43110 +  print("\nTesting Sysfs Attributes\n");
43111 +
43112 +  load_module("") or die;
43113 +
43114 +  # Test initial values of regoffset/regvalue/guid/gsnpsid
43115 +  print("\nTesting Default Values\n");
43116 +
43117 +  test("regoffset", "0xffffffff");
43118 +  test("regvalue", "invalid offset");
43119 +  test("guid", "0x12345678");  # this will fail if it has been changed
43120 +  test("gsnpsid", "0x4f54200a");
43121 +
43122 +  # Test operation of regoffset/regvalue
43123 +  print("\nTesting regoffset\n");
43124 +  set('regoffset', '5a5a5a5a');
43125 +  test("regoffset", "0xffffffff");
43126 +
43127 +  set('regoffset', '0');
43128 +  test("regoffset", "0x00000000");
43129 +
43130 +  set('regoffset', '40000');
43131 +  test("regoffset", "0x00000000");
43132 +
43133 +  set('regoffset', '3ffff');
43134 +  test("regoffset", "0x0003ffff");
43135 +
43136 +  set('regoffset', '1');
43137 +  test("regoffset", "0x00000001");
43138 +
43139 +  print("\nTesting regvalue\n");
43140 +  set('regoffset', '3c');
43141 +  test("regvalue", "0x12345678");
43142 +  set('regvalue', '5a5a5a5a');
43143 +  test("regvalue", "0x5a5a5a5a");
43144 +  set('regvalue','a5a5a5a5');
43145 +  test("regvalue", "0xa5a5a5a5");
43146 +  set('guid','12345678');
43147 +
43148 +  # Test HNP Capable
43149 +  print("\nTesting HNP Capable bit\n");
43150 +  set('hnpcapable', '1');
43151 +  test("hnpcapable", "0x1");
43152 +  set('hnpcapable','0');
43153 +  test("hnpcapable", "0x0");
43154 +
43155 +  set('regoffset','0c');
43156 +
43157 +  my $old = get('gusbcfg');
43158 +  print("setting hnpcapable\n");
43159 +  set('hnpcapable', '1');
43160 +  test("hnpcapable", "0x1");
43161 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9)));
43162 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9)));
43163 +
43164 +  $old = get('gusbcfg');
43165 +  print("clearing hnpcapable\n");
43166 +  set('hnpcapable', '0');
43167 +  test("hnpcapable", "0x0");
43168 +  test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9)));
43169 +  test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9)));
43170 +
43171 +  # Test SRP Capable
43172 +  print("\nTesting SRP Capable bit\n");
43173 +  set('srpcapable', '1');
43174 +  test("srpcapable", "0x1");
43175 +  set('srpcapable','0');
43176 +  test("srpcapable", "0x0");
43177 +
43178 +  set('regoffset','0c');
43179 +
43180 +  $old = get('gusbcfg');
43181 +  print("setting srpcapable\n");
43182 +  set('srpcapable', '1');
43183 +  test("srpcapable", "0x1");
43184 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8)));
43185 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8)));
43186 +
43187 +  $old = get('gusbcfg');
43188 +  print("clearing srpcapable\n");
43189 +  set('srpcapable', '0');
43190 +  test("srpcapable", "0x0");
43191 +  test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8)));
43192 +  test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8)));
43193 +
43194 +  # Test GGPIO
43195 +  print("\nTesting GGPIO\n");
43196 +  set('ggpio','5a5a5a5a');
43197 +  test('ggpio','0x5a5a0000');
43198 +  set('ggpio','a5a5a5a5');
43199 +  test('ggpio','0xa5a50000');
43200 +  set('ggpio','11110000');
43201 +  test('ggpio','0x11110000');
43202 +  set('ggpio','00001111');
43203 +  test('ggpio','0x00000000');
43204 +
43205 +  # Test DEVSPEED
43206 +  print("\nTesting DEVSPEED\n");
43207 +  set('regoffset','800');
43208 +  $old = get('regvalue');
43209 +  set('devspeed','0');
43210 +  test('devspeed','0x0');
43211 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
43212 +  set('devspeed','1');
43213 +  test('devspeed','0x1');
43214 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
43215 +  set('devspeed','2');
43216 +  test('devspeed','0x2');
43217 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2));
43218 +  set('devspeed','3');
43219 +  test('devspeed','0x3');
43220 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3));
43221 +  set('devspeed','4');
43222 +  test('devspeed','0x0');
43223 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
43224 +  set('devspeed','5');
43225 +  test('devspeed','0x1');
43226 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
43227 +
43228 +
43229 +  #  mode      Returns the current mode:0 for device mode1 for host mode       Read
43230 +  #  hnp       Initiate the Host Negotiation Protocol.  Read returns the status.       Read/Write
43231 +  #  srp       Initiate the Session Request Protocol.  Read returns the status.        Read/Write
43232 +  #  buspower  Get or Set the Power State of the bus (0 - Off or 1 - On)       Read/Write
43233 +  #  bussuspend        Suspend the USB bus.    Read/Write
43234 +  #  busconnected      Get the connection status of the bus    Read
43235 +
43236 +  #  gotgctl   Get or set the Core Control Status Register.    Read/Write
43237 +  ##  gusbcfg  Get or set the Core USB Configuration Register  Read/Write
43238 +  #  grxfsiz   Get or set the Receive FIFO Size Register       Read/Write
43239 +  #  gnptxfsiz Get or set the non-periodic Transmit Size Register      Read/Write
43240 +  #  gpvndctl  Get or set the PHY Vendor Control Register      Read/Write
43241 +  ##  ggpio    Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write
43242 +  ##  guid     Get or set the value of the User ID Register    Read/Write
43243 +  ##  gsnpsid  Get the value of the Synopsys ID Regester       Read
43244 +  ##  devspeed Get or set the device speed setting in the DCFG register        Read/Write
43245 +  #  enumspeed Gets the device enumeration Speed.      Read
43246 +  #  hptxfsiz  Get the value of the Host Periodic Transmit FIFO        Read
43247 +  #  hprt0     Get or Set the value in the Host Port Control and Status Register       Read/Write
43248 +
43249 +  test_status("TEST NYI") or die;
43250 +}
43251 +
43252 +test_main();
43253 +0;