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__