1 /*****************************************************************************
2 ** FILE NAME : ifxhcd_es.c
3 ** PROJECT : IFX USB sub-system V3
4 ** MODULES : IFX USB sub-system Host and Device driver
7 ** AUTHOR : Chen, Howard
8 ** DESCRIPTION : The file contain function to enable host mode USB-IF Electrical Test function.
11 ** REFERENCE : Synopsys DWC-OTG Driver 2.7
12 ** COPYRIGHT : Copyright (c) 2010
13 ** LANTIQ DEUTSCHLAND GMBH,
14 ** Am Campeon 3, 85579 Neubiberg, Germany
16 ** This program is free software; you can redistribute it and/or modify
17 ** it under the terms of the GNU General Public License as published by
18 ** the Free Software Foundation; either version 2 of the License, or
19 ** (at your option) any later version.
21 ** Version Control Section **
25 ** $Log$ Revision history
26 *****************************************************************************/
29 * This file contains code fragments from Synopsys HS OTG Linux Software Driver.
30 * For this code the following notice is applicable:
32 * ==========================================================================
34 * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
35 * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
36 * otherwise expressly agreed to in writing between Synopsys and you.
38 * The Software IS NOT an item of Licensed Software or Licensed Product under
39 * any End User Software License Agreement or Agreement for Licensed Product
40 * with Synopsys or any supplement thereto. You are permitted to use and
41 * redistribute this Software in source and binary forms, with or without
42 * modification, provided that redistributions of source code must retain this
43 * notice. You may not view, use, disclose, copy or distribute this file or
44 * any information contained herein except pursuant to this license grant from
45 * Synopsys. If you do not agree with this notice, including the disclaimer
46 * below, then you are not authorized to use the Software.
48 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
49 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
52 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
54 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
55 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
59 * ========================================================================== */
63 \ingroup IFXUSB_DRIVER_V3
64 \brief The file contain function to enable host mode USB-IF Electrical Test function.
67 #include <linux/version.h>
68 #include "ifxusb_version.h"
70 #include <linux/kernel.h>
72 #include <linux/errno.h>
74 #include <linux/dma-mapping.h>
76 #include "ifxusb_plat.h"
77 #include "ifxusb_regs.h"
78 #include "ifxusb_cif.h"
82 #ifdef __WITH_HS_ELECT_TST__
84 * Quick and dirty hack to implement the HS Electrical Test
85 * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
87 * This code was copied from our userspace app "hset". It sends a
88 * Get Device Descriptor control sequence in two parts, first the
89 * Setup packet by itself, followed some time later by the In and
90 * Ack packets. Rather than trying to figure out how to add this
91 * functionality to the normal driver code, we just hijack the
92 * hardware, using these two function to drive the hardware
97 void do_setup(ifxusb_core_if_t
*_core_if
)
100 ifxusb_core_global_regs_t
*global_regs
= _core_if
->core_global_regs
;
101 ifxusb_host_global_regs_t
*hc_global_regs
= _core_if
->host_global_regs
;
102 ifxusb_hc_regs_t
*hc_regs
= _core_if
->hc_regs
[0];
103 uint32_t *data_fifo
= _core_if
->data_fifo
[0];
106 hctsiz_data_t hctsiz
;
107 hcchar_data_t hcchar
;
113 ifxusb_wreg(&hc_global_regs
->haintmsk
, 0x0001);
116 ifxusb_wreg(&hc_regs
->hcintmsk
, 0x04a3);
119 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
120 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
123 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
124 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
127 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
128 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
131 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
132 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
135 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
138 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
141 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
144 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
145 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
148 * Send Setup packet (Get Device Descriptor)
151 /* Make sure channel is disabled */
152 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
154 //fprintf(stderr, "Channel already enabled 1, HCCHAR = %08x\n", hcchar.d32);
156 // hcchar.b.chen = 1;
157 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
162 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
163 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
166 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
167 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
170 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
171 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
174 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
175 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
178 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
181 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
184 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
186 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
187 //if (hcchar.b.chen) {
188 // fprintf(stderr, "** Channel _still_ enabled 1, HCCHAR = %08x **\n", hcchar.d32);
194 hctsiz
.b
.xfersize
= 8;
196 hctsiz
.b
.pid
= IFXUSB_HC_PID_SETUP
;
197 ifxusb_wreg(&hc_regs
->hctsiz
, hctsiz
.d32
);
200 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
201 hcchar
.b
.eptype
= IFXUSB_EP_TYPE_CTRL
;
206 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
208 /* Fill FIFO with Setup data for Get Device Descriptor */
209 ifxusb_wreg(data_fifo
++, 0x01000680);
210 ifxusb_wreg(data_fifo
++, 0x00080000);
212 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
213 //fprintf(stderr, "Waiting for HCINTR intr 1, GINTSTS = %08x\n", gintsts.d32);
215 /* Wait for host channel interrupt */
217 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
218 } while (gintsts
.b
.hcintr
== 0);
220 //fprintf(stderr, "Got HCINTR intr 1, GINTSTS = %08x\n", gintsts.d32);
223 ifxusb_wreg(&hc_regs
->hcintmsk
, 0x0000);
226 ifxusb_wreg(&hc_global_regs
->haintmsk
, 0x0000);
229 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
230 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
233 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
234 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
237 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
238 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
241 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
244 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
247 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
250 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
251 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
254 void do_in_ack(ifxusb_core_if_t
*_core_if
)
257 ifxusb_core_global_regs_t
*global_regs
= _core_if
->core_global_regs
;
258 ifxusb_host_global_regs_t
*hc_global_regs
= _core_if
->host_global_regs
;
259 ifxusb_hc_regs_t
*hc_regs
= _core_if
->hc_regs
[0];
260 uint32_t *data_fifo
= _core_if
->data_fifo
[0];
263 hctsiz_data_t hctsiz
;
264 hcchar_data_t hcchar
;
267 grxsts_data_t grxsts
;
270 ifxusb_wreg(&hc_global_regs
->haintmsk
, 0x0001);
273 ifxusb_wreg(&hc_regs
->hcintmsk
, 0x04a3);
276 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
277 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
280 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
281 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
284 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
285 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
288 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
289 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
292 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
295 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
298 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
301 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
302 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
305 * Receive Control In packet
308 /* Make sure channel is disabled */
309 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
311 //fprintf(stderr, "Channel already enabled 2, HCCHAR = %08x\n", hcchar.d32);
314 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
319 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
320 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
323 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
324 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
327 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
328 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
331 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
332 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
335 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
338 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
341 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
343 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
344 //if (hcchar.b.chen) {
345 // fprintf(stderr, "** Channel _still_ enabled 2, HCCHAR = %08x **\n", hcchar.d32);
351 hctsiz
.b
.xfersize
= 8;
353 hctsiz
.b
.pid
= IFXUSB_HC_PID_DATA1
;
354 ifxusb_wreg(&hc_regs
->hctsiz
, hctsiz
.d32
);
357 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
358 hcchar
.b
.eptype
= IFXUSB_EP_TYPE_CTRL
;
363 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
365 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
366 //fprintf(stderr, "Waiting for RXSTSQLVL intr 1, GINTSTS = %08x\n", gintsts.d32);
368 /* Wait for receive status queue interrupt */
370 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
371 } while (gintsts
.b
.rxstsqlvl
== 0);
373 //fprintf(stderr, "Got RXSTSQLVL intr 1, GINTSTS = %08x\n", gintsts.d32);
376 grxsts
.d32
= ifxusb_rreg(&global_regs
->grxstsp
);
377 //fprintf(stderr, "GRXSTS: %08x\n", grxsts.d32);
379 /* Clear RXSTSQLVL in GINTSTS */
381 gintsts
.b
.rxstsqlvl
= 1;
382 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
384 switch (grxsts
.hb
.pktsts
) {
385 case IFXUSB_HSTS_DATA_UPDT
:
386 /* Read the data into the host buffer */
387 if (grxsts
.hb
.bcnt
> 0) {
389 int word_count
= (grxsts
.hb
.bcnt
+ 3) / 4;
391 for (i
= 0; i
< word_count
; i
++) {
392 (void)ifxusb_rreg(data_fifo
++);
396 //fprintf(stderr, "Received %u bytes\n", (unsigned)grxsts.hb.bcnt);
400 //fprintf(stderr, "** Unexpected GRXSTS packet status 1 **\n");
404 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
405 //fprintf(stderr, "Waiting for RXSTSQLVL intr 2, GINTSTS = %08x\n", gintsts.d32);
407 /* Wait for receive status queue interrupt */
409 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
410 } while (gintsts
.b
.rxstsqlvl
== 0);
412 //fprintf(stderr, "Got RXSTSQLVL intr 2, GINTSTS = %08x\n", gintsts.d32);
415 grxsts
.d32
= ifxusb_rreg(&global_regs
->grxstsp
);
416 //fprintf(stderr, "GRXSTS: %08x\n", grxsts.d32);
418 /* Clear RXSTSQLVL in GINTSTS */
420 gintsts
.b
.rxstsqlvl
= 1;
421 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
423 switch (grxsts
.hb
.pktsts
) {
424 case IFXUSB_HSTS_XFER_COMP
:
428 //fprintf(stderr, "** Unexpected GRXSTS packet status 2 **\n");
432 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
433 //fprintf(stderr, "Waiting for HCINTR intr 2, GINTSTS = %08x\n", gintsts.d32);
435 /* Wait for host channel interrupt */
437 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
438 } while (gintsts
.b
.hcintr
== 0);
440 //fprintf(stderr, "Got HCINTR intr 2, GINTSTS = %08x\n", gintsts.d32);
443 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
444 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
447 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
448 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
451 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
452 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
455 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
458 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
461 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
464 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
465 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
472 * Send handshake packet
476 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
477 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
480 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
481 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
484 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
485 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
488 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
491 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
494 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
497 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
498 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
500 /* Make sure channel is disabled */
501 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
503 //fprintf(stderr, "Channel already enabled 3, HCCHAR = %08x\n", hcchar.d32);
506 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
511 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
512 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
515 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
516 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
519 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
520 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
523 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
524 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
527 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
530 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
533 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
535 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
536 //if (hcchar.b.chen) {
537 // fprintf(stderr, "** Channel _still_ enabled 3, HCCHAR = %08x **\n", hcchar.d32);
543 hctsiz
.b
.xfersize
= 0;
545 hctsiz
.b
.pid
= IFXUSB_HC_PID_DATA1
;
546 ifxusb_wreg(&hc_regs
->hctsiz
, hctsiz
.d32
);
549 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
550 hcchar
.b
.eptype
= IFXUSB_EP_TYPE_CTRL
;
555 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
557 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
558 //fprintf(stderr, "Waiting for HCINTR intr 3, GINTSTS = %08x\n", gintsts.d32);
560 /* Wait for host channel interrupt */
562 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
563 } while (gintsts
.b
.hcintr
== 0);
565 //fprintf(stderr, "Got HCINTR intr 3, GINTSTS = %08x\n", gintsts.d32);
568 ifxusb_wreg(&hc_regs
->hcintmsk
, 0x0000);
571 ifxusb_wreg(&hc_global_regs
->haintmsk
, 0x0000);
574 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
575 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
578 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
579 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
582 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
583 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
586 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
589 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
592 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
595 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
596 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
598 #endif //__WITH_HS_ELECT_TST__