[lantiq]
[openwrt/svn-archive/archive.git] / target / linux / lantiq / patches-2.6.39 / 550-dwc_otg.patch
1 --- a/drivers/usb/Kconfig
2 +++ b/drivers/usb/Kconfig
3 @@ -114,6 +114,8 @@
4
5 source "drivers/usb/host/Kconfig"
6
7 +source "drivers/usb/dwc_otg/Kconfig"
8 +
9 source "drivers/usb/musb/Kconfig"
10
11 source "drivers/usb/class/Kconfig"
12 --- a/drivers/usb/Makefile
13 +++ b/drivers/usb/Makefile
14 @@ -27,6 +27,8 @@
15
16 obj-$(CONFIG_USB_WUSB) += wusbcore/
17
18 +obj-$(CONFIG_DWC_OTG) += dwc_otg/
19 +
20 obj-$(CONFIG_USB_ACM) += class/
21 obj-$(CONFIG_USB_PRINTER) += class/
22 obj-$(CONFIG_USB_WDM) += class/
23 --- /dev/null
24 +++ b/drivers/usb/dwc_otg/Kconfig
25 @@ -0,0 +1,37 @@
26 +config DWC_OTG
27 + tristate "Synopsis DWC_OTG support"
28 + depends on USB
29 + help
30 + This driver supports Synopsis DWC_OTG IP core
31 + embebbed on many SOCs (ralink, infineon, etc)
32 +
33 +choice
34 + prompt "USB Operation Mode"
35 + depends on DWC_OTG
36 + default DWC_OTG_HOST_ONLY
37 +
38 +config DWC_OTG_HOST_ONLY
39 + bool "HOST ONLY MODE"
40 + depends on DWC_OTG
41 +
42 +#config DWC_OTG_DEVICE_ONLY
43 +# bool "DEVICE ONLY MODE"
44 +# depends on DWC_OTG
45 +endchoice
46 +
47 +choice
48 + prompt "Platform"
49 + depends on DWC_OTG
50 + default DWC_OTG_LANTIQ
51 +
52 +config DWC_OTG_LANTIQ
53 + bool "Lantiq"
54 + depends on LANTIQ
55 + help
56 + Danube USB Host Controller
57 + platform support
58 +endchoice
59 +
60 +config DWC_OTG_DEBUG
61 + bool "Enable debug mode"
62 + depends on DWC_OTG
63 --- /dev/null
64 +++ b/drivers/usb/dwc_otg/Makefile
65 @@ -0,0 +1,39 @@
66 +#
67 +# Makefile for DWC_otg Highspeed USB controller driver
68 +#
69 +
70 +ifeq ($(CONFIG_DWC_OTG_DEBUG),y)
71 +EXTRA_CFLAGS += -DDEBUG
72 +endif
73 +
74 +# Use one of the following flags to compile the software in host-only or
75 +# device-only mode based on the configuration selected by the user
76 +ifeq ($(CONFIG_DWC_OTG_HOST_ONLY),y)
77 + EXTRA_CFLAGS += -DDWC_OTG_HOST_ONLY -DDWC_HOST_ONLY
78 + EXTRA_CFLAGS += -DDWC_OTG_EN_ISOC -DDWC_EN_ISOC
79 +else ifeq ($(CONFIG_DWC_OTG_DEVICE_ONLY),y)
80 + EXTRA_CFLAGS += -DDWC_OTG_DEVICE_ONLY
81 +else
82 + EXTRA_CFLAGS += -DDWC_OTG_MODE
83 +endif
84 +
85 +# EXTRA_CFLAGS += -DDWC_HS_ELECT_TST
86 +# EXTRA_CFLAGS += -DDWC_OTG_EXT_CHG_PUMP
87 +
88 +ifeq ($(CONFIG_DWC_OTG_LANTIQ),y)
89 + EXTRA_CFLAGS += -Dlinux -D__LINUX__ -DDWC_OTG_IFX -DDWC_OTG_HOST_ONLY -DDWC_HOST_ONLY -D__KERNEL__
90 +endif
91 +ifeq ($(CONFIG_DWC_OTG_LANTIQ),m)
92 + EXTRA_CFLAGS += -Dlinux -D__LINUX__ -DDWC_OTG_IFX -DDWC_HOST_ONLY -DMODULE -D__KERNEL__ -DDEBUG
93 +endif
94 +
95 +obj-$(CONFIG_DWC_OTG) := dwc_otg.o
96 +dwc_otg-objs := dwc_otg_hcd.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o
97 +#dwc_otg-objs += dwc_otg_pcd.o dwc_otg_pcd_intr.o
98 +dwc_otg-objs += dwc_otg_attr.o
99 +dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o
100 +dwc_otg-objs += dwc_otg_ifx.o
101 +dwc_otg-objs += dwc_otg_driver.o
102 +
103 +#obj-$(CONFIG_DWC_OTG_IFX) := dwc_otg_ifx.o
104 +#dwc_otg_ifx-objs := dwc_otg_ifx.o
105 --- /dev/null
106 +++ b/drivers/usb/dwc_otg/dwc_otg_attr.c
107 @@ -0,0 +1,802 @@
108 +/* ==========================================================================
109 + * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_attr.c $
110 + * $Revision: 1.1.1.1 $
111 + * $Date: 2009-04-17 06:15:34 $
112 + * $Change: 537387 $
113 + *
114 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
115 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
116 + * otherwise expressly agreed to in writing between Synopsys and you.
117 + *
118 + * The Software IS NOT an item of Licensed Software or Licensed Product under
119 + * any End User Software License Agreement or Agreement for Licensed Product
120 + * with Synopsys or any supplement thereto. You are permitted to use and
121 + * redistribute this Software in source and binary forms, with or without
122 + * modification, provided that redistributions of source code must retain this
123 + * notice. You may not view, use, disclose, copy or distribute this file or
124 + * any information contained herein except pursuant to this license grant from
125 + * Synopsys. If you do not agree with this notice, including the disclaimer
126 + * below, then you are not authorized to use the Software.
127 + *
128 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
129 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
130 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
131 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
132 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
133 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
134 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
135 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
136 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
137 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
138 + * DAMAGE.
139 + * ========================================================================== */
140 +
141 +/** @file
142 + *
143 + * The diagnostic interface will provide access to the controller for
144 + * bringing up the hardware and testing. The Linux driver attributes
145 + * feature will be used to provide the Linux Diagnostic
146 + * Interface. These attributes are accessed through sysfs.
147 + */
148 +
149 +/** @page "Linux Module Attributes"
150 + *
151 + * The Linux module attributes feature is used to provide the Linux
152 + * Diagnostic Interface. These attributes are accessed through sysfs.
153 + * The diagnostic interface will provide access to the controller for
154 + * bringing up the hardware and testing.
155 +
156 +
157 + The following table shows the attributes.
158 + <table>
159 + <tr>
160 + <td><b> Name</b></td>
161 + <td><b> Description</b></td>
162 + <td><b> Access</b></td>
163 + </tr>
164 +
165 + <tr>
166 + <td> mode </td>
167 + <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
168 + <td> Read</td>
169 + </tr>
170 +
171 + <tr>
172 + <td> hnpcapable </td>
173 + <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
174 + Read returns the current value.</td>
175 + <td> Read/Write</td>
176 + </tr>
177 +
178 + <tr>
179 + <td> srpcapable </td>
180 + <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
181 + Read returns the current value.</td>
182 + <td> Read/Write</td>
183 + </tr>
184 +
185 + <tr>
186 + <td> hnp </td>
187 + <td> Initiates the Host Negotiation Protocol. Read returns the status.</td>
188 + <td> Read/Write</td>
189 + </tr>
190 +
191 + <tr>
192 + <td> srp </td>
193 + <td> Initiates the Session Request Protocol. Read returns the status.</td>
194 + <td> Read/Write</td>
195 + </tr>
196 +
197 + <tr>
198 + <td> buspower </td>
199 + <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
200 + <td> Read/Write</td>
201 + </tr>
202 +
203 + <tr>
204 + <td> bussuspend </td>
205 + <td> Suspends the USB bus.</td>
206 + <td> Read/Write</td>
207 + </tr>
208 +
209 + <tr>
210 + <td> busconnected </td>
211 + <td> Gets the connection status of the bus</td>
212 + <td> Read</td>
213 + </tr>
214 +
215 + <tr>
216 + <td> gotgctl </td>
217 + <td> Gets or sets the Core Control Status Register.</td>
218 + <td> Read/Write</td>
219 + </tr>
220 +
221 + <tr>
222 + <td> gusbcfg </td>
223 + <td> Gets or sets the Core USB Configuration Register</td>
224 + <td> Read/Write</td>
225 + </tr>
226 +
227 + <tr>
228 + <td> grxfsiz </td>
229 + <td> Gets or sets the Receive FIFO Size Register</td>
230 + <td> Read/Write</td>
231 + </tr>
232 +
233 + <tr>
234 + <td> gnptxfsiz </td>
235 + <td> Gets or sets the non-periodic Transmit Size Register</td>
236 + <td> Read/Write</td>
237 + </tr>
238 +
239 + <tr>
240 + <td> gpvndctl </td>
241 + <td> Gets or sets the PHY Vendor Control Register</td>
242 + <td> Read/Write</td>
243 + </tr>
244 +
245 + <tr>
246 + <td> ggpio </td>
247 + <td> Gets the value in the lower 16-bits of the General Purpose IO Register
248 + or sets the upper 16 bits.</td>
249 + <td> Read/Write</td>
250 + </tr>
251 +
252 + <tr>
253 + <td> guid </td>
254 + <td> Gets or sets the value of the User ID Register</td>
255 + <td> Read/Write</td>
256 + </tr>
257 +
258 + <tr>
259 + <td> gsnpsid </td>
260 + <td> Gets the value of the Synopsys ID Regester</td>
261 + <td> Read</td>
262 + </tr>
263 +
264 + <tr>
265 + <td> devspeed </td>
266 + <td> Gets or sets the device speed setting in the DCFG register</td>
267 + <td> Read/Write</td>
268 + </tr>
269 +
270 + <tr>
271 + <td> enumspeed </td>
272 + <td> Gets the device enumeration Speed.</td>
273 + <td> Read</td>
274 + </tr>
275 +
276 + <tr>
277 + <td> hptxfsiz </td>
278 + <td> Gets the value of the Host Periodic Transmit FIFO</td>
279 + <td> Read</td>
280 + </tr>
281 +
282 + <tr>
283 + <td> hprt0 </td>
284 + <td> Gets or sets the value in the Host Port Control and Status Register</td>
285 + <td> Read/Write</td>
286 + </tr>
287 +
288 + <tr>
289 + <td> regoffset </td>
290 + <td> Sets the register offset for the next Register Access</td>
291 + <td> Read/Write</td>
292 + </tr>
293 +
294 + <tr>
295 + <td> regvalue </td>
296 + <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
297 + <td> Read/Write</td>
298 + </tr>
299 +
300 + <tr>
301 + <td> remote_wakeup </td>
302 + <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
303 + wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
304 + Wakeup signalling bit in the Device Control Register is set for 1
305 + milli-second.</td>
306 + <td> Read/Write</td>
307 + </tr>
308 +
309 + <tr>
310 + <td> regdump </td>
311 + <td> Dumps the contents of core registers.</td>
312 + <td> Read</td>
313 + </tr>
314 +
315 + <tr>
316 + <td> hcddump </td>
317 + <td> Dumps the current HCD state.</td>
318 + <td> Read</td>
319 + </tr>
320 +
321 + <tr>
322 + <td> hcd_frrem </td>
323 + <td> Shows the average value of the Frame Remaining
324 + field in the Host Frame Number/Frame Remaining register when an SOF interrupt
325 + occurs. This can be used to determine the average interrupt latency. Also
326 + shows the average Frame Remaining value for start_transfer and the "a" and
327 + "b" sample points. The "a" and "b" sample points may be used during debugging
328 + bto determine how long it takes to execute a section of the HCD code.</td>
329 + <td> Read</td>
330 + </tr>
331 +
332 + <tr>
333 + <td> rd_reg_test </td>
334 + <td> Displays the time required to read the GNPTXFSIZ register many times
335 + (the output shows the number of times the register is read).
336 + <td> Read</td>
337 + </tr>
338 +
339 + <tr>
340 + <td> wr_reg_test </td>
341 + <td> Displays the time required to write the GNPTXFSIZ register many times
342 + (the output shows the number of times the register is written).
343 + <td> Read</td>
344 + </tr>
345 +
346 + </table>
347 +
348 + Example usage:
349 + To get the current mode:
350 + cat /sys/devices/lm0/mode
351 +
352 + To power down the USB:
353 + echo 0 > /sys/devices/lm0/buspower
354 + */
355 +#include <linux/kernel.h>
356 +#include <linux/module.h>
357 +#include <linux/moduleparam.h>
358 +#include <linux/init.h>
359 +#include <linux/device.h>
360 +#include <linux/errno.h>
361 +#include <linux/types.h>
362 +#include <linux/stat.h> /* permission constants */
363 +
364 +#include <asm/io.h>
365 +
366 +#include "dwc_otg_plat.h"
367 +#include "dwc_otg_attr.h"
368 +#include "dwc_otg_driver.h"
369 +// #include "dwc_otg_pcd.h"
370 +#include "dwc_otg_hcd.h"
371 +
372 +// 20070316, winder added.
373 +#ifndef SZ_256K
374 +#define SZ_256K 0x00040000
375 +#endif
376 +
377 +/*
378 + * MACROs for defining sysfs attribute
379 + */
380 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
381 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
382 +{ \
383 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
384 + uint32_t val; \
385 + val = dwc_read_reg32 (_addr_); \
386 + val = (val & (_mask_)) >> _shift_; \
387 + return sprintf (buf, "%s = 0x%x\n", _string_, val); \
388 +}
389 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
390 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, const char *buf, size_t count) \
391 +{ \
392 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
393 + uint32_t set = simple_strtoul(buf, NULL, 16); \
394 + uint32_t clear = set; \
395 + clear = ((~clear) << _shift_) & _mask_; \
396 + set = (set << _shift_) & _mask_; \
397 + dev_dbg(_dev, "Storing Address=0x%08x Set=0x%08x Clear=0x%08x\n", (uint32_t)_addr_, set, clear); \
398 + dwc_modify_reg32(_addr_, clear, set); \
399 + return count; \
400 +}
401 +
402 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
403 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
404 +DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
405 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
406 +
407 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
408 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
409 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
410 +
411 +/*
412 + * MACROs for defining sysfs attribute for 32-bit registers
413 + */
414 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
415 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
416 +{ \
417 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
418 + uint32_t val; \
419 + val = dwc_read_reg32 (_addr_); \
420 + return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
421 +}
422 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_addr_,_string_) \
423 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, const char *buf, size_t count) \
424 +{ \
425 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
426 + uint32_t val = simple_strtoul(buf, NULL, 16); \
427 + dev_dbg(_dev, "Storing Address=0x%08x Val=0x%08x\n", (uint32_t)_addr_, val); \
428 + dwc_write_reg32(_addr_, val); \
429 + return count; \
430 +}
431 +
432 +#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
433 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
434 +DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_addr_,_string_) \
435 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
436 +
437 +#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
438 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
439 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
440 +
441 +
442 +/** @name Functions for Show/Store of Attributes */
443 +/**@{*/
444 +
445 +/**
446 + * Show the register offset of the Register Access.
447 + */
448 +static ssize_t regoffset_show( struct device *_dev, struct device_attribute *attr, char *buf)
449 +{
450 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
451 + return snprintf(buf, sizeof("0xFFFFFFFF\n")+1,"0x%08x\n", otg_dev->reg_offset);
452 +}
453 +
454 +/**
455 + * Set the register offset for the next Register Access Read/Write
456 + */
457 +static ssize_t regoffset_store( struct device *_dev, struct device_attribute *attr, const char *buf,
458 + size_t count )
459 +{
460 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
461 + uint32_t offset = simple_strtoul(buf, NULL, 16);
462 + //dev_dbg(_dev, "Offset=0x%08x\n", offset);
463 + if (offset < SZ_256K ) {
464 + otg_dev->reg_offset = offset;
465 + }
466 + else {
467 + dev_err( _dev, "invalid offset\n" );
468 + }
469 +
470 + return count;
471 +}
472 +DEVICE_ATTR(regoffset, S_IRUGO|S_IWUSR, regoffset_show, regoffset_store);
473 +
474 +/**
475 + * Show the value of the register at the offset in the reg_offset
476 + * attribute.
477 + */
478 +static ssize_t regvalue_show( struct device *_dev, struct device_attribute *attr, char *buf)
479 +{
480 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
481 + uint32_t val;
482 + volatile uint32_t *addr;
483 +
484 + if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) {
485 + /* Calculate the address */
486 + addr = (uint32_t*)(otg_dev->reg_offset +
487 + (uint8_t*)otg_dev->base);
488 + //dev_dbg(_dev, "@0x%08x\n", (unsigned)addr);
489 + val = dwc_read_reg32( addr );
490 + return snprintf(buf, sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n")+1,
491 + "Reg@0x%06x = 0x%08x\n",
492 + otg_dev->reg_offset, val);
493 + }
494 + else {
495 + dev_err(_dev, "Invalid offset (0x%0x)\n",
496 + otg_dev->reg_offset);
497 + return sprintf(buf, "invalid offset\n" );
498 + }
499 +}
500 +
501 +/**
502 + * Store the value in the register at the offset in the reg_offset
503 + * attribute.
504 + *
505 + */
506 +static ssize_t regvalue_store( struct device *_dev, struct device_attribute *attr, const char *buf,
507 + size_t count )
508 +{
509 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
510 + volatile uint32_t * addr;
511 + uint32_t val = simple_strtoul(buf, NULL, 16);
512 + //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
513 + if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) {
514 + /* Calculate the address */
515 + addr = (uint32_t*)(otg_dev->reg_offset +
516 + (uint8_t*)otg_dev->base);
517 + //dev_dbg(_dev, "@0x%08x\n", (unsigned)addr);
518 + dwc_write_reg32( addr, val );
519 + }
520 + else {
521 + dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
522 + otg_dev->reg_offset);
523 + }
524 + return count;
525 +}
526 +DEVICE_ATTR(regvalue, S_IRUGO|S_IWUSR, regvalue_show, regvalue_store);
527 +
528 +/*
529 + * Attributes
530 + */
531 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<20),20,"Mode");
532 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable,&(otg_dev->core_if->core_global_regs->gusbcfg),(1<<9),9,"Mode");
533 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable,&(otg_dev->core_if->core_global_regs->gusbcfg),(1<<8),8,"Mode");
534 +
535 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
536 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
537 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected,otg_dev->core_if->host_if->hprt0,0x01,0,"Bus Connected");
538 +
539 +DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl,&(otg_dev->core_if->core_global_regs->gotgctl),"GOTGCTL");
540 +DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,&(otg_dev->core_if->core_global_regs->gusbcfg),"GUSBCFG");
541 +DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,&(otg_dev->core_if->core_global_regs->grxfsiz),"GRXFSIZ");
542 +DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,&(otg_dev->core_if->core_global_regs->gnptxfsiz),"GNPTXFSIZ");
543 +DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,&(otg_dev->core_if->core_global_regs->gpvndctl),"GPVNDCTL");
544 +DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,&(otg_dev->core_if->core_global_regs->ggpio),"GGPIO");
545 +DWC_OTG_DEVICE_ATTR_REG32_RW(guid,&(otg_dev->core_if->core_global_regs->guid),"GUID");
546 +DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,&(otg_dev->core_if->core_global_regs->gsnpsid),"GSNPSID");
547 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed,&(otg_dev->core_if->dev_if->dev_global_regs->dcfg),0x3,0,"Device Speed");
548 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed,&(otg_dev->core_if->dev_if->dev_global_regs->dsts),0x6,1,"Device Enumeration Speed");
549 +
550 +DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,&(otg_dev->core_if->core_global_regs->hptxfsiz),"HPTXFSIZ");
551 +DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0,otg_dev->core_if->host_if->hprt0,"HPRT0");
552 +
553 +
554 +/**
555 + * @todo Add code to initiate the HNP.
556 + */
557 +/**
558 + * Show the HNP status bit
559 + */
560 +static ssize_t hnp_show( struct device *_dev, struct device_attribute *attr, char *buf)
561 +{
562 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
563 + gotgctl_data_t val;
564 + val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl));
565 + return sprintf (buf, "HstNegScs = 0x%x\n", val.b.hstnegscs);
566 +}
567 +
568 +/**
569 + * Set the HNP Request bit
570 + */
571 +static ssize_t hnp_store( struct device *_dev, struct device_attribute *attr, const char *buf,
572 + size_t count )
573 +{
574 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
575 + uint32_t in = simple_strtoul(buf, NULL, 16);
576 + uint32_t *addr = (uint32_t *)&(otg_dev->core_if->core_global_regs->gotgctl);
577 + gotgctl_data_t mem;
578 + mem.d32 = dwc_read_reg32(addr);
579 + mem.b.hnpreq = in;
580 + dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
581 + dwc_write_reg32(addr, mem.d32);
582 + return count;
583 +}
584 +DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
585 +
586 +/**
587 + * @todo Add code to initiate the SRP.
588 + */
589 +/**
590 + * Show the SRP status bit
591 + */
592 +static ssize_t srp_show( struct device *_dev, struct device_attribute *attr, char *buf)
593 +{
594 +#ifndef DWC_HOST_ONLY
595 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
596 + gotgctl_data_t val;
597 + val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl));
598 + return sprintf (buf, "SesReqScs = 0x%x\n", val.b.sesreqscs);
599 +#else
600 + return sprintf(buf, "Host Only Mode!\n");
601 +#endif
602 +}
603 +
604 +/**
605 + * Set the SRP Request bit
606 + */
607 +static ssize_t srp_store( struct device *_dev, struct device_attribute *attr, const char *buf,
608 + size_t count )
609 +{
610 +#ifndef DWC_HOST_ONLY
611 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
612 + dwc_otg_pcd_initiate_srp(otg_dev->pcd);
613 +#endif
614 + return count;
615 +}
616 +DEVICE_ATTR(srp, 0644, srp_show, srp_store);
617 +
618 +/**
619 + * @todo Need to do more for power on/off?
620 + */
621 +/**
622 + * Show the Bus Power status
623 + */
624 +static ssize_t buspower_show( struct device *_dev, struct device_attribute *attr, char *buf)
625 +{
626 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
627 + hprt0_data_t val;
628 + val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0);
629 + return sprintf (buf, "Bus Power = 0x%x\n", val.b.prtpwr);
630 +}
631 +
632 +
633 +/**
634 + * Set the Bus Power status
635 + */
636 +static ssize_t buspower_store( struct device *_dev, struct device_attribute *attr, const char *buf,
637 + size_t count )
638 +{
639 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
640 + uint32_t on = simple_strtoul(buf, NULL, 16);
641 + uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0;
642 + hprt0_data_t mem;
643 +
644 + mem.d32 = dwc_read_reg32(addr);
645 + mem.b.prtpwr = on;
646 +
647 + //dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
648 + dwc_write_reg32(addr, mem.d32);
649 +
650 + return count;
651 +}
652 +DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
653 +
654 +/**
655 + * @todo Need to do more for suspend?
656 + */
657 +/**
658 + * Show the Bus Suspend status
659 + */
660 +static ssize_t bussuspend_show( struct device *_dev, struct device_attribute *attr, char *buf)
661 +{
662 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
663 + hprt0_data_t val;
664 + val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0);
665 + return sprintf (buf, "Bus Suspend = 0x%x\n", val.b.prtsusp);
666 +}
667 +
668 +/**
669 + * Set the Bus Suspend status
670 + */
671 +static ssize_t bussuspend_store( struct device *_dev, struct device_attribute *attr, const char *buf,
672 + size_t count )
673 +{
674 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
675 + uint32_t in = simple_strtoul(buf, NULL, 16);
676 + uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0;
677 + hprt0_data_t mem;
678 + mem.d32 = dwc_read_reg32(addr);
679 + mem.b.prtsusp = in;
680 + dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
681 + dwc_write_reg32(addr, mem.d32);
682 + return count;
683 +}
684 +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
685 +
686 +/**
687 + * Show the status of Remote Wakeup.
688 + */
689 +static ssize_t remote_wakeup_show( struct device *_dev, struct device_attribute *attr, char *buf)
690 +{
691 +#ifndef DWC_HOST_ONLY
692 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
693 + dctl_data_t val;
694 + val.d32 = dwc_read_reg32( &otg_dev->core_if->dev_if->dev_global_regs->dctl);
695 + return sprintf( buf, "Remote Wakeup = %d Enabled = %d\n",
696 + val.b.rmtwkupsig, otg_dev->pcd->remote_wakeup_enable);
697 +#else
698 + return sprintf(buf, "Host Only Mode!\n");
699 +#endif
700 +}
701 +
702 +/**
703 + * Initiate a remote wakeup of the host. The Device control register
704 + * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
705 + * flag is set.
706 + *
707 + */
708 +static ssize_t remote_wakeup_store( struct device *_dev, struct device_attribute *attr, const char *buf,
709 + size_t count )
710 +{
711 +#ifndef DWC_HOST_ONLY
712 + uint32_t val = simple_strtoul(buf, NULL, 16);
713 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
714 + if (val&1) {
715 + dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
716 + }
717 + else {
718 + dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
719 + }
720 +#endif
721 + return count;
722 +}
723 +DEVICE_ATTR(remote_wakeup, S_IRUGO|S_IWUSR, remote_wakeup_show,
724 + remote_wakeup_store);
725 +
726 +/**
727 + * Dump global registers and either host or device registers (depending on the
728 + * current mode of the core).
729 + */
730 +static ssize_t regdump_show( struct device *_dev, struct device_attribute *attr, char *buf)
731 +{
732 +#ifdef DEBUG
733 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
734 + printk("%s otg_dev=0x%p\n", __FUNCTION__, otg_dev);
735 +
736 + dwc_otg_dump_global_registers( otg_dev->core_if);
737 + if (dwc_otg_is_host_mode(otg_dev->core_if)) {
738 + dwc_otg_dump_host_registers( otg_dev->core_if);
739 + } else {
740 + dwc_otg_dump_dev_registers( otg_dev->core_if);
741 + }
742 +#endif
743 +
744 + return sprintf( buf, "Register Dump\n" );
745 +}
746 +
747 +DEVICE_ATTR(regdump, S_IRUGO|S_IWUSR, regdump_show, 0);
748 +
749 +/**
750 + * Dump the current hcd state.
751 + */
752 +static ssize_t hcddump_show( struct device *_dev, struct device_attribute *attr, char *buf)
753 +{
754 +#ifndef DWC_DEVICE_ONLY
755 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
756 + dwc_otg_hcd_dump_state(otg_dev->hcd);
757 +#endif
758 + return sprintf( buf, "HCD Dump\n" );
759 +}
760 +
761 +DEVICE_ATTR(hcddump, S_IRUGO|S_IWUSR, hcddump_show, 0);
762 +
763 +/**
764 + * Dump the average frame remaining at SOF. This can be used to
765 + * determine average interrupt latency. Frame remaining is also shown for
766 + * start transfer and two additional sample points.
767 + */
768 +static ssize_t hcd_frrem_show( struct device *_dev, struct device_attribute *attr, char *buf)
769 +{
770 +#ifndef DWC_DEVICE_ONLY
771 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
772 + dwc_otg_hcd_dump_frrem(otg_dev->hcd);
773 +#endif
774 + return sprintf( buf, "HCD Dump Frame Remaining\n" );
775 +}
776 +
777 +DEVICE_ATTR(hcd_frrem, S_IRUGO|S_IWUSR, hcd_frrem_show, 0);
778 +
779 +/**
780 + * Displays the time required to read the GNPTXFSIZ register many times (the
781 + * output shows the number of times the register is read).
782 + */
783 +#define RW_REG_COUNT 10000000
784 +#define MSEC_PER_JIFFIE 1000/HZ
785 +static ssize_t rd_reg_test_show( struct device *_dev, struct device_attribute *attr, char *buf)
786 +{
787 + int i;
788 + int time;
789 + int start_jiffies;
790 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
791 +
792 + printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
793 + HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
794 + start_jiffies = jiffies;
795 + for (i = 0; i < RW_REG_COUNT; i++) {
796 + dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz);
797 + }
798 + time = jiffies - start_jiffies;
799 + return sprintf( buf, "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
800 + RW_REG_COUNT, time * MSEC_PER_JIFFIE, time );
801 +}
802 +
803 +DEVICE_ATTR(rd_reg_test, S_IRUGO|S_IWUSR, rd_reg_test_show, 0);
804 +
805 +/**
806 + * Displays the time required to write the GNPTXFSIZ register many times (the
807 + * output shows the number of times the register is written).
808 + */
809 +static ssize_t wr_reg_test_show( struct device *_dev, struct device_attribute *attr, char *buf)
810 +{
811 + int i;
812 + int time;
813 + int start_jiffies;
814 + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
815 + uint32_t reg_val;
816 +
817 + printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
818 + HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
819 + reg_val = dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz);
820 + start_jiffies = jiffies;
821 + for (i = 0; i < RW_REG_COUNT; i++) {
822 + dwc_write_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz, reg_val);
823 + }
824 + time = jiffies - start_jiffies;
825 + return sprintf( buf, "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
826 + RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
827 +}
828 +
829 +DEVICE_ATTR(wr_reg_test, S_IRUGO|S_IWUSR, wr_reg_test_show, 0);
830 +/**@}*/
831 +
832 +/**
833 + * Create the device files
834 + */
835 +void dwc_otg_attr_create (struct device *_dev)
836 +{
837 + int retval;
838 +
839 + retval = device_create_file(_dev, &dev_attr_regoffset);
840 + retval += device_create_file(_dev, &dev_attr_regvalue);
841 + retval += device_create_file(_dev, &dev_attr_mode);
842 + retval += device_create_file(_dev, &dev_attr_hnpcapable);
843 + retval += device_create_file(_dev, &dev_attr_srpcapable);
844 + retval += device_create_file(_dev, &dev_attr_hnp);
845 + retval += device_create_file(_dev, &dev_attr_srp);
846 + retval += device_create_file(_dev, &dev_attr_buspower);
847 + retval += device_create_file(_dev, &dev_attr_bussuspend);
848 + retval += device_create_file(_dev, &dev_attr_busconnected);
849 + retval += device_create_file(_dev, &dev_attr_gotgctl);
850 + retval += device_create_file(_dev, &dev_attr_gusbcfg);
851 + retval += device_create_file(_dev, &dev_attr_grxfsiz);
852 + retval += device_create_file(_dev, &dev_attr_gnptxfsiz);
853 + retval += device_create_file(_dev, &dev_attr_gpvndctl);
854 + retval += device_create_file(_dev, &dev_attr_ggpio);
855 + retval += device_create_file(_dev, &dev_attr_guid);
856 + retval += device_create_file(_dev, &dev_attr_gsnpsid);
857 + retval += device_create_file(_dev, &dev_attr_devspeed);
858 + retval += device_create_file(_dev, &dev_attr_enumspeed);
859 + retval += device_create_file(_dev, &dev_attr_hptxfsiz);
860 + retval += device_create_file(_dev, &dev_attr_hprt0);
861 + retval += device_create_file(_dev, &dev_attr_remote_wakeup);
862 + retval += device_create_file(_dev, &dev_attr_regdump);
863 + retval += device_create_file(_dev, &dev_attr_hcddump);
864 + retval += device_create_file(_dev, &dev_attr_hcd_frrem);
865 + retval += device_create_file(_dev, &dev_attr_rd_reg_test);
866 + retval += device_create_file(_dev, &dev_attr_wr_reg_test);
867 +
868 + if(retval != 0)
869 + {
870 + DWC_PRINT("cannot create sysfs device files.\n");
871 + // DWC_PRINT("killing own sysfs device files!\n");
872 + dwc_otg_attr_remove(_dev);
873 + }
874 +}
875 +
876 +/**
877 + * Remove the device files
878 + */
879 +void dwc_otg_attr_remove (struct device *_dev)
880 +{
881 + device_remove_file(_dev, &dev_attr_regoffset);
882 + device_remove_file(_dev, &dev_attr_regvalue);
883 + device_remove_file(_dev, &dev_attr_mode);
884 + device_remove_file(_dev, &dev_attr_hnpcapable);
885 + device_remove_file(_dev, &dev_attr_srpcapable);
886 + device_remove_file(_dev, &dev_attr_hnp);
887 + device_remove_file(_dev, &dev_attr_srp);
888 + device_remove_file(_dev, &dev_attr_buspower);
889 + device_remove_file(_dev, &dev_attr_bussuspend);
890 + device_remove_file(_dev, &dev_attr_busconnected);
891 + device_remove_file(_dev, &dev_attr_gotgctl);
892 + device_remove_file(_dev, &dev_attr_gusbcfg);
893 + device_remove_file(_dev, &dev_attr_grxfsiz);
894 + device_remove_file(_dev, &dev_attr_gnptxfsiz);
895 + device_remove_file(_dev, &dev_attr_gpvndctl);
896 + device_remove_file(_dev, &dev_attr_ggpio);
897 + device_remove_file(_dev, &dev_attr_guid);
898 + device_remove_file(_dev, &dev_attr_gsnpsid);
899 + device_remove_file(_dev, &dev_attr_devspeed);
900 + device_remove_file(_dev, &dev_attr_enumspeed);
901 + device_remove_file(_dev, &dev_attr_hptxfsiz);
902 + device_remove_file(_dev, &dev_attr_hprt0);
903 + device_remove_file(_dev, &dev_attr_remote_wakeup);
904 + device_remove_file(_dev, &dev_attr_regdump);
905 + device_remove_file(_dev, &dev_attr_hcddump);
906 + device_remove_file(_dev, &dev_attr_hcd_frrem);
907 + device_remove_file(_dev, &dev_attr_rd_reg_test);
908 + device_remove_file(_dev, &dev_attr_wr_reg_test);
909 +}
910 --- /dev/null
911 +++ b/drivers/usb/dwc_otg/dwc_otg_attr.h
912 @@ -0,0 +1,67 @@
913 +/* ==========================================================================
914 + * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_attr.h $
915 + * $Revision: 1.1.1.1 $
916 + * $Date: 2009-04-17 06:15:34 $
917 + * $Change: 510275 $
918 + *
919 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
920 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
921 + * otherwise expressly agreed to in writing between Synopsys and you.
922 + *
923 + * The Software IS NOT an item of Licensed Software or Licensed Product under
924 + * any End User Software License Agreement or Agreement for Licensed Product
925 + * with Synopsys or any supplement thereto. You are permitted to use and
926 + * redistribute this Software in source and binary forms, with or without
927 + * modification, provided that redistributions of source code must retain this
928 + * notice. You may not view, use, disclose, copy or distribute this file or
929 + * any information contained herein except pursuant to this license grant from
930 + * Synopsys. If you do not agree with this notice, including the disclaimer
931 + * below, then you are not authorized to use the Software.
932 + *
933 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
934 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
935 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
936 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
937 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
938 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
939 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
940 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
941 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
942 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
943 + * DAMAGE.
944 + * ========================================================================== */
945 +
946 +#if !defined(__DWC_OTG_ATTR_H__)
947 +#define __DWC_OTG_ATTR_H__
948 +
949 +/** @file
950 + * This file contains the interface to the Linux device attributes.
951 + */
952 +extern struct device_attribute dev_attr_regoffset;
953 +extern struct device_attribute dev_attr_regvalue;
954 +
955 +extern struct device_attribute dev_attr_mode;
956 +extern struct device_attribute dev_attr_hnpcapable;
957 +extern struct device_attribute dev_attr_srpcapable;
958 +extern struct device_attribute dev_attr_hnp;
959 +extern struct device_attribute dev_attr_srp;
960 +extern struct device_attribute dev_attr_buspower;
961 +extern struct device_attribute dev_attr_bussuspend;
962 +extern struct device_attribute dev_attr_busconnected;
963 +extern struct device_attribute dev_attr_gotgctl;
964 +extern struct device_attribute dev_attr_gusbcfg;
965 +extern struct device_attribute dev_attr_grxfsiz;
966 +extern struct device_attribute dev_attr_gnptxfsiz;
967 +extern struct device_attribute dev_attr_gpvndctl;
968 +extern struct device_attribute dev_attr_ggpio;
969 +extern struct device_attribute dev_attr_guid;
970 +extern struct device_attribute dev_attr_gsnpsid;
971 +extern struct device_attribute dev_attr_devspeed;
972 +extern struct device_attribute dev_attr_enumspeed;
973 +extern struct device_attribute dev_attr_hptxfsiz;
974 +extern struct device_attribute dev_attr_hprt0;
975 +
976 +void dwc_otg_attr_create (struct device *_dev);
977 +void dwc_otg_attr_remove (struct device *_dev);
978 +
979 +#endif
980 --- /dev/null
981 +++ b/drivers/usb/dwc_otg/dwc_otg_cil.c
982 @@ -0,0 +1,3025 @@
983 +/* ==========================================================================
984 + * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_cil.c $
985 + * $Revision: 1.1.1.1 $
986 + * $Date: 2009-04-17 06:15:34 $
987 + * $Change: 631780 $
988 + *
989 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
990 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
991 + * otherwise expressly agreed to in writing between Synopsys and you.
992 + *
993 + * The Software IS NOT an item of Licensed Software or Licensed Product under
994 + * any End User Software License Agreement or Agreement for Licensed Product
995 + * with Synopsys or any supplement thereto. You are permitted to use and
996 + * redistribute this Software in source and binary forms, with or without
997 + * modification, provided that redistributions of source code must retain this
998 + * notice. You may not view, use, disclose, copy or distribute this file or
999 + * any information contained herein except pursuant to this license grant from
1000 + * Synopsys. If you do not agree with this notice, including the disclaimer
1001 + * below, then you are not authorized to use the Software.
1002 + *
1003 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
1004 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1005 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1006 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
1007 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1008 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1009 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1010 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1011 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1012 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1013 + * DAMAGE.
1014 + * ========================================================================== */
1015 +
1016 +/** @file
1017 + *
1018 + * The Core Interface Layer provides basic services for accessing and
1019 + * managing the DWC_otg hardware. These services are used by both the
1020 + * Host Controller Driver and the Peripheral Controller Driver.
1021 + *
1022 + * The CIL manages the memory map for the core so that the HCD and PCD
1023 + * don't have to do this separately. It also handles basic tasks like
1024 + * reading/writing the registers and data FIFOs in the controller.
1025 + * Some of the data access functions provide encapsulation of several
1026 + * operations required to perform a task, such as writing multiple
1027 + * registers to start a transfer. Finally, the CIL performs basic
1028 + * services that are not specific to either the host or device modes
1029 + * of operation. These services include management of the OTG Host
1030 + * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
1031 + * Diagnostic API is also provided to allow testing of the controller
1032 + * hardware.
1033 + *
1034 + * The Core Interface Layer has the following requirements:
1035 + * - Provides basic controller operations.
1036 + * - Minimal use of OS services.
1037 + * - The OS services used will be abstracted by using inline functions
1038 + * or macros.
1039 + *
1040 + */
1041 +#include <asm/unaligned.h>
1042 +
1043 +#ifdef DEBUG
1044 +#include <linux/jiffies.h>
1045 +#endif
1046 +
1047 +#include "dwc_otg_plat.h"
1048 +
1049 +#include "dwc_otg_regs.h"
1050 +#include "dwc_otg_cil.h"
1051 +
1052 +/**
1053 + * This function is called to initialize the DWC_otg CSR data
1054 + * structures. The register addresses in the device and host
1055 + * structures are initialized from the base address supplied by the
1056 + * caller. The calling function must make the OS calls to get the
1057 + * base address of the DWC_otg controller registers. The core_params
1058 + * argument holds the parameters that specify how the core should be
1059 + * configured.
1060 + *
1061 + * @param[in] _reg_base_addr Base address of DWC_otg core registers
1062 + * @param[in] _core_params Pointer to the core configuration parameters
1063 + *
1064 + */
1065 +dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t *_reg_base_addr,
1066 + dwc_otg_core_params_t *_core_params)
1067 +{
1068 + dwc_otg_core_if_t *core_if = 0;
1069 + dwc_otg_dev_if_t *dev_if = 0;
1070 + dwc_otg_host_if_t *host_if = 0;
1071 + uint8_t *reg_base = (uint8_t *)_reg_base_addr;
1072 + int i = 0;
1073 +
1074 + DWC_DEBUGPL(DBG_CILV, "%s(%p,%p)\n", __func__, _reg_base_addr, _core_params);
1075 +
1076 + core_if = kmalloc( sizeof(dwc_otg_core_if_t), GFP_KERNEL);
1077 + if (core_if == 0) {
1078 + DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_core_if_t failed\n");
1079 + return 0;
1080 + }
1081 + memset(core_if, 0, sizeof(dwc_otg_core_if_t));
1082 +
1083 + core_if->core_params = _core_params;
1084 + core_if->core_global_regs = (dwc_otg_core_global_regs_t *)reg_base;
1085 + /*
1086 + * Allocate the Device Mode structures.
1087 + */
1088 + dev_if = kmalloc( sizeof(dwc_otg_dev_if_t), GFP_KERNEL);
1089 + if (dev_if == 0) {
1090 + DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");
1091 + kfree( core_if );
1092 + return 0;
1093 + }
1094 +
1095 + dev_if->dev_global_regs =
1096 + (dwc_otg_device_global_regs_t *)(reg_base + DWC_DEV_GLOBAL_REG_OFFSET);
1097 +
1098 + for (i=0; i<MAX_EPS_CHANNELS; i++) {
1099 + dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
1100 + (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
1101 + (i * DWC_EP_REG_OFFSET));
1102 +
1103 + dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
1104 + (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
1105 + (i * DWC_EP_REG_OFFSET));
1106 + DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",
1107 + i, &dev_if->in_ep_regs[i]->diepctl);
1108 + DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",
1109 + i, &dev_if->out_ep_regs[i]->doepctl);
1110 + }
1111 + dev_if->speed = 0; // unknown
1112 + //dev_if->num_eps = MAX_EPS_CHANNELS;
1113 + //dev_if->num_perio_eps = 0;
1114 +
1115 + core_if->dev_if = dev_if;
1116 + /*
1117 + * Allocate the Host Mode structures.
1118 + */
1119 + host_if = kmalloc( sizeof(dwc_otg_host_if_t), GFP_KERNEL);
1120 + if (host_if == 0) {
1121 + DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_host_if_t failed\n");
1122 + kfree( dev_if );
1123 + kfree( core_if );
1124 + return 0;
1125 + }
1126 +
1127 + host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
1128 + (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
1129 + host_if->hprt0 = (uint32_t*)(reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
1130 + for (i=0; i<MAX_EPS_CHANNELS; i++) {
1131 + host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
1132 + (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
1133 + (i * DWC_OTG_CHAN_REGS_OFFSET));
1134 + DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
1135 + i, &host_if->hc_regs[i]->hcchar);
1136 + }
1137 + host_if->num_host_channels = MAX_EPS_CHANNELS;
1138 + core_if->host_if = host_if;
1139 +
1140 + for (i=0; i<MAX_EPS_CHANNELS; i++) {
1141 + core_if->data_fifo[i] =
1142 + (uint32_t *)(reg_base + DWC_OTG_DATA_FIFO_OFFSET +
1143 + (i * DWC_OTG_DATA_FIFO_SIZE));
1144 + DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08x\n",
1145 + i, (unsigned)core_if->data_fifo[i]);
1146 + } // for loop.
1147 +
1148 + core_if->pcgcctl = (uint32_t*)(reg_base + DWC_OTG_PCGCCTL_OFFSET);
1149 +
1150 + /*
1151 + * Store the contents of the hardware configuration registers here for
1152 + * easy access later.
1153 + */
1154 + core_if->hwcfg1.d32 = dwc_read_reg32(&core_if->core_global_regs->ghwcfg1);
1155 + core_if->hwcfg2.d32 = dwc_read_reg32(&core_if->core_global_regs->ghwcfg2);
1156 + core_if->hwcfg3.d32 = dwc_read_reg32(&core_if->core_global_regs->ghwcfg3);
1157 + core_if->hwcfg4.d32 = dwc_read_reg32(&core_if->core_global_regs->ghwcfg4);
1158 +
1159 + DWC_DEBUGPL(DBG_CILV,"hwcfg1=%08x\n",core_if->hwcfg1.d32);
1160 + DWC_DEBUGPL(DBG_CILV,"hwcfg2=%08x\n",core_if->hwcfg2.d32);
1161 + DWC_DEBUGPL(DBG_CILV,"hwcfg3=%08x\n",core_if->hwcfg3.d32);
1162 + DWC_DEBUGPL(DBG_CILV,"hwcfg4=%08x\n",core_if->hwcfg4.d32);
1163 +
1164 +
1165 + DWC_DEBUGPL(DBG_CILV,"op_mode=%0x\n",core_if->hwcfg2.b.op_mode);
1166 + DWC_DEBUGPL(DBG_CILV,"arch=%0x\n",core_if->hwcfg2.b.architecture);
1167 + DWC_DEBUGPL(DBG_CILV,"num_dev_ep=%d\n",core_if->hwcfg2.b.num_dev_ep);
1168 + DWC_DEBUGPL(DBG_CILV,"num_host_chan=%d\n",core_if->hwcfg2.b.num_host_chan);
1169 + DWC_DEBUGPL(DBG_CILV,"nonperio_tx_q_depth=0x%0x\n",core_if->hwcfg2.b.nonperio_tx_q_depth);
1170 + DWC_DEBUGPL(DBG_CILV,"host_perio_tx_q_depth=0x%0x\n",core_if->hwcfg2.b.host_perio_tx_q_depth);
1171 + DWC_DEBUGPL(DBG_CILV,"dev_token_q_depth=0x%0x\n",core_if->hwcfg2.b.dev_token_q_depth);
1172 +
1173 + DWC_DEBUGPL(DBG_CILV,"Total FIFO SZ=%d\n", core_if->hwcfg3.b.dfifo_depth);
1174 + DWC_DEBUGPL(DBG_CILV,"xfer_size_cntr_width=%0x\n", core_if->hwcfg3.b.xfer_size_cntr_width);
1175 +
1176 + /*
1177 + * Set the SRP sucess bit for FS-I2c
1178 + */
1179 + core_if->srp_success = 0;
1180 + core_if->srp_timer_started = 0;
1181 +
1182 + return core_if;
1183 +}
1184 +/**
1185 + * This function frees the structures allocated by dwc_otg_cil_init().
1186 + *
1187 + * @param[in] _core_if The core interface pointer returned from
1188 + * dwc_otg_cil_init().
1189 + *
1190 + */
1191 +void dwc_otg_cil_remove( dwc_otg_core_if_t *_core_if )
1192 +{
1193 + /* Disable all interrupts */
1194 + dwc_modify_reg32( &_core_if->core_global_regs->gahbcfg, 1, 0);
1195 + dwc_write_reg32( &_core_if->core_global_regs->gintmsk, 0);
1196 +
1197 + if ( _core_if->dev_if ) {
1198 + kfree( _core_if->dev_if );
1199 + }
1200 + if ( _core_if->host_if ) {
1201 + kfree( _core_if->host_if );
1202 + }
1203 + kfree( _core_if );
1204 +}
1205 +
1206 +/**
1207 + * This function enables the controller's Global Interrupt in the AHB Config
1208 + * register.
1209 + *
1210 + * @param[in] _core_if Programming view of DWC_otg controller.
1211 + */
1212 +extern void dwc_otg_enable_global_interrupts( dwc_otg_core_if_t *_core_if )
1213 +{
1214 + gahbcfg_data_t ahbcfg = { .d32 = 0};
1215 + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
1216 + dwc_modify_reg32(&_core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
1217 +}
1218 +/**
1219 + * This function disables the controller's Global Interrupt in the AHB Config
1220 + * register.
1221 + *
1222 + * @param[in] _core_if Programming view of DWC_otg controller.
1223 + */
1224 +extern void dwc_otg_disable_global_interrupts( dwc_otg_core_if_t *_core_if )
1225 +{
1226 + gahbcfg_data_t ahbcfg = { .d32 = 0};
1227 + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
1228 + dwc_modify_reg32(&_core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
1229 +}
1230 +
1231 +/**
1232 + * This function initializes the commmon interrupts, used in both
1233 + * device and host modes.
1234 + *
1235 + * @param[in] _core_if Programming view of the DWC_otg controller
1236 + *
1237 + */
1238 +static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t *_core_if)
1239 +{
1240 + dwc_otg_core_global_regs_t *global_regs =
1241 + _core_if->core_global_regs;
1242 + gintmsk_data_t intr_mask = { .d32 = 0};
1243 + /* Clear any pending OTG Interrupts */
1244 + dwc_write_reg32( &global_regs->gotgint, 0xFFFFFFFF);
1245 + /* Clear any pending interrupts */
1246 + dwc_write_reg32( &global_regs->gintsts, 0xFFFFFFFF);
1247 + /*
1248 + * Enable the interrupts in the GINTMSK.
1249 + */
1250 + intr_mask.b.modemismatch = 1;
1251 + intr_mask.b.otgintr = 1;
1252 + if (!_core_if->dma_enable) {
1253 + intr_mask.b.rxstsqlvl = 1;
1254 + }
1255 + intr_mask.b.conidstschng = 1;
1256 + intr_mask.b.wkupintr = 1;
1257 + intr_mask.b.disconnect = 1;
1258 + intr_mask.b.usbsuspend = 1;
1259 + intr_mask.b.sessreqintr = 1;
1260 + dwc_write_reg32( &global_regs->gintmsk, intr_mask.d32);
1261 +}
1262 +
1263 +/**
1264 + * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
1265 + * type.
1266 + */
1267 +static void init_fslspclksel(dwc_otg_core_if_t *_core_if)
1268 +{
1269 + uint32_t val;
1270 + hcfg_data_t hcfg;
1271 +
1272 + if (((_core_if->hwcfg2.b.hs_phy_type == 2) &&
1273 + (_core_if->hwcfg2.b.fs_phy_type == 1) &&
1274 + (_core_if->core_params->ulpi_fs_ls)) ||
1275 + (_core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS))
1276 + {
1277 + /* Full speed PHY */
1278 + val = DWC_HCFG_48_MHZ;
1279 + } else {
1280 + /* High speed PHY running at full speed or high speed */
1281 + val = DWC_HCFG_30_60_MHZ;
1282 + }
1283 +
1284 + DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
1285 + hcfg.d32 = dwc_read_reg32(&_core_if->host_if->host_global_regs->hcfg);
1286 + hcfg.b.fslspclksel = val;
1287 + dwc_write_reg32(&_core_if->host_if->host_global_regs->hcfg, hcfg.d32);
1288 +}
1289 +
1290 +/**
1291 + * Initializes the DevSpd field of the DCFG register depending on the PHY type
1292 + * and the enumeration speed of the device.
1293 + */
1294 +static void init_devspd(dwc_otg_core_if_t *_core_if)
1295 +{
1296 + uint32_t val;
1297 + dcfg_data_t dcfg;
1298 +
1299 + if (((_core_if->hwcfg2.b.hs_phy_type == 2) &&
1300 + (_core_if->hwcfg2.b.fs_phy_type == 1) &&
1301 + (_core_if->core_params->ulpi_fs_ls)) ||
1302 + (_core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS))
1303 + {
1304 + /* Full speed PHY */
1305 + val = 0x3;
1306 + } else if (_core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
1307 + /* High speed PHY running at full speed */
1308 + val = 0x1;
1309 + } else {
1310 + /* High speed PHY running at high speed */
1311 + val = 0x0;
1312 + }
1313 +
1314 + DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
1315 + dcfg.d32 = dwc_read_reg32(&_core_if->dev_if->dev_global_regs->dcfg);
1316 + dcfg.b.devspd = val;
1317 + dwc_write_reg32(&_core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
1318 +}
1319 +
1320 +/**
1321 + * This function calculates the number of IN EPS
1322 + * using GHWCFG1 and GHWCFG2 registers values
1323 + *
1324 + * @param _pcd the pcd structure.
1325 + */
1326 +static uint32_t calc_num_in_eps(dwc_otg_core_if_t * _core_if)
1327 +{
1328 + uint32_t num_in_eps = 0;
1329 + uint32_t num_eps = _core_if->hwcfg2.b.num_dev_ep;
1330 + uint32_t hwcfg1 = _core_if->hwcfg1.d32 >> 2;
1331 + uint32_t num_tx_fifos = _core_if->hwcfg4.b.num_in_eps;
1332 + int i;
1333 + for (i = 0; i < num_eps; ++i) {
1334 + if (!(hwcfg1 & 0x1))
1335 + num_in_eps++;
1336 + hwcfg1 >>= 2;
1337 + }
1338 + if (_core_if->hwcfg4.b.ded_fifo_en) {
1339 + num_in_eps = (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
1340 + }
1341 + return num_in_eps;
1342 +}
1343 +
1344 +
1345 +/**
1346 + * This function calculates the number of OUT EPS
1347 + * using GHWCFG1 and GHWCFG2 registers values
1348 + *
1349 + * @param _pcd the pcd structure.
1350 + */
1351 +static uint32_t calc_num_out_eps(dwc_otg_core_if_t * _core_if)
1352 +{
1353 + uint32_t num_out_eps = 0;
1354 + uint32_t num_eps = _core_if->hwcfg2.b.num_dev_ep;
1355 + uint32_t hwcfg1 = _core_if->hwcfg1.d32 >> 2;
1356 + int i;
1357 + for (i = 0; i < num_eps; ++i) {
1358 + if (!(hwcfg1 & 0x2))
1359 + num_out_eps++;
1360 + hwcfg1 >>= 2;
1361 + }
1362 + return num_out_eps;
1363 +}
1364 +/**
1365 + * This function initializes the DWC_otg controller registers and
1366 + * prepares the core for device mode or host mode operation.
1367 + *
1368 + * @param _core_if Programming view of the DWC_otg controller
1369 + *
1370 + */
1371 +void dwc_otg_core_init(dwc_otg_core_if_t *_core_if)
1372 +{
1373 + dwc_otg_core_global_regs_t * global_regs = _core_if->core_global_regs;
1374 + dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
1375 + int i = 0;
1376 + gahbcfg_data_t ahbcfg = { .d32 = 0};
1377 + gusbcfg_data_t usbcfg = { .d32 = 0 };
1378 + gi2cctl_data_t i2cctl = {.d32 = 0};
1379 +
1380 + DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p)\n",_core_if);
1381 +
1382 + /* Common Initialization */
1383 +
1384 + usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
1385 + DWC_DEBUGPL(DBG_CIL, "USB config register: 0x%08x\n", usbcfg.d32);
1386 +
1387 + /* Program the ULPI External VBUS bit if needed */
1388 + //usbcfg.b.ulpi_ext_vbus_drv = 1;
1389 + //usbcfg.b.ulpi_ext_vbus_drv = 0;
1390 + usbcfg.b.ulpi_ext_vbus_drv =
1391 + (_core_if->core_params->phy_ulpi_ext_vbus == DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
1392 +
1393 + /* Set external TS Dline pulsing */
1394 + usbcfg.b.term_sel_dl_pulse = (_core_if->core_params->ts_dline == 1) ? 1 : 0;
1395 + dwc_write_reg32 (&global_regs->gusbcfg, usbcfg.d32);
1396 +
1397 + /* Reset the Controller */
1398 + dwc_otg_core_reset( _core_if );
1399 +
1400 + /* Initialize parameters from Hardware configuration registers. */
1401 +#if 0
1402 + dev_if->num_eps = _core_if->hwcfg2.b.num_dev_ep;
1403 + dev_if->num_perio_eps = _core_if->hwcfg4.b.num_dev_perio_in_ep;
1404 +#else
1405 + dev_if->num_in_eps = calc_num_in_eps(_core_if);
1406 + dev_if->num_out_eps = calc_num_out_eps(_core_if);
1407 +#endif
1408 + DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
1409 + _core_if->hwcfg4.b.num_dev_perio_in_ep);
1410 + DWC_DEBUGPL(DBG_CIL, "Is power optimization enabled? %s\n",
1411 + _core_if->hwcfg4.b.power_optimiz ? "Yes" : "No");
1412 + DWC_DEBUGPL(DBG_CIL, "vbus_valid filter enabled? %s\n",
1413 + _core_if->hwcfg4.b.vbus_valid_filt_en ? "Yes" : "No");
1414 + DWC_DEBUGPL(DBG_CIL, "iddig filter enabled? %s\n",
1415 + _core_if->hwcfg4.b.iddig_filt_en ? "Yes" : "No");
1416 +
1417 + DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",_core_if->hwcfg4.b.num_dev_perio_in_ep);
1418 + for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
1419 + dev_if->perio_tx_fifo_size[i] =
1420 + dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16;
1421 + DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", i,
1422 + dev_if->perio_tx_fifo_size[i]);
1423 + }
1424 + for (i = 0; i < _core_if->hwcfg4.b.num_in_eps; i++) {
1425 + dev_if->tx_fifo_size[i] =
1426 + dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16;
1427 + DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", i,
1428 + dev_if->perio_tx_fifo_size[i]);
1429 + }
1430 +
1431 + _core_if->total_fifo_size = _core_if->hwcfg3.b.dfifo_depth;
1432 + _core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz);
1433 + _core_if->nperio_tx_fifo_size = dwc_read_reg32(&global_regs->gnptxfsiz) >> 16;
1434 +
1435 + DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", _core_if->total_fifo_size);
1436 + DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", _core_if->rx_fifo_size);
1437 + DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n", _core_if->nperio_tx_fifo_size);
1438 +
1439 + /* This programming sequence needs to happen in FS mode before any other
1440 + * programming occurs */
1441 + if ((_core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
1442 + (_core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
1443 + /* If FS mode with FS PHY */
1444 +
1445 + /* core_init() is now called on every switch so only call the
1446 + * following for the first time through. */
1447 + if (!_core_if->phy_init_done) {
1448 + _core_if->phy_init_done = 1;
1449 + DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
1450 + usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
1451 + usbcfg.b.physel = 1;
1452 + dwc_write_reg32 (&global_regs->gusbcfg, usbcfg.d32);
1453 +
1454 + /* Reset after a PHY select */
1455 + dwc_otg_core_reset( _core_if );
1456 + }
1457 +
1458 + /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
1459 + * do this on HNP Dev/Host mode switches (done in dev_init and
1460 + * host_init). */
1461 + if (dwc_otg_is_host_mode(_core_if)) {
1462 + DWC_DEBUGPL(DBG_CIL, "host mode\n");
1463 + init_fslspclksel(_core_if);
1464 + } else {
1465 + DWC_DEBUGPL(DBG_CIL, "device mode\n");
1466 + init_devspd(_core_if);
1467 + }
1468 +
1469 + if (_core_if->core_params->i2c_enable) {
1470 + DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
1471 + /* Program GUSBCFG.OtgUtmifsSel to I2C */
1472 + usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
1473 + usbcfg.b.otgutmifssel = 1;
1474 + dwc_write_reg32 (&global_regs->gusbcfg, usbcfg.d32);
1475 +
1476 + /* Program GI2CCTL.I2CEn */
1477 + i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl);
1478 + i2cctl.b.i2cdevaddr = 1;
1479 + i2cctl.b.i2cen = 0;
1480 + dwc_write_reg32 (&global_regs->gi2cctl, i2cctl.d32);
1481 + i2cctl.b.i2cen = 1;
1482 + dwc_write_reg32 (&global_regs->gi2cctl, i2cctl.d32);
1483 + }
1484 +
1485 + } /* endif speed == DWC_SPEED_PARAM_FULL */
1486 + else {
1487 + /* High speed PHY. */
1488 + if (!_core_if->phy_init_done) {
1489 + _core_if->phy_init_done = 1;
1490 + DWC_DEBUGPL(DBG_CIL, "High spped PHY\n");
1491 + /* HS PHY parameters. These parameters are preserved
1492 + * during soft reset so only program the first time. Do
1493 + * a soft reset immediately after setting phyif. */
1494 + usbcfg.b.ulpi_utmi_sel = _core_if->core_params->phy_type;
1495 + if (usbcfg.b.ulpi_utmi_sel == 2) { // winder
1496 + DWC_DEBUGPL(DBG_CIL, "ULPI\n");
1497 + /* ULPI interface */
1498 + usbcfg.b.phyif = 0;
1499 + usbcfg.b.ddrsel = _core_if->core_params->phy_ulpi_ddr;
1500 + } else {
1501 + /* UTMI+ interface */
1502 + if (_core_if->core_params->phy_utmi_width == 16) {
1503 + usbcfg.b.phyif = 1;
1504 + DWC_DEBUGPL(DBG_CIL, "UTMI+ 16\n");
1505 + } else {
1506 + DWC_DEBUGPL(DBG_CIL, "UTMI+ 8\n");
1507 + usbcfg.b.phyif = 0;
1508 + }
1509 + }
1510 + dwc_write_reg32( &global_regs->gusbcfg, usbcfg.d32);
1511 +
1512 + /* Reset after setting the PHY parameters */
1513 + dwc_otg_core_reset( _core_if );
1514 + }
1515 + }
1516 +
1517 + if ((_core_if->hwcfg2.b.hs_phy_type == 2) &&
1518 + (_core_if->hwcfg2.b.fs_phy_type == 1) &&
1519 + (_core_if->core_params->ulpi_fs_ls))
1520 + {
1521 + DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
1522 + usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
1523 + usbcfg.b.ulpi_fsls = 1;
1524 + usbcfg.b.ulpi_clk_sus_m = 1;
1525 + dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
1526 + } else {
1527 + DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS=0\n");
1528 + usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
1529 + usbcfg.b.ulpi_fsls = 0;
1530 + usbcfg.b.ulpi_clk_sus_m = 0;
1531 + dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
1532 + }
1533 +
1534 + /* Program the GAHBCFG Register.*/
1535 + switch (_core_if->hwcfg2.b.architecture){
1536 +
1537 + case DWC_SLAVE_ONLY_ARCH:
1538 + DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
1539 + ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
1540 + ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
1541 + _core_if->dma_enable = 0;
1542 + break;
1543 +
1544 + case DWC_EXT_DMA_ARCH:
1545 + DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
1546 + ahbcfg.b.hburstlen = _core_if->core_params->dma_burst_size;
1547 + _core_if->dma_enable = (_core_if->core_params->dma_enable != 0);
1548 + break;
1549 +
1550 + case DWC_INT_DMA_ARCH:
1551 + DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
1552 + //ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR;
1553 + ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR4;
1554 + _core_if->dma_enable = (_core_if->core_params->dma_enable != 0);
1555 + break;
1556 + }
1557 + ahbcfg.b.dmaenable = _core_if->dma_enable;
1558 + dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32);
1559 + _core_if->en_multiple_tx_fifo = _core_if->hwcfg4.b.ded_fifo_en;
1560 +
1561 + /*
1562 + * Program the GUSBCFG register.
1563 + */
1564 + usbcfg.d32 = dwc_read_reg32( &global_regs->gusbcfg );
1565 +
1566 + switch (_core_if->hwcfg2.b.op_mode) {
1567 + case DWC_MODE_HNP_SRP_CAPABLE:
1568 + usbcfg.b.hnpcap = (_core_if->core_params->otg_cap ==
1569 + DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
1570 + usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=
1571 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
1572 + break;
1573 +
1574 + case DWC_MODE_SRP_ONLY_CAPABLE:
1575 + usbcfg.b.hnpcap = 0;
1576 + usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=
1577 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
1578 + break;
1579 +
1580 + case DWC_MODE_NO_HNP_SRP_CAPABLE:
1581 + usbcfg.b.hnpcap = 0;
1582 + usbcfg.b.srpcap = 0;
1583 + break;
1584 +
1585 + case DWC_MODE_SRP_CAPABLE_DEVICE:
1586 + usbcfg.b.hnpcap = 0;
1587 + usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=
1588 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
1589 + break;
1590 +
1591 + case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
1592 + usbcfg.b.hnpcap = 0;
1593 + usbcfg.b.srpcap = 0;
1594 + break;
1595 +
1596 + case DWC_MODE_SRP_CAPABLE_HOST:
1597 + usbcfg.b.hnpcap = 0;
1598 + usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=
1599 + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
1600 + break;
1601 +
1602 + case DWC_MODE_NO_SRP_CAPABLE_HOST:
1603 + usbcfg.b.hnpcap = 0;
1604 + usbcfg.b.srpcap = 0;
1605 + break;
1606 + }
1607 +
1608 + dwc_write_reg32( &global_regs->gusbcfg, usbcfg.d32);
1609 +
1610 + /* Enable common interrupts */
1611 + dwc_otg_enable_common_interrupts( _core_if );
1612 +
1613 + /* Do device or host intialization based on mode during PCD
1614 + * and HCD initialization */
1615 + if (dwc_otg_is_host_mode( _core_if )) {
1616 + DWC_DEBUGPL(DBG_ANY, "Host Mode\n" );
1617 + _core_if->op_state = A_HOST;
1618 + } else {
1619 + DWC_DEBUGPL(DBG_ANY, "Device Mode\n" );
1620 + _core_if->op_state = B_PERIPHERAL;
1621 +#ifdef DWC_DEVICE_ONLY
1622 + dwc_otg_core_dev_init( _core_if );
1623 +#endif
1624 + }
1625 +}
1626 +
1627 +
1628 +/**
1629 + * This function enables the Device mode interrupts.
1630 + *
1631 + * @param _core_if Programming view of DWC_otg controller
1632 + */
1633 +void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t *_core_if)
1634 +{
1635 + gintmsk_data_t intr_mask = { .d32 = 0};
1636 + dwc_otg_core_global_regs_t * global_regs = _core_if->core_global_regs;
1637 +
1638 + DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
1639 +
1640 + /* Disable all interrupts. */
1641 + dwc_write_reg32( &global_regs->gintmsk, 0);
1642 +
1643 + /* Clear any pending interrupts */
1644 + dwc_write_reg32( &global_regs->gintsts, 0xFFFFFFFF);
1645 +
1646 + /* Enable the common interrupts */
1647 + dwc_otg_enable_common_interrupts( _core_if );
1648 +
1649 + /* Enable interrupts */
1650 + intr_mask.b.usbreset = 1;
1651 + intr_mask.b.enumdone = 1;
1652 + //intr_mask.b.epmismatch = 1;
1653 + intr_mask.b.inepintr = 1;
1654 + intr_mask.b.outepintr = 1;
1655 + intr_mask.b.erlysuspend = 1;
1656 + if (_core_if->en_multiple_tx_fifo == 0) {
1657 + intr_mask.b.epmismatch = 1;
1658 + }
1659 +
1660 + /** @todo NGS: Should this be a module parameter? */
1661 + intr_mask.b.isooutdrop = 1;
1662 + intr_mask.b.eopframe = 1;
1663 + intr_mask.b.incomplisoin = 1;
1664 + intr_mask.b.incomplisoout = 1;
1665 +
1666 + dwc_modify_reg32( &global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
1667 +
1668 + DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
1669 + dwc_read_reg32( &global_regs->gintmsk));
1670 +}
1671 +
1672 +/**
1673 + * This function initializes the DWC_otg controller registers for
1674 + * device mode.
1675 + *
1676 + * @param _core_if Programming view of DWC_otg controller
1677 + *
1678 + */
1679 +void dwc_otg_core_dev_init(dwc_otg_core_if_t *_core_if)
1680 +{
1681 + dwc_otg_core_global_regs_t *global_regs =
1682 + _core_if->core_global_regs;
1683 + dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
1684 + dwc_otg_core_params_t *params = _core_if->core_params;
1685 + dcfg_data_t dcfg = {.d32 = 0};
1686 + grstctl_t resetctl = { .d32=0 };
1687 + int i;
1688 + uint32_t rx_fifo_size;
1689 + fifosize_data_t nptxfifosize;
1690 + fifosize_data_t txfifosize;
1691 + dthrctl_data_t dthrctl;
1692 +
1693 + fifosize_data_t ptxfifosize;
1694 +
1695 + /* Restart the Phy Clock */
1696 + dwc_write_reg32(_core_if->pcgcctl, 0);
1697 +
1698 + /* Device configuration register */
1699 + init_devspd(_core_if);
1700 + dcfg.d32 = dwc_read_reg32( &dev_if->dev_global_regs->dcfg);
1701 + dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
1702 + dwc_write_reg32( &dev_if->dev_global_regs->dcfg, dcfg.d32 );
1703 +
1704 + /* Configure data FIFO sizes */
1705 + if ( _core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo ) {
1706 +
1707 + DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", _core_if->total_fifo_size);
1708 + DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", params->dev_rx_fifo_size);
1709 + DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", params->dev_nperio_tx_fifo_size);
1710 +
1711 + /* Rx FIFO */
1712 + DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
1713 + dwc_read_reg32(&global_regs->grxfsiz));
1714 + rx_fifo_size = params->dev_rx_fifo_size;
1715 + dwc_write_reg32( &global_regs->grxfsiz, rx_fifo_size );
1716 + DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
1717 + dwc_read_reg32(&global_regs->grxfsiz));
1718 +
1719 + /** Set Periodic Tx FIFO Mask all bits 0 */
1720 + _core_if->p_tx_msk = 0;
1721 +
1722 + /** Set Tx FIFO Mask all bits 0 */
1723 + _core_if->tx_msk = 0;
1724 + if (_core_if->en_multiple_tx_fifo == 0) {
1725 + /* Non-periodic Tx FIFO */
1726 + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
1727 + dwc_read_reg32(&global_regs->gnptxfsiz));
1728 + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
1729 + nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
1730 + dwc_write_reg32( &global_regs->gnptxfsiz, nptxfifosize.d32 );
1731 + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
1732 + dwc_read_reg32(&global_regs->gnptxfsiz));
1733 +
1734 +
1735 + /**@todo NGS: Fix Periodic FIFO Sizing! */
1736 + /*
1737 + * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.
1738 + * Indexes of the FIFO size module parameters in the
1739 + * dev_perio_tx_fifo_size array and the FIFO size registers in
1740 + * the dptxfsiz array run from 0 to 14.
1741 + */
1742 + /** @todo Finish debug of this */
1743 + ptxfifosize.b.startaddr =
1744 + nptxfifosize.b.startaddr + nptxfifosize.b.depth;
1745 + for (i = 0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep;i++) {
1746 + ptxfifosize.b.depth = params->dev_perio_tx_fifo_size[i];
1747 + DWC_DEBUGPL(DBG_CIL,"initial dptxfsiz_dieptxf[%d]=%08x\n",
1748 + i,dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]));
1749 + dwc_write_reg32(&global_regs->dptxfsiz_dieptxf[i],ptxfifosize.d32);
1750 + DWC_DEBUGPL(DBG_CIL,"new dptxfsiz_dieptxf[%d]=%08x\n",
1751 + i,dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]));
1752 + ptxfifosize.b.startaddr += ptxfifosize.b.depth;
1753 + }
1754 + } else {
1755 +
1756 + /*
1757 + * Tx FIFOs These FIFOs are numbered from 1 to 15.
1758 + * Indexes of the FIFO size module parameters in the
1759 + * dev_tx_fifo_size array and the FIFO size registers in
1760 + * the dptxfsiz_dieptxf array run from 0 to 14.
1761 + */
1762 +
1763 + /* Non-periodic Tx FIFO */
1764 + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
1765 + dwc_read_reg32(&global_regs->gnptxfsiz));
1766 + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
1767 + nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
1768 + dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);
1769 + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
1770 + dwc_read_reg32(&global_regs->gnptxfsiz));
1771 + txfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth;
1772 + for (i = 1;i < _core_if->hwcfg4.b.num_dev_perio_in_ep;i++) {
1773 + txfifosize.b.depth = params->dev_tx_fifo_size[i];
1774 + DWC_DEBUGPL(DBG_CIL,"initial dptxfsiz_dieptxf[%d]=%08x\n",
1775 + i,dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]));
1776 + dwc_write_reg32(&global_regs->dptxfsiz_dieptxf[i - 1],txfifosize.d32);
1777 + DWC_DEBUGPL(DBG_CIL,"new dptxfsiz_dieptxf[%d]=%08x\n",
1778 + i,dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i-1]));
1779 + txfifosize.b.startaddr += txfifosize.b.depth;
1780 + }
1781 + }
1782 + }
1783 + /* Flush the FIFOs */
1784 + dwc_otg_flush_tx_fifo(_core_if, 0x10); /* all Tx FIFOs */
1785 + dwc_otg_flush_rx_fifo(_core_if);
1786 +
1787 + /* Flush the Learning Queue. */
1788 + resetctl.b.intknqflsh = 1;
1789 + dwc_write_reg32( &_core_if->core_global_regs->grstctl, resetctl.d32);
1790 +
1791 + /* Clear all pending Device Interrupts */
1792 + dwc_write_reg32( &dev_if->dev_global_regs->diepmsk, 0 );
1793 + dwc_write_reg32( &dev_if->dev_global_regs->doepmsk, 0 );
1794 + dwc_write_reg32( &dev_if->dev_global_regs->daint, 0xFFFFFFFF );
1795 + dwc_write_reg32( &dev_if->dev_global_regs->daintmsk, 0 );
1796 +
1797 + for (i = 0; i <= dev_if->num_in_eps; i++) {
1798 + depctl_data_t depctl;
1799 + depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl);
1800 + if (depctl.b.epena) {
1801 + depctl.d32 = 0;
1802 + depctl.b.epdis = 1;
1803 + depctl.b.snak = 1;
1804 + } else {
1805 + depctl.d32 = 0;
1806 + }
1807 + dwc_write_reg32( &dev_if->in_ep_regs[i]->diepctl, depctl.d32);
1808 +
1809 + dwc_write_reg32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
1810 + dwc_write_reg32(&dev_if->in_ep_regs[i]->diepdma, 0);
1811 + dwc_write_reg32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
1812 + }
1813 + for (i = 0; i <= dev_if->num_out_eps; i++) {
1814 + depctl_data_t depctl;
1815 + depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl);
1816 + if (depctl.b.epena) {
1817 + depctl.d32 = 0;
1818 + depctl.b.epdis = 1;
1819 + depctl.b.snak = 1;
1820 + } else {
1821 + depctl.d32 = 0;
1822 + }
1823 + dwc_write_reg32( &dev_if->out_ep_regs[i]->doepctl, depctl.d32);
1824 +
1825 + //dwc_write_reg32( &dev_if->in_ep_regs[i]->dieptsiz, 0);
1826 + dwc_write_reg32( &dev_if->out_ep_regs[i]->doeptsiz, 0);
1827 + //dwc_write_reg32( &dev_if->in_ep_regs[i]->diepdma, 0);
1828 + dwc_write_reg32( &dev_if->out_ep_regs[i]->doepdma, 0);
1829 + //dwc_write_reg32( &dev_if->in_ep_regs[i]->diepint, 0xFF);
1830 + dwc_write_reg32( &dev_if->out_ep_regs[i]->doepint, 0xFF);
1831 + }
1832 +
1833 + if (_core_if->en_multiple_tx_fifo && _core_if->dma_enable) {
1834 + dev_if->non_iso_tx_thr_en = _core_if->core_params->thr_ctl & 0x1;
1835 + dev_if->iso_tx_thr_en = (_core_if->core_params->thr_ctl >> 1) & 0x1;
1836 + dev_if->rx_thr_en = (_core_if->core_params->thr_ctl >> 2) & 0x1;
1837 + dev_if->rx_thr_length = _core_if->core_params->rx_thr_length;
1838 + dev_if->tx_thr_length = _core_if->core_params->tx_thr_length;
1839 + dthrctl.d32 = 0;
1840 + dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;
1841 + dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;
1842 + dthrctl.b.tx_thr_len = dev_if->tx_thr_length;
1843 + dthrctl.b.rx_thr_en = dev_if->rx_thr_en;
1844 + dthrctl.b.rx_thr_len = dev_if->rx_thr_length;
1845 + dwc_write_reg32(&dev_if->dev_global_regs->dtknqr3_dthrctl,dthrctl.d32);
1846 + DWC_DEBUGPL(DBG_CIL, "Non ISO Tx Thr - %d\nISO Tx Thr - %d\n"
1847 + "Rx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",
1848 + dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,
1849 + dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,
1850 + dthrctl.b.rx_thr_len);
1851 + }
1852 + dwc_otg_enable_device_interrupts( _core_if );
1853 + {
1854 + diepmsk_data_t msk = {.d32 = 0};
1855 + msk.b.txfifoundrn = 1;
1856 + dwc_modify_reg32(&dev_if->dev_global_regs->diepmsk, msk.d32,msk.d32);
1857 +}
1858 +}
1859 +
1860 +/**
1861 + * This function enables the Host mode interrupts.
1862 + *
1863 + * @param _core_if Programming view of DWC_otg controller
1864 + */
1865 +void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t *_core_if)
1866 +{
1867 + dwc_otg_core_global_regs_t *global_regs = _core_if->core_global_regs;
1868 + gintmsk_data_t intr_mask = {.d32 = 0};
1869 +
1870 + DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
1871 +
1872 + /* Disable all interrupts. */
1873 + dwc_write_reg32(&global_regs->gintmsk, 0);
1874 +
1875 + /* Clear any pending interrupts. */
1876 + dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF);
1877 +
1878 + /* Enable the common interrupts */
1879 + dwc_otg_enable_common_interrupts(_core_if);
1880 +
1881 + /*
1882 + * Enable host mode interrupts without disturbing common
1883 + * interrupts.
1884 + */
1885 + intr_mask.b.sofintr = 1;
1886 + intr_mask.b.portintr = 1;
1887 + intr_mask.b.hcintr = 1;
1888 +
1889 + //dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
1890 + //dwc_modify_reg32(&global_regs->gintmsk, 0, intr_mask.d32);
1891 + dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
1892 +}
1893 +
1894 +/**
1895 + * This function disables the Host Mode interrupts.
1896 + *
1897 + * @param _core_if Programming view of DWC_otg controller
1898 + */
1899 +void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t *_core_if)
1900 +{
1901 + dwc_otg_core_global_regs_t *global_regs =
1902 + _core_if->core_global_regs;
1903 + gintmsk_data_t intr_mask = {.d32 = 0};
1904 +
1905 + DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);
1906 +
1907 + /*
1908 + * Disable host mode interrupts without disturbing common
1909 + * interrupts.
1910 + */
1911 + intr_mask.b.sofintr = 1;
1912 + intr_mask.b.portintr = 1;
1913 + intr_mask.b.hcintr = 1;
1914 + intr_mask.b.ptxfempty = 1;
1915 + intr_mask.b.nptxfempty = 1;
1916 +
1917 + dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 0);
1918 +}
1919 +
1920 +#if 0
1921 +/* currently not used, keep it here as if needed later */
1922 +static int phy_read(dwc_otg_core_if_t * _core_if, int addr)
1923 +{
1924 + u32 val;
1925 + int timeout = 10;
1926 +
1927 + dwc_write_reg32(&_core_if->core_global_regs->gpvndctl,
1928 + 0x02000000 | (addr << 16));
1929 + val = dwc_read_reg32(&_core_if->core_global_regs->gpvndctl);
1930 + while (((val & 0x08000000) == 0) && (timeout--)) {
1931 + udelay(1000);
1932 + val = dwc_read_reg32(&_core_if->core_global_regs->gpvndctl);
1933 + }
1934 + val = dwc_read_reg32(&_core_if->core_global_regs->gpvndctl);
1935 + printk("%s: addr=%02x regval=%02x\n", __func__, addr, val & 0x000000ff);
1936 +
1937 + return 0;
1938 +}
1939 +#endif
1940 +
1941 +/**
1942 + * This function initializes the DWC_otg controller registers for
1943 + * host mode.
1944 + *
1945 + * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
1946 + * request queues. Host channels are reset to ensure that they are ready for
1947 + * performing transfers.
1948 + *
1949 + * @param _core_if Programming view of DWC_otg controller
1950 + *
1951 + */
1952 +void dwc_otg_core_host_init(dwc_otg_core_if_t *_core_if)
1953 +{
1954 + dwc_otg_core_global_regs_t *global_regs = _core_if->core_global_regs;
1955 + dwc_otg_host_if_t *host_if = _core_if->host_if;
1956 + dwc_otg_core_params_t *params = _core_if->core_params;
1957 + hprt0_data_t hprt0 = {.d32 = 0};
1958 + fifosize_data_t nptxfifosize;
1959 + fifosize_data_t ptxfifosize;
1960 + int i;
1961 + hcchar_data_t hcchar;
1962 + hcfg_data_t hcfg;
1963 + dwc_otg_hc_regs_t *hc_regs;
1964 + int num_channels;
1965 + gotgctl_data_t gotgctl = {.d32 = 0};
1966 +
1967 + DWC_DEBUGPL(DBG_CILV,"%s(%p)\n", __func__, _core_if);
1968 +
1969 + /* Restart the Phy Clock */
1970 + dwc_write_reg32(_core_if->pcgcctl, 0);
1971 +
1972 + /* Initialize Host Configuration Register */
1973 + init_fslspclksel(_core_if);
1974 + if (_core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
1975 + hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg);
1976 + hcfg.b.fslssupp = 1;
1977 + dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32);
1978 + }
1979 +
1980 + /* Configure data FIFO sizes */
1981 + if (_core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
1982 + DWC_DEBUGPL(DBG_CIL,"Total FIFO Size=%d\n", _core_if->total_fifo_size);
1983 + DWC_DEBUGPL(DBG_CIL,"Rx FIFO Size=%d\n", params->host_rx_fifo_size);
1984 + DWC_DEBUGPL(DBG_CIL,"NP Tx FIFO Size=%d\n", params->host_nperio_tx_fifo_size);
1985 + DWC_DEBUGPL(DBG_CIL,"P Tx FIFO Size=%d\n", params->host_perio_tx_fifo_size);
1986 +
1987 + /* Rx FIFO */
1988 + DWC_DEBUGPL(DBG_CIL,"initial grxfsiz=%08x\n", dwc_read_reg32(&global_regs->grxfsiz));
1989 + dwc_write_reg32(&global_regs->grxfsiz, params->host_rx_fifo_size);
1990 + DWC_DEBUGPL(DBG_CIL,"new grxfsiz=%08x\n", dwc_read_reg32(&global_regs->grxfsiz));
1991 +
1992 + /* Non-periodic Tx FIFO */
1993 + DWC_DEBUGPL(DBG_CIL,"initial gnptxfsiz=%08x\n", dwc_read_reg32(&global_regs->gnptxfsiz));
1994 + nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
1995 + nptxfifosize.b.startaddr = params->host_rx_fifo_size;
1996 + dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);
1997 + DWC_DEBUGPL(DBG_CIL,"new gnptxfsiz=%08x\n", dwc_read_reg32(&global_regs->gnptxfsiz));
1998 +
1999 + /* Periodic Tx FIFO */
2000 + DWC_DEBUGPL(DBG_CIL,"initial hptxfsiz=%08x\n", dwc_read_reg32(&global_regs->hptxfsiz));
2001 + ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
2002 + ptxfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth;
2003 + dwc_write_reg32(&global_regs->hptxfsiz, ptxfifosize.d32);
2004 + DWC_DEBUGPL(DBG_CIL,"new hptxfsiz=%08x\n", dwc_read_reg32(&global_regs->hptxfsiz));
2005 + }
2006 +
2007 + /* Clear Host Set HNP Enable in the OTG Control Register */
2008 + gotgctl.b.hstsethnpen = 1;
2009 + dwc_modify_reg32( &global_regs->gotgctl, gotgctl.d32, 0);
2010 +
2011 + /* Make sure the FIFOs are flushed. */
2012 + dwc_otg_flush_tx_fifo(_core_if, 0x10 /* all Tx FIFOs */);
2013 + dwc_otg_flush_rx_fifo(_core_if);
2014 +
2015 + /* Flush out any leftover queued requests. */
2016 + num_channels = _core_if->core_params->host_channels;
2017 + for (i = 0; i < num_channels; i++) {
2018 + hc_regs = _core_if->host_if->hc_regs[i];
2019 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2020 + hcchar.b.chen = 0;
2021 + hcchar.b.chdis = 1;
2022 + hcchar.b.epdir = 0;
2023 + dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
2024 + }
2025 +
2026 + /* Halt all channels to put them into a known state. */
2027 + for (i = 0; i < num_channels; i++) {
2028 + int count = 0;
2029 + hc_regs = _core_if->host_if->hc_regs[i];
2030 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2031 + hcchar.b.chen = 1;
2032 + hcchar.b.chdis = 1;
2033 + hcchar.b.epdir = 0;
2034 + dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
2035 + DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d\n", __func__, i);
2036 + do {
2037 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2038 + if (++count > 200) {
2039 + DWC_ERROR("%s: Unable to clear halt on channel %d\n",
2040 + __func__, i);
2041 + break;
2042 + }
2043 + udelay(100);
2044 + } while (hcchar.b.chen);
2045 + }
2046 +
2047 + /* Turn on the vbus power. */
2048 + DWC_PRINT("Init: Port Power? op_state=%d\n", _core_if->op_state);
2049 + if (_core_if->op_state == A_HOST){
2050 + hprt0.d32 = dwc_otg_read_hprt0(_core_if);
2051 + DWC_PRINT("Init: Power Port (%d)\n", hprt0.b.prtpwr);
2052 + if (hprt0.b.prtpwr == 0 ) {
2053 + hprt0.b.prtpwr = 1;
2054 + dwc_write_reg32(host_if->hprt0, hprt0.d32);
2055 + }
2056 + }
2057 +
2058 + dwc_otg_enable_host_interrupts( _core_if );
2059 +}
2060 +
2061 +/**
2062 + * Prepares a host channel for transferring packets to/from a specific
2063 + * endpoint. The HCCHARn register is set up with the characteristics specified
2064 + * in _hc. Host channel interrupts that may need to be serviced while this
2065 + * transfer is in progress are enabled.
2066 + *
2067 + * @param _core_if Programming view of DWC_otg controller
2068 + * @param _hc Information needed to initialize the host channel
2069 + */
2070 +void dwc_otg_hc_init(dwc_otg_core_if_t *_core_if, dwc_hc_t *_hc)
2071 +{
2072 + uint32_t intr_enable;
2073 + hcintmsk_data_t hc_intr_mask;
2074 + gintmsk_data_t gintmsk = {.d32 = 0};
2075 + hcchar_data_t hcchar;
2076 + hcsplt_data_t hcsplt;
2077 +
2078 + uint8_t hc_num = _hc->hc_num;
2079 + dwc_otg_host_if_t *host_if = _core_if->host_if;
2080 + dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
2081 +
2082 + /* Clear old interrupt conditions for this host channel. */
2083 + hc_intr_mask.d32 = 0xFFFFFFFF;
2084 + hc_intr_mask.b.reserved = 0;
2085 + dwc_write_reg32(&hc_regs->hcint, hc_intr_mask.d32);
2086 +
2087 + /* Enable channel interrupts required for this transfer. */
2088 + hc_intr_mask.d32 = 0;
2089 + hc_intr_mask.b.chhltd = 1;
2090 + if (_core_if->dma_enable) {
2091 + hc_intr_mask.b.ahberr = 1;
2092 + if (_hc->error_state && !_hc->do_split &&
2093 + _hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
2094 + hc_intr_mask.b.ack = 1;
2095 + if (_hc->ep_is_in) {
2096 + hc_intr_mask.b.datatglerr = 1;
2097 + if (_hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
2098 + hc_intr_mask.b.nak = 1;
2099 + }
2100 + }
2101 + }
2102 + } else {
2103 + switch (_hc->ep_type) {
2104 + case DWC_OTG_EP_TYPE_CONTROL:
2105 + case DWC_OTG_EP_TYPE_BULK:
2106 + hc_intr_mask.b.xfercompl = 1;
2107 + hc_intr_mask.b.stall = 1;
2108 + hc_intr_mask.b.xacterr = 1;
2109 + hc_intr_mask.b.datatglerr = 1;
2110 + if (_hc->ep_is_in) {
2111 + hc_intr_mask.b.bblerr = 1;
2112 + } else {
2113 + hc_intr_mask.b.nak = 1;
2114 + hc_intr_mask.b.nyet = 1;
2115 + if (_hc->do_ping) {
2116 + hc_intr_mask.b.ack = 1;
2117 + }
2118 + }
2119 +
2120 + if (_hc->do_split) {
2121 + hc_intr_mask.b.nak = 1;
2122 + if (_hc->complete_split) {
2123 + hc_intr_mask.b.nyet = 1;
2124 + }
2125 + else {
2126 + hc_intr_mask.b.ack = 1;
2127 + }
2128 + }
2129 +
2130 + if (_hc->error_state) {
2131 + hc_intr_mask.b.ack = 1;
2132 + }
2133 + break;
2134 + case DWC_OTG_EP_TYPE_INTR:
2135 + hc_intr_mask.b.xfercompl = 1;
2136 + hc_intr_mask.b.nak = 1;
2137 + hc_intr_mask.b.stall = 1;
2138 + hc_intr_mask.b.xacterr = 1;
2139 + hc_intr_mask.b.datatglerr = 1;
2140 + hc_intr_mask.b.frmovrun = 1;
2141 +
2142 + if (_hc->ep_is_in) {
2143 + hc_intr_mask.b.bblerr = 1;
2144 + }
2145 + if (_hc->error_state) {
2146 + hc_intr_mask.b.ack = 1;
2147 + }
2148 + if (_hc->do_split) {
2149 + if (_hc->complete_split) {
2150 + hc_intr_mask.b.nyet = 1;
2151 + }
2152 + else {
2153 + hc_intr_mask.b.ack = 1;
2154 + }
2155 + }
2156 + break;
2157 + case DWC_OTG_EP_TYPE_ISOC:
2158 + hc_intr_mask.b.xfercompl = 1;
2159 + hc_intr_mask.b.frmovrun = 1;
2160 + hc_intr_mask.b.ack = 1;
2161 +
2162 + if (_hc->ep_is_in) {
2163 + hc_intr_mask.b.xacterr = 1;
2164 + hc_intr_mask.b.bblerr = 1;
2165 + }
2166 + break;
2167 + }
2168 + }
2169 + dwc_write_reg32(&hc_regs->hcintmsk, hc_intr_mask.d32);
2170 +
2171 + /* Enable the top level host channel interrupt. */
2172 + intr_enable = (1 << hc_num);
2173 + dwc_modify_reg32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
2174 +
2175 + /* Make sure host channel interrupts are enabled. */
2176 + gintmsk.b.hcintr = 1;
2177 + dwc_modify_reg32(&_core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
2178 +
2179 + /*
2180 + * Program the HCCHARn register with the endpoint characteristics for
2181 + * the current transfer.
2182 + */
2183 + hcchar.d32 = 0;
2184 + hcchar.b.devaddr = _hc->dev_addr;
2185 + hcchar.b.epnum = _hc->ep_num;
2186 + hcchar.b.epdir = _hc->ep_is_in;
2187 + hcchar.b.lspddev = (_hc->speed == DWC_OTG_EP_SPEED_LOW);
2188 + hcchar.b.eptype = _hc->ep_type;
2189 + hcchar.b.mps = _hc->max_packet;
2190 +
2191 + dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
2192 +
2193 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _hc->hc_num);
2194 + DWC_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr);
2195 + DWC_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum);
2196 + DWC_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir);
2197 + DWC_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev);
2198 + DWC_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype);
2199 + DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps);
2200 + DWC_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt);
2201 +
2202 + /*
2203 + * Program the HCSPLIT register for SPLITs
2204 + */
2205 + hcsplt.d32 = 0;
2206 + if (_hc->do_split) {
2207 + DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", _hc->hc_num,
2208 + _hc->complete_split ? "CSPLIT" : "SSPLIT");
2209 + hcsplt.b.compsplt = _hc->complete_split;
2210 + hcsplt.b.xactpos = _hc->xact_pos;
2211 + hcsplt.b.hubaddr = _hc->hub_addr;
2212 + hcsplt.b.prtaddr = _hc->port_addr;
2213 + DWC_DEBUGPL(DBG_HCDV, " comp split %d\n", _hc->complete_split);
2214 + DWC_DEBUGPL(DBG_HCDV, " xact pos %d\n", _hc->xact_pos);
2215 + DWC_DEBUGPL(DBG_HCDV, " hub addr %d\n", _hc->hub_addr);
2216 + DWC_DEBUGPL(DBG_HCDV, " port addr %d\n", _hc->port_addr);
2217 + DWC_DEBUGPL(DBG_HCDV, " is_in %d\n", _hc->ep_is_in);
2218 + DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps);
2219 + DWC_DEBUGPL(DBG_HCDV, " xferlen: %d\n", _hc->xfer_len);
2220 + }
2221 + dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
2222 +
2223 +}
2224 +
2225 +/**
2226 + * Attempts to halt a host channel. This function should only be called in
2227 + * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
2228 + * normal circumstances in DMA mode, the controller halts the channel when the
2229 + * transfer is complete or a condition occurs that requires application
2230 + * intervention.
2231 + *
2232 + * In slave mode, checks for a free request queue entry, then sets the Channel
2233 + * Enable and Channel Disable bits of the Host Channel Characteristics
2234 + * register of the specified channel to intiate the halt. If there is no free
2235 + * request queue entry, sets only the Channel Disable bit of the HCCHARn
2236 + * register to flush requests for this channel. In the latter case, sets a
2237 + * flag to indicate that the host channel needs to be halted when a request
2238 + * queue slot is open.
2239 + *
2240 + * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
2241 + * HCCHARn register. The controller ensures there is space in the request
2242 + * queue before submitting the halt request.
2243 + *
2244 + * Some time may elapse before the core flushes any posted requests for this
2245 + * host channel and halts. The Channel Halted interrupt handler completes the
2246 + * deactivation of the host channel.
2247 + *
2248 + * @param _core_if Controller register interface.
2249 + * @param _hc Host channel to halt.
2250 + * @param _halt_status Reason for halting the channel.
2251 + */
2252 +void dwc_otg_hc_halt(dwc_otg_core_if_t *_core_if,
2253 + dwc_hc_t *_hc,
2254 + dwc_otg_halt_status_e _halt_status)
2255 +{
2256 + gnptxsts_data_t nptxsts;
2257 + hptxsts_data_t hptxsts;
2258 + hcchar_data_t hcchar;
2259 + dwc_otg_hc_regs_t *hc_regs;
2260 + dwc_otg_core_global_regs_t *global_regs;
2261 + dwc_otg_host_global_regs_t *host_global_regs;
2262 +
2263 + hc_regs = _core_if->host_if->hc_regs[_hc->hc_num];
2264 + global_regs = _core_if->core_global_regs;
2265 + host_global_regs = _core_if->host_if->host_global_regs;
2266 +
2267 + WARN_ON(_halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS);
2268 +
2269 + if (_halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
2270 + _halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
2271 + /*
2272 + * Disable all channel interrupts except Ch Halted. The QTD
2273 + * and QH state associated with this transfer has been cleared
2274 + * (in the case of URB_DEQUEUE), so the channel needs to be
2275 + * shut down carefully to prevent crashes.
2276 + */
2277 + hcintmsk_data_t hcintmsk;
2278 + hcintmsk.d32 = 0;
2279 + hcintmsk.b.chhltd = 1;
2280 + dwc_write_reg32(&hc_regs->hcintmsk, hcintmsk.d32);
2281 +
2282 + /*
2283 + * Make sure no other interrupts besides halt are currently
2284 + * pending. Handling another interrupt could cause a crash due
2285 + * to the QTD and QH state.
2286 + */
2287 + dwc_write_reg32(&hc_regs->hcint, ~hcintmsk.d32);
2288 +
2289 + /*
2290 + * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
2291 + * even if the channel was already halted for some other
2292 + * reason.
2293 + */
2294 + _hc->halt_status = _halt_status;
2295 +
2296 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2297 + if (hcchar.b.chen == 0) {
2298 + /*
2299 + * The channel is either already halted or it hasn't
2300 + * started yet. In DMA mode, the transfer may halt if
2301 + * it finishes normally or a condition occurs that
2302 + * requires driver intervention. Don't want to halt
2303 + * the channel again. In either Slave or DMA mode,
2304 + * it's possible that the transfer has been assigned
2305 + * to a channel, but not started yet when an URB is
2306 + * dequeued. Don't want to halt a channel that hasn't
2307 + * started yet.
2308 + */
2309 + return;
2310 + }
2311 + }
2312 +
2313 + if (_hc->halt_pending) {
2314 + /*
2315 + * A halt has already been issued for this channel. This might
2316 + * happen when a transfer is aborted by a higher level in
2317 + * the stack.
2318 + */
2319 +#ifdef DEBUG
2320 + DWC_PRINT("*** %s: Channel %d, _hc->halt_pending already set ***\n",
2321 + __func__, _hc->hc_num);
2322 +
2323 +/* dwc_otg_dump_global_registers(_core_if); */
2324 +/* dwc_otg_dump_host_registers(_core_if); */
2325 +#endif
2326 + return;
2327 + }
2328 +
2329 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2330 + hcchar.b.chen = 1;
2331 + hcchar.b.chdis = 1;
2332 +
2333 + if (!_core_if->dma_enable) {
2334 + /* Check for space in the request queue to issue the halt. */
2335 + if (_hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
2336 + _hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
2337 + nptxsts.d32 = dwc_read_reg32(&global_regs->gnptxsts);
2338 + if (nptxsts.b.nptxqspcavail == 0) {
2339 + hcchar.b.chen = 0;
2340 + }
2341 + } else {
2342 + hptxsts.d32 = dwc_read_reg32(&host_global_regs->hptxsts);
2343 + if ((hptxsts.b.ptxqspcavail == 0) || (_core_if->queuing_high_bandwidth)) {
2344 + hcchar.b.chen = 0;
2345 + }
2346 + }
2347 + }
2348 +
2349 + dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
2350 +
2351 + _hc->halt_status = _halt_status;
2352 +
2353 + if (hcchar.b.chen) {
2354 + _hc->halt_pending = 1;
2355 + _hc->halt_on_queue = 0;
2356 + } else {
2357 + _hc->halt_on_queue = 1;
2358 + }
2359 +
2360 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _hc->hc_num);
2361 + DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32);
2362 + DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", _hc->halt_pending);
2363 + DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", _hc->halt_on_queue);
2364 + DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", _hc->halt_status);
2365 +
2366 + return;
2367 +}
2368 +
2369 +/**
2370 + * Clears the transfer state for a host channel. This function is normally
2371 + * called after a transfer is done and the host channel is being released.
2372 + *
2373 + * @param _core_if Programming view of DWC_otg controller.
2374 + * @param _hc Identifies the host channel to clean up.
2375 + */
2376 +void dwc_otg_hc_cleanup(dwc_otg_core_if_t *_core_if, dwc_hc_t *_hc)
2377 +{
2378 + dwc_otg_hc_regs_t *hc_regs;
2379 +
2380 + _hc->xfer_started = 0;
2381 +
2382 + /*
2383 + * Clear channel interrupt enables and any unhandled channel interrupt
2384 + * conditions.
2385 + */
2386 + hc_regs = _core_if->host_if->hc_regs[_hc->hc_num];
2387 + dwc_write_reg32(&hc_regs->hcintmsk, 0);
2388 + dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF);
2389 +
2390 +#ifdef DEBUG
2391 + del_timer(&_core_if->hc_xfer_timer[_hc->hc_num]);
2392 + {
2393 + hcchar_data_t hcchar;
2394 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2395 + if (hcchar.b.chdis) {
2396 + DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
2397 + __func__, _hc->hc_num, hcchar.d32);
2398 + }
2399 + }
2400 +#endif
2401 +}
2402 +
2403 +/**
2404 + * Sets the channel property that indicates in which frame a periodic transfer
2405 + * should occur. This is always set to the _next_ frame. This function has no
2406 + * effect on non-periodic transfers.
2407 + *
2408 + * @param _core_if Programming view of DWC_otg controller.
2409 + * @param _hc Identifies the host channel to set up and its properties.
2410 + * @param _hcchar Current value of the HCCHAR register for the specified host
2411 + * channel.
2412 + */
2413 +static inline void hc_set_even_odd_frame(dwc_otg_core_if_t *_core_if,
2414 + dwc_hc_t *_hc,
2415 + hcchar_data_t *_hcchar)
2416 +{
2417 + if (_hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
2418 + _hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
2419 + hfnum_data_t hfnum;
2420 + hfnum.d32 = dwc_read_reg32(&_core_if->host_if->host_global_regs->hfnum);
2421 + /* 1 if _next_ frame is odd, 0 if it's even */
2422 + _hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
2423 +#ifdef DEBUG
2424 + if (_hc->ep_type == DWC_OTG_EP_TYPE_INTR && _hc->do_split && !_hc->complete_split) {
2425 + switch (hfnum.b.frnum & 0x7) {
2426 + case 7:
2427 + _core_if->hfnum_7_samples++;
2428 + _core_if->hfnum_7_frrem_accum += hfnum.b.frrem;
2429 + break;
2430 + case 0:
2431 + _core_if->hfnum_0_samples++;
2432 + _core_if->hfnum_0_frrem_accum += hfnum.b.frrem;
2433 + break;
2434 + default:
2435 + _core_if->hfnum_other_samples++;
2436 + _core_if->hfnum_other_frrem_accum += hfnum.b.frrem;
2437 + break;
2438 + }
2439 + }
2440 +#endif
2441 + }
2442 +}
2443 +
2444 +#ifdef DEBUG
2445 +static void hc_xfer_timeout(unsigned long _ptr)
2446 +{
2447 + hc_xfer_info_t *xfer_info = (hc_xfer_info_t *)_ptr;
2448 + int hc_num = xfer_info->hc->hc_num;
2449 + DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);
2450 + DWC_WARN(" start_hcchar_val 0x%08x\n", xfer_info->core_if->start_hcchar_val[hc_num]);
2451 +}
2452 +#endif
2453 +
2454 +/*
2455 + * This function does the setup for a data transfer for a host channel and
2456 + * starts the transfer. May be called in either Slave mode or DMA mode. In
2457 + * Slave mode, the caller must ensure that there is sufficient space in the
2458 + * request queue and Tx Data FIFO.
2459 + *
2460 + * For an OUT transfer in Slave mode, it loads a data packet into the
2461 + * appropriate FIFO. If necessary, additional data packets will be loaded in
2462 + * the Host ISR.
2463 + *
2464 + * For an IN transfer in Slave mode, a data packet is requested. The data
2465 + * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
2466 + * additional data packets are requested in the Host ISR.
2467 + *
2468 + * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
2469 + * register along with a packet count of 1 and the channel is enabled. This
2470 + * causes a single PING transaction to occur. Other fields in HCTSIZ are
2471 + * simply set to 0 since no data transfer occurs in this case.
2472 + *
2473 + * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
2474 + * all the information required to perform the subsequent data transfer. In
2475 + * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
2476 + * controller performs the entire PING protocol, then starts the data
2477 + * transfer.
2478 + *
2479 + * @param _core_if Programming view of DWC_otg controller.
2480 + * @param _hc Information needed to initialize the host channel. The xfer_len
2481 + * value may be reduced to accommodate the max widths of the XferSize and
2482 + * PktCnt fields in the HCTSIZn register. The multi_count value may be changed
2483 + * to reflect the final xfer_len value.
2484 + */
2485 +void dwc_otg_hc_start_transfer(dwc_otg_core_if_t *_core_if, dwc_hc_t *_hc)
2486 +{
2487 + hcchar_data_t hcchar;
2488 + hctsiz_data_t hctsiz;
2489 + uint16_t num_packets;
2490 + uint32_t max_hc_xfer_size = _core_if->core_params->max_transfer_size;
2491 + uint16_t max_hc_pkt_count = _core_if->core_params->max_packet_count;
2492 + dwc_otg_hc_regs_t *hc_regs = _core_if->host_if->hc_regs[_hc->hc_num];
2493 +
2494 + hctsiz.d32 = 0;
2495 +
2496 + if (_hc->do_ping) {
2497 + if (!_core_if->dma_enable) {
2498 + dwc_otg_hc_do_ping(_core_if, _hc);
2499 + _hc->xfer_started = 1;
2500 + return;
2501 + } else {
2502 + hctsiz.b.dopng = 1;
2503 + }
2504 + }
2505 +
2506 + if (_hc->do_split) {
2507 + num_packets = 1;
2508 +
2509 + if (_hc->complete_split && !_hc->ep_is_in) {
2510 + /* For CSPLIT OUT Transfer, set the size to 0 so the
2511 + * core doesn't expect any data written to the FIFO */
2512 + _hc->xfer_len = 0;
2513 + } else if (_hc->ep_is_in || (_hc->xfer_len > _hc->max_packet)) {
2514 + _hc->xfer_len = _hc->max_packet;
2515 + } else if (!_hc->ep_is_in && (_hc->xfer_len > 188)) {
2516 + _hc->xfer_len = 188;
2517 + }
2518 +
2519 + hctsiz.b.xfersize = _hc->xfer_len;
2520 + } else {
2521 + /*
2522 + * Ensure that the transfer length and packet count will fit
2523 + * in the widths allocated for them in the HCTSIZn register.
2524 + */
2525 + if (_hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
2526 + _hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
2527 + /*
2528 + * Make sure the transfer size is no larger than one
2529 + * (micro)frame's worth of data. (A check was done
2530 + * when the periodic transfer was accepted to ensure
2531 + * that a (micro)frame's worth of data can be
2532 + * programmed into a channel.)
2533 + */
2534 + uint32_t max_periodic_len = _hc->multi_count * _hc->max_packet;
2535 + if (_hc->xfer_len > max_periodic_len) {
2536 + _hc->xfer_len = max_periodic_len;
2537 + } else {
2538 + }
2539 + } else if (_hc->xfer_len > max_hc_xfer_size) {
2540 + /* Make sure that xfer_len is a multiple of max packet size. */
2541 + _hc->xfer_len = max_hc_xfer_size - _hc->max_packet + 1;
2542 + }
2543 +
2544 + if (_hc->xfer_len > 0) {
2545 + num_packets = (_hc->xfer_len + _hc->max_packet - 1) / _hc->max_packet;
2546 + if (num_packets > max_hc_pkt_count) {
2547 + num_packets = max_hc_pkt_count;
2548 + _hc->xfer_len = num_packets * _hc->max_packet;
2549 + }
2550 + } else {
2551 + /* Need 1 packet for transfer length of 0. */
2552 + num_packets = 1;
2553 + }
2554 +
2555 + if (_hc->ep_is_in) {
2556 + /* Always program an integral # of max packets for IN transfers. */
2557 + _hc->xfer_len = num_packets * _hc->max_packet;
2558 + }
2559 +
2560 + if (_hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
2561 + _hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
2562 + /*
2563 + * Make sure that the multi_count field matches the
2564 + * actual transfer length.
2565 + */
2566 + _hc->multi_count = num_packets;
2567 +
2568 + }
2569 +
2570 + if (_hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
2571 + /* Set up the initial PID for the transfer. */
2572 + if (_hc->speed == DWC_OTG_EP_SPEED_HIGH) {
2573 + if (_hc->ep_is_in) {
2574 + if (_hc->multi_count == 1) {
2575 + _hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
2576 + } else if (_hc->multi_count == 2) {
2577 + _hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
2578 + } else {
2579 + _hc->data_pid_start = DWC_OTG_HC_PID_DATA2;
2580 + }
2581 + } else {
2582 + if (_hc->multi_count == 1) {
2583 + _hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
2584 + } else {
2585 + _hc->data_pid_start = DWC_OTG_HC_PID_MDATA;
2586 + }
2587 + }
2588 + } else {
2589 + _hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
2590 + }
2591 + }
2592 +
2593 + hctsiz.b.xfersize = _hc->xfer_len;
2594 + }
2595 +
2596 + _hc->start_pkt_count = num_packets;
2597 + hctsiz.b.pktcnt = num_packets;
2598 + hctsiz.b.pid = _hc->data_pid_start;
2599 + dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
2600 +
2601 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _hc->hc_num);
2602 + DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize);
2603 + DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt);
2604 + DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
2605 +
2606 + if (_core_if->dma_enable) {
2607 +#ifdef DEBUG
2608 +if(((uint32_t)_hc->xfer_buff)%4)
2609 +printk("dwc_otg_hc_start_transfer _hc->xfer_buff not 4 byte alignment\n");
2610 +#endif
2611 + dwc_write_reg32(&hc_regs->hcdma, (uint32_t)_hc->xfer_buff);
2612 + }
2613 +
2614 + /* Start the split */
2615 + if (_hc->do_split) {
2616 + hcsplt_data_t hcsplt;
2617 + hcsplt.d32 = dwc_read_reg32 (&hc_regs->hcsplt);
2618 + hcsplt.b.spltena = 1;
2619 + dwc_write_reg32(&hc_regs->hcsplt, hcsplt.d32);
2620 + }
2621 +
2622 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2623 + hcchar.b.multicnt = _hc->multi_count;
2624 + hc_set_even_odd_frame(_core_if, _hc, &hcchar);
2625 +#ifdef DEBUG
2626 + _core_if->start_hcchar_val[_hc->hc_num] = hcchar.d32;
2627 + if (hcchar.b.chdis) {
2628 + DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
2629 + __func__, _hc->hc_num, hcchar.d32);
2630 + }
2631 +#endif
2632 +
2633 + /* Set host channel enable after all other setup is complete. */
2634 + hcchar.b.chen = 1;
2635 + hcchar.b.chdis = 0;
2636 + dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
2637 +
2638 + _hc->xfer_started = 1;
2639 + _hc->requests++;
2640 +
2641 + if (!_core_if->dma_enable && !_hc->ep_is_in && _hc->xfer_len > 0) {
2642 + /* Load OUT packet into the appropriate Tx FIFO. */
2643 + dwc_otg_hc_write_packet(_core_if, _hc);
2644 + }
2645 +
2646 +#ifdef DEBUG
2647 + /* Start a timer for this transfer. */
2648 + _core_if->hc_xfer_timer[_hc->hc_num].function = hc_xfer_timeout;
2649 + _core_if->hc_xfer_info[_hc->hc_num].core_if = _core_if;
2650 + _core_if->hc_xfer_info[_hc->hc_num].hc = _hc;
2651 + _core_if->hc_xfer_timer[_hc->hc_num].data = (unsigned long)(&_core_if->hc_xfer_info[_hc->hc_num]);
2652 + _core_if->hc_xfer_timer[_hc->hc_num].expires = jiffies + (HZ*10);
2653 + add_timer(&_core_if->hc_xfer_timer[_hc->hc_num]);
2654 +#endif
2655 +}
2656 +
2657 +/**
2658 + * This function continues a data transfer that was started by previous call
2659 + * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is
2660 + * sufficient space in the request queue and Tx Data FIFO. This function
2661 + * should only be called in Slave mode. In DMA mode, the controller acts
2662 + * autonomously to complete transfers programmed to a host channel.
2663 + *
2664 + * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
2665 + * if there is any data remaining to be queued. For an IN transfer, another
2666 + * data packet is always requested. For the SETUP phase of a control transfer,
2667 + * this function does nothing.
2668 + *
2669 + * @return 1 if a new request is queued, 0 if no more requests are required
2670 + * for this transfer.
2671 + */
2672 +int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t *_core_if, dwc_hc_t *_hc)
2673 +{
2674 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _hc->hc_num);
2675 +
2676 + if (_hc->do_split) {
2677 + /* SPLITs always queue just once per channel */
2678 + return 0;
2679 + } else if (_hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
2680 + /* SETUPs are queued only once since they can't be NAKed. */
2681 + return 0;
2682 + } else if (_hc->ep_is_in) {
2683 + /*
2684 + * Always queue another request for other IN transfers. If
2685 + * back-to-back INs are issued and NAKs are received for both,
2686 + * the driver may still be processing the first NAK when the
2687 + * second NAK is received. When the interrupt handler clears
2688 + * the NAK interrupt for the first NAK, the second NAK will
2689 + * not be seen. So we can't depend on the NAK interrupt
2690 + * handler to requeue a NAKed request. Instead, IN requests
2691 + * are issued each time this function is called. When the
2692 + * transfer completes, the extra requests for the channel will
2693 + * be flushed.
2694 + */
2695 + hcchar_data_t hcchar;
2696 + dwc_otg_hc_regs_t *hc_regs = _core_if->host_if->hc_regs[_hc->hc_num];
2697 +
2698 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2699 + hc_set_even_odd_frame(_core_if, _hc, &hcchar);
2700 + hcchar.b.chen = 1;
2701 + hcchar.b.chdis = 0;
2702 + DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", hcchar.d32);
2703 + dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
2704 + _hc->requests++;
2705 + return 1;
2706 + } else {
2707 + /* OUT transfers. */
2708 + if (_hc->xfer_count < _hc->xfer_len) {
2709 + if (_hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
2710 + _hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
2711 + hcchar_data_t hcchar;
2712 + dwc_otg_hc_regs_t *hc_regs;
2713 + hc_regs = _core_if->host_if->hc_regs[_hc->hc_num];
2714 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2715 + hc_set_even_odd_frame(_core_if, _hc, &hcchar);
2716 + }
2717 +
2718 + /* Load OUT packet into the appropriate Tx FIFO. */
2719 + dwc_otg_hc_write_packet(_core_if, _hc);
2720 + _hc->requests++;
2721 + return 1;
2722 + } else {
2723 + return 0;
2724 + }
2725 + }
2726 +}
2727 +
2728 +/**
2729 + * Starts a PING transfer. This function should only be called in Slave mode.
2730 + * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
2731 + */
2732 +void dwc_otg_hc_do_ping(dwc_otg_core_if_t *_core_if, dwc_hc_t *_hc)
2733 +{
2734 + hcchar_data_t hcchar;
2735 + hctsiz_data_t hctsiz;
2736 + dwc_otg_hc_regs_t *hc_regs = _core_if->host_if->hc_regs[_hc->hc_num];
2737 +
2738 + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _hc->hc_num);
2739 +
2740 + hctsiz.d32 = 0;
2741 + hctsiz.b.dopng = 1;
2742 + hctsiz.b.pktcnt = 1;
2743 + dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
2744 +
2745 + hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
2746 + hcchar.b.chen = 1;
2747 + hcchar.b.chdis = 0;
2748 + dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
2749 +}
2750 +
2751 +/*
2752 + * This function writes a packet into the Tx FIFO associated with the Host
2753 + * Channel. For a channel associated with a non-periodic EP, the non-periodic
2754 + * Tx FIFO is written. For a channel associated with a periodic EP, the
2755 + * periodic Tx FIFO is written. This function should only be called in Slave
2756 + * mode.
2757 + *
2758 + * Upon return the xfer_buff and xfer_count fields in _hc are incremented by
2759 + * then number of bytes written to the Tx FIFO.
2760 + */
2761 +void dwc_otg_hc_write_packet(dwc_otg_core_if_t *_core_if, dwc_hc_t *_hc)
2762 +{
2763 + uint32_t i;
2764 + uint32_t remaining_count;
2765 + uint32_t byte_count;
2766 + uint32_t dword_count;
2767 +
2768 + uint32_t *data_buff = (uint32_t *)(_hc->xfer_buff);
2769 + uint32_t *data_fifo = _core_if->data_fifo[_hc->hc_num];
2770 +
2771 + remaining_count = _hc->xfer_len - _hc->xfer_count;
2772 + if (remaining_count > _hc->max_packet) {
2773 + byte_count = _hc->max_packet;
2774 + } else {
2775 + byte_count = remaining_count;
2776 + }
2777 +
2778 + dword_count = (byte_count + 3) / 4;
2779 +
2780 + if ((((unsigned long)data_buff) & 0x3) == 0) {
2781 + /* xfer_buff is DWORD aligned. */
2782 + for (i = 0; i < dword_count; i++, data_buff++) {
2783 + dwc_write_reg32(data_fifo, *data_buff);
2784 + }
2785 + } else {
2786 + /* xfer_buff is not DWORD aligned. */
2787 + for (i = 0; i < dword_count; i++, data_buff++) {
2788 + dwc_write_reg32(data_fifo, get_unaligned(data_buff));
2789 + }
2790 + }
2791 +
2792 + _hc->xfer_count += byte_count;
2793 + _hc->xfer_buff += byte_count;
2794 +}
2795 +
2796 +/**
2797 + * Gets the current USB frame number. This is the frame number from the last
2798 + * SOF packet.
2799 + */
2800 +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t *_core_if)
2801 +{
2802 + dsts_data_t dsts;
2803 + dsts.d32 = dwc_read_reg32(&_core_if->dev_if->dev_global_regs->dsts);
2804 +
2805 + /* read current frame/microfreme number from DSTS register */
2806 + return dsts.b.soffn;
2807 +}
2808 +
2809 +/**
2810 + * This function reads a setup packet from the Rx FIFO into the destination
2811 + * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
2812 + * Interrupt routine when a SETUP packet has been received in Slave mode.
2813 + *
2814 + * @param _core_if Programming view of DWC_otg controller.
2815 + * @param _dest Destination buffer for packet data.
2816 + */
2817 +void dwc_otg_read_setup_packet(dwc_otg_core_if_t *_core_if, uint32_t *_dest)
2818 +{
2819 + /* Get the 8 bytes of a setup transaction data */
2820 +
2821 + /* Pop 2 DWORDS off the receive data FIFO into memory */
2822 + _dest[0] = dwc_read_reg32(_core_if->data_fifo[0]);
2823 + _dest[1] = dwc_read_reg32(_core_if->data_fifo[0]);
2824 + //_dest[0] = dwc_read_datafifo32(_core_if->data_fifo[0]);
2825 + //_dest[1] = dwc_read_datafifo32(_core_if->data_fifo[0]);
2826 +}
2827 +
2828 +
2829 +/**
2830 + * This function enables EP0 OUT to receive SETUP packets and configures EP0
2831 + * IN for transmitting packets. It is normally called when the
2832 + * "Enumeration Done" interrupt occurs.
2833 + *
2834 + * @param _core_if Programming view of DWC_otg controller.
2835 + * @param _ep The EP0 data.
2836 + */
2837 +void dwc_otg_ep0_activate(dwc_otg_core_if_t *_core_if, dwc_ep_t *_ep)
2838 +{
2839 + dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
2840 + dsts_data_t dsts;
2841 + depctl_data_t diepctl;
2842 + depctl_data_t doepctl;
2843 + dctl_data_t dctl ={.d32=0};
2844 +
2845 + /* Read the Device Status and Endpoint 0 Control registers */
2846 + dsts.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dsts);
2847 + diepctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl);
2848 + doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl);
2849 +
2850 + /* Set the MPS of the IN EP based on the enumeration speed */
2851 + switch (dsts.b.enumspd) {
2852 + case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
2853 + case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
2854 + case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
2855 + diepctl.b.mps = DWC_DEP0CTL_MPS_64;
2856 + break;
2857 + case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
2858 + diepctl.b.mps = DWC_DEP0CTL_MPS_8;
2859 + break;
2860 + }
2861 +
2862 + dwc_write_reg32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
2863 +
2864 + /* Enable OUT EP for receive */
2865 + doepctl.b.epena = 1;
2866 + dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
2867 +
2868 +#ifdef VERBOSE
2869 + DWC_DEBUGPL(DBG_PCDV,"doepctl0=%0x\n",
2870 + dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));
2871 + DWC_DEBUGPL(DBG_PCDV,"diepctl0=%0x\n",
2872 + dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl));
2873 +#endif
2874 + dctl.b.cgnpinnak = 1;
2875 + dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
2876 + DWC_DEBUGPL(DBG_PCDV,"dctl=%0x\n",
2877 + dwc_read_reg32(&dev_if->dev_global_regs->dctl));
2878 +}
2879 +
2880 +/**
2881 + * This function activates an EP. The Device EP control register for
2882 + * the EP is configured as defined in the ep structure. Note: This
2883 + * function is not used for EP0.
2884 + *
2885 + * @param _core_if Programming view of DWC_otg controller.
2886 + * @param _ep The EP to activate.
2887 + */
2888 +void dwc_otg_ep_activate(dwc_otg_core_if_t *_core_if, dwc_ep_t *_ep)
2889 +{
2890 + dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
2891 + depctl_data_t depctl;
2892 + volatile uint32_t *addr;
2893 + daint_data_t daintmsk = {.d32=0};
2894 +
2895 + DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, _ep->num,
2896 + (_ep->is_in?"IN":"OUT"));
2897 +
2898 + /* Read DEPCTLn register */
2899 + if (_ep->is_in == 1) {
2900 + addr = &dev_if->in_ep_regs[_ep->num]->diepctl;
2901 + daintmsk.ep.in = 1<<_ep->num;
2902 + } else {
2903 + addr = &dev_if->out_ep_regs[_ep->num]->doepctl;
2904 + daintmsk.ep.out = 1<<_ep->num;
2905 + }
2906 +
2907 + /* If the EP is already active don't change the EP Control
2908 + * register. */
2909 + depctl.d32 = dwc_read_reg32(addr);
2910 + if (!depctl.b.usbactep) {
2911 + depctl.b.mps = _ep->maxpacket;
2912 + depctl.b.eptype = _ep->type;
2913 + depctl.b.txfnum = _ep->tx_fifo_num;
2914 +
2915 + if (_ep->type == DWC_OTG_EP_TYPE_ISOC) {
2916 + depctl.b.setd0pid = 1; // ???
2917 + } else {
2918 + depctl.b.setd0pid = 1;
2919 + }
2920 + depctl.b.usbactep = 1;
2921 +
2922 + dwc_write_reg32(addr, depctl.d32);
2923 + DWC_DEBUGPL(DBG_PCDV,"DEPCTL=%08x\n", dwc_read_reg32(addr));
2924 + }
2925 +
2926 +
2927 + /* Enable the Interrupt for this EP */
2928 + dwc_modify_reg32(&dev_if->dev_global_regs->daintmsk,
2929 + 0, daintmsk.d32);
2930 + DWC_DEBUGPL(DBG_PCDV,"DAINTMSK=%0x\n",
2931 + dwc_read_reg32(&dev_if->dev_global_regs->daintmsk));
2932 + _ep->stall_clear_flag = 0;
2933 + return;
2934 +}
2935 +
2936 +/**
2937 + * This function deactivates an EP. This is done by clearing the USB Active
2938 + * EP bit in the Device EP control register. Note: This function is not used
2939 + * for EP0. EP0 cannot be deactivated.
2940 + *
2941 + * @param _core_if Programming view of DWC_otg controller.
2942 + * @param _ep The EP to deactivate.
2943 + */
2944 +void dwc_otg_ep_deactivate(dwc_otg_core_if_t *_core_if, dwc_ep_t *_ep)
2945 +{
2946 + depctl_data_t depctl ={.d32 = 0};
2947 + volatile uint32_t *addr;
2948 + daint_data_t daintmsk = {.d32=0};
2949 +
2950 + /* Read DEPCTLn register */
2951 + if (_ep->is_in == 1) {
2952 + addr = &_core_if->dev_if->in_ep_regs[_ep->num]->diepctl;
2953 + daintmsk.ep.in = 1<<_ep->num;
2954 + } else {
2955 + addr = &_core_if->dev_if->out_ep_regs[_ep->num]->doepctl;
2956 + daintmsk.ep.out = 1<<_ep->num;
2957 + }
2958 +
2959 + depctl.b.usbactep = 0;
2960 + dwc_write_reg32(addr, depctl.d32);
2961 +
2962 + /* Disable the Interrupt for this EP */
2963 + dwc_modify_reg32(&_core_if->dev_if->dev_global_regs->daintmsk,
2964 + daintmsk.d32, 0);
2965 +
2966 + return;
2967 +}
2968 +
2969 +/**
2970 + * This function does the setup for a data transfer for an EP and
2971 + * starts the transfer. For an IN transfer, the packets will be
2972 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
2973 + * the packets are unloaded from the Rx FIFO in the ISR. the ISR.
2974 + *
2975 + * @param _core_if Programming view of DWC_otg controller.
2976 + * @param _ep The EP to start the transfer on.
2977 + */
2978 +void dwc_otg_ep_start_transfer(dwc_otg_core_if_t *_core_if, dwc_ep_t *_ep)
2979 +{
2980 + /** @todo Refactor this funciton to check the transfer size
2981 + * count value does not execed the number bits in the Transfer
2982 + * count register. */
2983 + depctl_data_t depctl;
2984 + deptsiz_data_t deptsiz;
2985 + gintmsk_data_t intr_mask = { .d32 = 0};
2986 +
2987 +#ifdef CHECK_PACKET_COUNTER_WIDTH
2988 + const uint32_t MAX_XFER_SIZE =
2989 + _core_if->core_params->max_transfer_size;
2990 + const uint32_t MAX_PKT_COUNT =
2991 + _core_if->core_params->max_packet_count;
2992 + uint32_t num_packets;
2993 + uint32_t transfer_len;
2994 + dwc_otg_dev_out_ep_regs_t *out_regs =
2995 + _core_if->dev_if->out_ep_regs[_ep->num];
2996 + dwc_otg_dev_in_ep_regs_t *in_regs =
2997 + _core_if->dev_if->in_ep_regs[_ep->num];
2998 + gnptxsts_data_t txstatus;
2999 +
3000 + int lvl = SET_DEBUG_LEVEL(DBG_PCD);
3001 +
3002 +
3003 + DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
3004 + "xfer_buff=%p start_xfer_buff=%p\n",
3005 + _ep->num, (_ep->is_in?"IN":"OUT"), _ep->xfer_len,
3006 + _ep->xfer_count, _ep->xfer_buff, _ep->start_xfer_buff);
3007 +
3008 + transfer_len = _ep->xfer_len - _ep->xfer_count;
3009 + if (transfer_len > MAX_XFER_SIZE) {
3010 + transfer_len = MAX_XFER_SIZE;
3011 + }
3012 + if (transfer_len == 0) {
3013 + num_packets = 1;
3014 + /* OUT EP to recieve Zero-length packet set transfer
3015 + * size to maxpacket size. */
3016 + if (!_ep->is_in) {
3017 + transfer_len = _ep->maxpacket;
3018 + }
3019 + } else {
3020 + num_packets =
3021 + (transfer_len + _ep->maxpacket - 1) / _ep->maxpacket;
3022 + if (num_packets > MAX_PKT_COUNT) {
3023 + num_packets = MAX_PKT_COUNT;
3024 + }
3025 + }
3026 + DWC_DEBUGPL(DBG_PCD, "transfer_len=%d #pckt=%d\n", transfer_len,
3027 + num_packets);
3028 +
3029 + deptsiz.b.xfersize = transfer_len;
3030 + deptsiz.b.pktcnt = num_packets;
3031 +
3032 + /* IN endpoint */
3033 + if (_ep->is_in == 1) {
3034 + depctl.d32 = dwc_read_reg32(&in_regs->diepctl);
3035 + } else {/* OUT endpoint */
3036 + depctl.d32 = dwc_read_reg32(&out_regs->doepctl);
3037 + }
3038 +
3039 + /* EP enable, IN data in FIFO */
3040 + depctl.b.cnak = 1;
3041 + depctl.b.epena = 1;
3042 + /* IN endpoint */
3043 + if (_ep->is_in == 1) {
3044 + txstatus.d32 =
3045 + dwc_read_reg32(&_core_if->core_global_regs->gnptxsts);
3046 + if (txstatus.b.nptxqspcavail == 0) {
3047 + DWC_DEBUGPL(DBG_ANY, "TX Queue Full (0x%0x)\n",
3048 + txstatus.d32);
3049 + return;
3050 + }
3051 + dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
3052 + dwc_write_reg32(&in_regs->diepctl, depctl.d32);
3053 + /**
3054 + * Enable the Non-Periodic Tx FIFO empty interrupt, the
3055 + * data will be written into the fifo by the ISR.
3056 + */
3057 + if (_core_if->dma_enable) {
3058 + dwc_write_reg32(&in_regs->diepdma, (uint32_t) _ep->xfer_buff);
3059 + } else {
3060 + if (_core_if->en_multiple_tx_fifo == 0) {
3061 + intr_mask.b.nptxfempty = 1;
3062 + dwc_modify_reg32( &_core_if->core_global_regs->gintsts,
3063 + intr_mask.d32, 0);
3064 + dwc_modify_reg32( &_core_if->core_global_regs->gintmsk,
3065 + intr_mask.d32, intr_mask.d32);
3066 + } else {
3067 + /* Enable the Tx FIFO Empty Interrupt for this EP */
3068 + if (_ep->xfer_len > 0 &&
3069 + _ep->type != DWC_OTG_EP_TYPE_ISOC) {
3070 + uint32_t fifoemptymsk = 0;
3071 + fifoemptymsk = (0x1 << _ep->num);
3072 + dwc_modify_reg32(&_core_if->dev_if->dev_global_regs->
3073 + dtknqr4_fifoemptymsk,0, fifoemptymsk);
3074 + }
3075 + }
3076 + }
3077 + } else { /* OUT endpoint */
3078 + dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
3079 + dwc_write_reg32(&out_regs->doepctl, depctl.d32);
3080 + if (_core_if->dma_enable) {
3081 + dwc_write_reg32(&out_regs->doepdma,(uint32_t) _ep->xfer_buff);
3082 + }
3083 + }
3084 + DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
3085 + dwc_read_reg32(&out_regs->doepctl),
3086 + dwc_read_reg32(&out_regs->doeptsiz));
3087 + DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
3088 + dwc_read_reg32(&_core_if->dev_if->dev_global_regs->daintmsk),
3089 + dwc_read_reg32(&_core_if->core_global_regs->gintmsk));
3090 +
3091 + SET_DEBUG_LEVEL(lvl);
3092 +#endif
3093 + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
3094 +
3095 + DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
3096 + "xfer_buff=%p start_xfer_buff=%p\n",
3097 + _ep->num, (_ep->is_in?"IN":"OUT"), _ep->xfer_len,
3098 + _ep->xfer_count, _ep->xfer_buff, _ep->start_xfer_buff);
3099 +
3100 + /* IN endpoint */
3101 + if (_ep->is_in == 1) {
3102 + dwc_otg_dev_in_ep_regs_t * in_regs = _core_if->dev_if->in_ep_regs[_ep->num];
3103 + gnptxsts_data_t gtxstatus;
3104 + gtxstatus.d32 = dwc_read_reg32(&_core_if->core_global_regs->gnptxsts);
3105 + if (_core_if->en_multiple_tx_fifo == 0 &&
3106 + gtxstatus.b.nptxqspcavail == 0) {
3107 +#ifdef DEBUG
3108 + DWC_PRINT("TX Queue Full (0x%0x)\n", gtxstatus.d32);
3109 +#endif
3110 + //return;
3111 + MDELAY(100); //james
3112 + }
3113 +
3114 + depctl.d32 = dwc_read_reg32(&(in_regs->diepctl));
3115 + deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz));
3116 +
3117 + /* Zero Length Packet? */
3118 + if (_ep->xfer_len == 0) {
3119 + deptsiz.b.xfersize = 0;
3120 + deptsiz.b.pktcnt = 1;
3121 + } else {
3122 +
3123 + /* Program the transfer size and packet count
3124 + * as follows: xfersize = N * maxpacket +
3125 + * short_packet pktcnt = N + (short_packet
3126 + * exist ? 1 : 0)
3127 + */
3128 + deptsiz.b.xfersize = _ep->xfer_len;
3129 + deptsiz.b.pktcnt = (_ep->xfer_len - 1 + _ep->maxpacket) / _ep->maxpacket;
3130 + }
3131 +
3132 + dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
3133 +
3134 + /* Write the DMA register */
3135 + if (_core_if->dma_enable) {
3136 +#if 1 // winder
3137 + dma_cache_wback_inv((unsigned long) _ep->xfer_buff, _ep->xfer_len); // winder
3138 + dwc_write_reg32 (&(in_regs->diepdma),
3139 + CPHYSADDR((uint32_t)_ep->xfer_buff)); // winder
3140 +#else
3141 + dwc_write_reg32 (&(in_regs->diepdma),
3142 + (uint32_t)_ep->dma_addr);
3143 +#endif
3144 + } else {
3145 + if (_ep->type != DWC_OTG_EP_TYPE_ISOC) {
3146 + /**
3147 + * Enable the Non-Periodic Tx FIFO empty interrupt,
3148 + * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
3149 + * the data will be written into the fifo by the ISR.
3150 + */
3151 + if (_core_if->en_multiple_tx_fifo == 0) {
3152 + intr_mask.b.nptxfempty = 1;
3153 + dwc_modify_reg32( &_core_if->core_global_regs->gintsts,
3154 + intr_mask.d32, 0);
3155 + dwc_modify_reg32( &_core_if->core_global_regs->gintmsk,
3156 + intr_mask.d32, intr_mask.d32);
3157 + } else {
3158 + /* Enable the Tx FIFO Empty Interrupt for this EP */
3159 + if (_ep->xfer_len > 0) {
3160 + uint32_t fifoemptymsk = 0;
3161 + fifoemptymsk = 1 << _ep->num;
3162 + dwc_modify_reg32(&_core_if->dev_if->dev_global_regs->
3163 + dtknqr4_fifoemptymsk,0,fifoemptymsk);
3164 + }
3165 + }
3166 + }
3167 + }
3168 +
3169 + /* EP enable, IN data in FIFO */
3170 + depctl.b.cnak = 1;
3171 + depctl.b.epena = 1;
3172 + dwc_write_reg32(&in_regs->diepctl, depctl.d32);
3173 +
3174 + if (_core_if->dma_enable) {
3175 + depctl.d32 = dwc_read_reg32 (&_core_if->dev_if->in_ep_regs[0]->diepctl);
3176 + depctl.b.nextep = _ep->num;
3177 + dwc_write_reg32 (&_core_if->dev_if->in_ep_regs[0]->diepctl, depctl.d32);
3178 +
3179 + }
3180 + } else {
3181 + /* OUT endpoint */
3182 + dwc_otg_dev_out_ep_regs_t * out_regs = _core_if->dev_if->out_ep_regs[_ep->num];
3183 +
3184 + depctl.d32 = dwc_read_reg32(&(out_regs->doepctl));
3185 + deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz));
3186 +
3187 + /* Program the transfer size and packet count as follows:
3188 + *
3189 + * pktcnt = N
3190 + * xfersize = N * maxpacket
3191 + */
3192 + if (_ep->xfer_len == 0) {
3193 + /* Zero Length Packet */
3194 + deptsiz.b.xfersize = _ep->maxpacket;
3195 + deptsiz.b.pktcnt = 1;
3196 + } else {
3197 + deptsiz.b.pktcnt = (_ep->xfer_len + (_ep->maxpacket - 1)) / _ep->maxpacket;
3198 + deptsiz.b.xfersize = deptsiz.b.pktcnt * _ep->maxpacket;
3199 + }
3200 + dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
3201 +
3202 + DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",
3203 + _ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);
3204 +
3205 + if (_core_if->dma_enable) {
3206 +#if 1 // winder
3207 + dwc_write_reg32 (&(out_regs->doepdma),
3208 + CPHYSADDR((uint32_t)_ep->xfer_buff)); // winder
3209 +#else
3210 + dwc_write_reg32 (&(out_regs->doepdma),
3211 + (uint32_t)_ep->dma_addr);
3212 +#endif
3213 + }
3214 +
3215 + if (_ep->type == DWC_OTG_EP_TYPE_ISOC) {
3216 + /** @todo NGS: dpid is read-only. Use setd0pid
3217 + * or setd1pid. */
3218 + if (_ep->even_odd_frame) {
3219 + depctl.b.setd1pid = 1;
3220 + } else {
3221 + depctl.b.setd0pid = 1;
3222 + }
3223 + }
3224 +
3225 + /* EP enable */
3226 + depctl.b.cnak = 1;
3227 + depctl.b.epena = 1;
3228 +
3229 + dwc_write_reg32(&out_regs->doepctl, depctl.d32);
3230 +
3231 + DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
3232 + dwc_read_reg32(&out_regs->doepctl),
3233 + dwc_read_reg32(&out_regs->doeptsiz));
3234 + DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
3235 + dwc_read_reg32(&_core_if->dev_if->dev_global_regs->daintmsk),
3236 + dwc_read_reg32(&_core_if->core_global_regs->gintmsk));
3237 + }
3238 +}
3239 +
3240 +
3241 +/**
3242 + * This function does the setup for a data transfer for EP0 and starts
3243 + * the transfer. For an IN transfer, the packets will be loaded into
3244 + * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
3245 + * unloaded from the Rx FIFO in the ISR.
3246 + *
3247 + * @param _core_if Programming view of DWC_otg controller.
3248 + * @param _ep The EP0 data.
3249 + */
3250 +void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t *_core_if, dwc_ep_t *_ep)
3251 +{
3252 + volatile depctl_data_t depctl;
3253 + volatile deptsiz0_data_t deptsiz;
3254 + gintmsk_data_t intr_mask = { .d32 = 0};
3255 +
3256 + DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
3257 + "xfer_buff=%p start_xfer_buff=%p total_len=%d\n",
3258 + _ep->num, (_ep->is_in?"IN":"OUT"), _ep->xfer_len,
3259 + _ep->xfer_count, _ep->xfer_buff, _ep->start_xfer_buff,
3260 + _ep->total_len);
3261 + _ep->total_len = _ep->xfer_len;
3262 +
3263 + /* IN endpoint */
3264 + if (_ep->is_in == 1) {
3265 + dwc_otg_dev_in_ep_regs_t * in_regs = _core_if->dev_if->in_ep_regs[0];
3266 + gnptxsts_data_t gtxstatus;
3267 + gtxstatus.d32 = dwc_read_reg32(&_core_if->core_global_regs->gnptxsts);
3268 + if (_core_if->en_multiple_tx_fifo == 0 &&
3269 + gtxstatus.b.nptxqspcavail == 0) {
3270 +#ifdef DEBUG
3271 + deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz);
3272 + DWC_DEBUGPL(DBG_PCD,"DIEPCTL0=%0x\n",
3273 + dwc_read_reg32(&in_regs->diepctl));
3274 + DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",
3275 + deptsiz.d32, deptsiz.b.xfersize,deptsiz.b.pktcnt);
3276 + DWC_PRINT("TX Queue or FIFO Full (0x%0x)\n", gtxstatus.d32);
3277 +#endif /* */
3278 + printk("TX Queue or FIFO Full!!!!\n"); // test-only
3279 + //return;
3280 + MDELAY(100); //james
3281 + }
3282 +
3283 + depctl.d32 = dwc_read_reg32(&in_regs->diepctl);
3284 + deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz);
3285 +
3286 + /* Zero Length Packet? */
3287 + if (_ep->xfer_len == 0) {
3288 + deptsiz.b.xfersize = 0;
3289 + deptsiz.b.pktcnt = 1;
3290 + } else {
3291 + /* Program the transfer size and packet count
3292 + * as follows: xfersize = N * maxpacket +
3293 + * short_packet pktcnt = N + (short_packet
3294 + * exist ? 1 : 0)
3295 + */
3296 + if (_ep->xfer_len > _ep->maxpacket) {
3297 + _ep->xfer_len = _ep->maxpacket;
3298 + deptsiz.b.xfersize = _ep->maxpacket;
3299 + }
3300 + else {
3301 + deptsiz.b.xfersize = _ep->xfer_len;
3302 + }
3303 + deptsiz.b.pktcnt = 1;
3304 +
3305 + }
3306 + dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
3307 + DWC_DEBUGPL(DBG_PCDV, "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
3308 + _ep->xfer_len, deptsiz.b.xfersize,deptsiz.b.pktcnt, deptsiz.d32);
3309 +
3310 + /* Write the DMA register */
3311 + if (_core_if->dma_enable) {
3312 + dwc_write_reg32(&(in_regs->diepdma), (uint32_t) _ep->dma_addr);
3313 + }
3314 +
3315 + /* EP enable, IN data in FIFO */
3316 + depctl.b.cnak = 1;
3317 + depctl.b.epena = 1;
3318 + dwc_write_reg32(&in_regs->diepctl, depctl.d32);
3319 +
3320 + /**
3321 + * Enable the Non-Periodic Tx FIFO empty interrupt, the
3322 + * data will be written into the fifo by the ISR.
3323 + */
3324 + if (!_core_if->dma_enable) {
3325 + if (_core_if->en_multiple_tx_fifo == 0) {
3326 + intr_mask.b.nptxfempty = 1;
3327 + dwc_modify_reg32(&_core_if->core_global_regs->gintsts, intr_mask.d32, 0);
3328 + dwc_modify_reg32(&_core_if->core_global_regs->gintmsk, intr_mask.d32,
3329 + intr_mask.d32);
3330 + } else {
3331 + /* Enable the Tx FIFO Empty Interrupt for this EP */
3332 + if (_ep->xfer_len > 0) {
3333 + uint32_t fifoemptymsk = 0;
3334 + fifoemptymsk |= 1 << _ep->num;
3335 + dwc_modify_reg32(&_core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
3336 + 0, fifoemptymsk);
3337 + }
3338 +
3339 + }
3340 + }
3341 + } else {
3342 + /* OUT endpoint */
3343 + dwc_otg_dev_out_ep_regs_t * out_regs = _core_if->dev_if->out_ep_regs[_ep->num];
3344 +
3345 + depctl.d32 = dwc_read_reg32(&out_regs->doepctl);
3346 + deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz);
3347 +
3348 + /* Program the transfer size and packet count as follows:
3349 + * xfersize = N * (maxpacket + 4 - (maxpacket % 4))
3350 + * pktcnt = N */
3351 + if (_ep->xfer_len == 0) {
3352 + /* Zero Length Packet */
3353 + deptsiz.b.xfersize = _ep->maxpacket;
3354 + deptsiz.b.pktcnt = 1;
3355 + } else {
3356 + deptsiz.b.pktcnt = (_ep->xfer_len + (_ep->maxpacket - 1)) / _ep->maxpacket;
3357 + deptsiz.b.xfersize = deptsiz.b.pktcnt * _ep->maxpacket;
3358 + }
3359 +
3360 + dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
3361 + DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n",
3362 + _ep->xfer_len, deptsiz.b.xfersize,deptsiz.b.pktcnt);
3363 +
3364 + if (_core_if->dma_enable) {
3365 + dwc_write_reg32(&(out_regs->doepdma), (uint32_t) _ep->dma_addr);
3366 + }
3367 +
3368 + /* EP enable */
3369 + depctl.b.cnak = 1;
3370 + depctl.b.epena = 1;
3371 + dwc_write_reg32 (&(out_regs->doepctl), depctl.d32);
3372 + }
3373 +}
3374 +
3375 +/**
3376 + * This function continues control IN transfers started by
3377 + * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
3378 + * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
3379 + * bit for the packet count.
3380 + *
3381 + * @param _core_if Programming view of DWC_otg controller.
3382 + * @param _ep The EP0 data.
3383 + */
3384 +void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t *_core_if, dwc_ep_t *_ep)
3385 +{
3386 + depctl_data_t depctl;
3387 + deptsiz0_data_t deptsiz;
3388 + gintmsk_data_t intr_mask = { .d32 = 0};
3389 +
3390 + if (_ep->is_in == 1) {
3391 + dwc_otg_dev_in_ep_regs_t *in_regs =
3392 + _core_if->dev_if->in_ep_regs[0];
3393 + gnptxsts_data_t tx_status = {.d32 = 0};
3394 +
3395 + tx_status.d32 = dwc_read_reg32( &_core_if->core_global_regs->gnptxsts );
3396 + /** @todo Should there be check for room in the Tx
3397 + * Status Queue. If not remove the code above this comment. */
3398 +
3399 + depctl.d32 = dwc_read_reg32(&in_regs->diepctl);
3400 + deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz);
3401 +
3402 + /* Program the transfer size and packet count
3403 + * as follows: xfersize = N * maxpacket +
3404 + * short_packet pktcnt = N + (short_packet
3405 + * exist ? 1 : 0)
3406 + */
3407 + deptsiz.b.xfersize = (_ep->total_len - _ep->xfer_count) > _ep->maxpacket ? _ep->maxpacket :
3408 + (_ep->total_len - _ep->xfer_count);
3409 + deptsiz.b.pktcnt = 1;
3410 + _ep->xfer_len += deptsiz.b.xfersize;
3411 +
3412 + dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
3413 + DWC_DEBUGPL(DBG_PCDV, "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
3414 + _ep->xfer_len,
3415 + deptsiz.b.xfersize, deptsiz.b.pktcnt, deptsiz.d32);
3416 +
3417 + /* Write the DMA register */
3418 + if (_core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
3419 + dwc_write_reg32 (&(in_regs->diepdma),
3420 + CPHYSADDR((uint32_t)_ep->dma_addr)); // winder
3421 + }
3422 +
3423 + /* EP enable, IN data in FIFO */
3424 + depctl.b.cnak = 1;
3425 + depctl.b.epena = 1;
3426 + dwc_write_reg32(&in_regs->diepctl, depctl.d32);
3427 +
3428 + /**
3429 + * Enable the Non-Periodic Tx FIFO empty interrupt, the
3430 + * data will be written into the fifo by the ISR.
3431 + */
3432 + if (!_core_if->dma_enable) {
3433 + /* First clear it from GINTSTS */
3434 + intr_mask.b.nptxfempty = 1;
3435 + dwc_write_reg32( &_core_if->core_global_regs->gintsts,
3436 + intr_mask.d32 );
3437 +
3438 + dwc_modify_reg32( &_core_if->core_global_regs->gintmsk,
3439 + intr_mask.d32, intr_mask.d32);
3440 + }
3441 +
3442 + }
3443 +
3444 +}
3445 +
3446 +#ifdef DEBUG
3447 +void dump_msg(const u8 *buf, unsigned int length)
3448 +{
3449 + unsigned int start, num, i;
3450 + char line[52], *p;
3451 +
3452 + if (length >= 512)
3453 + return;
3454 + start = 0;
3455 + while (length > 0) {
3456 + num = min(length, 16u);
3457 + p = line;
3458 + for (i = 0; i < num; ++i) {
3459 + if (i == 8)
3460 + *p++ = ' ';
3461 + sprintf(p, " %02x", buf[i]);
3462 + p += 3;
3463 + }
3464 + *p = 0;
3465 + DWC_PRINT( "%6x: %s\n", start, line);
3466 + buf += num;
3467 + start += num;