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.
9 *****************************************************************************/
13 \ingroup IFXUSB_DRIVER_V3
14 \brief The file contain function to enable host mode USB-IF Electrical Test function.
17 #include <linux/version.h>
18 #include "ifxusb_version.h"
20 #include <linux/kernel.h>
22 #include <linux/errno.h>
24 #include <linux/dma-mapping.h>
26 #include "ifxusb_plat.h"
27 #include "ifxusb_regs.h"
28 #include "ifxusb_cif.h"
32 #ifdef __WITH_HS_ELECT_TST__
34 * Quick and dirty hack to implement the HS Electrical Test
35 * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
37 * This code was copied from our userspace app "hset". It sends a
38 * Get Device Descriptor control sequence in two parts, first the
39 * Setup packet by itself, followed some time later by the In and
40 * Ack packets. Rather than trying to figure out how to add this
41 * functionality to the normal driver code, we just hijack the
42 * hardware, using these two function to drive the hardware
47 void do_setup(ifxusb_core_if_t
*_core_if
)
50 ifxusb_core_global_regs_t
*global_regs
= _core_if
->core_global_regs
;
51 ifxusb_host_global_regs_t
*hc_global_regs
= _core_if
->host_global_regs
;
52 ifxusb_hc_regs_t
*hc_regs
= _core_if
->hc_regs
[0];
53 uint32_t *data_fifo
= _core_if
->data_fifo
[0];
63 ifxusb_wreg(&hc_global_regs
->haintmsk
, 0x0001);
66 ifxusb_wreg(&hc_regs
->hcintmsk
, 0x04a3);
69 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
70 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
73 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
74 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
77 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
78 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
81 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
82 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
85 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
88 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
91 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
94 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
95 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
98 * Send Setup packet (Get Device Descriptor)
101 /* Make sure channel is disabled */
102 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
104 //fprintf(stderr, "Channel already enabled 1, HCCHAR = %08x\n", hcchar.d32);
106 // hcchar.b.chen = 1;
107 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
112 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
113 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
116 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
117 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
120 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
121 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
124 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
125 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
128 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
131 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
134 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
136 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
137 //if (hcchar.b.chen) {
138 // fprintf(stderr, "** Channel _still_ enabled 1, HCCHAR = %08x **\n", hcchar.d32);
144 hctsiz
.b
.xfersize
= 8;
146 hctsiz
.b
.pid
= IFXUSB_HC_PID_SETUP
;
147 ifxusb_wreg(&hc_regs
->hctsiz
, hctsiz
.d32
);
150 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
151 hcchar
.b
.eptype
= IFXUSB_EP_TYPE_CTRL
;
156 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
158 /* Fill FIFO with Setup data for Get Device Descriptor */
159 ifxusb_wreg(data_fifo
++, 0x01000680);
160 ifxusb_wreg(data_fifo
++, 0x00080000);
162 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
163 //fprintf(stderr, "Waiting for HCINTR intr 1, GINTSTS = %08x\n", gintsts.d32);
165 /* Wait for host channel interrupt */
167 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
168 } while (gintsts
.b
.hcintr
== 0);
170 //fprintf(stderr, "Got HCINTR intr 1, GINTSTS = %08x\n", gintsts.d32);
173 ifxusb_wreg(&hc_regs
->hcintmsk
, 0x0000);
176 ifxusb_wreg(&hc_global_regs
->haintmsk
, 0x0000);
179 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
180 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
183 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
184 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
187 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
188 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
191 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
194 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
197 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
200 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
201 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
204 void do_in_ack(ifxusb_core_if_t
*_core_if
)
207 ifxusb_core_global_regs_t
*global_regs
= _core_if
->core_global_regs
;
208 ifxusb_host_global_regs_t
*hc_global_regs
= _core_if
->host_global_regs
;
209 ifxusb_hc_regs_t
*hc_regs
= _core_if
->hc_regs
[0];
210 uint32_t *data_fifo
= _core_if
->data_fifo
[0];
213 hctsiz_data_t hctsiz
;
214 hcchar_data_t hcchar
;
217 grxsts_data_t grxsts
;
220 ifxusb_wreg(&hc_global_regs
->haintmsk
, 0x0001);
223 ifxusb_wreg(&hc_regs
->hcintmsk
, 0x04a3);
226 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
227 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
230 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
231 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
234 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
235 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
238 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
239 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
242 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
245 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
248 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
251 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
252 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
255 * Receive Control In packet
258 /* Make sure channel is disabled */
259 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
261 //fprintf(stderr, "Channel already enabled 2, HCCHAR = %08x\n", hcchar.d32);
264 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
269 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
270 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
273 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
274 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
277 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
278 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
281 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
282 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
285 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
288 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
291 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
293 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
294 //if (hcchar.b.chen) {
295 // fprintf(stderr, "** Channel _still_ enabled 2, HCCHAR = %08x **\n", hcchar.d32);
301 hctsiz
.b
.xfersize
= 8;
303 hctsiz
.b
.pid
= IFXUSB_HC_PID_DATA1
;
304 ifxusb_wreg(&hc_regs
->hctsiz
, hctsiz
.d32
);
307 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
308 hcchar
.b
.eptype
= IFXUSB_EP_TYPE_CTRL
;
313 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
315 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
316 //fprintf(stderr, "Waiting for RXSTSQLVL intr 1, GINTSTS = %08x\n", gintsts.d32);
318 /* Wait for receive status queue interrupt */
320 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
321 } while (gintsts
.b
.rxstsqlvl
== 0);
323 //fprintf(stderr, "Got RXSTSQLVL intr 1, GINTSTS = %08x\n", gintsts.d32);
326 grxsts
.d32
= ifxusb_rreg(&global_regs
->grxstsp
);
327 //fprintf(stderr, "GRXSTS: %08x\n", grxsts.d32);
329 /* Clear RXSTSQLVL in GINTSTS */
331 gintsts
.b
.rxstsqlvl
= 1;
332 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
334 switch (grxsts
.hb
.pktsts
) {
335 case IFXUSB_HSTS_DATA_UPDT
:
336 /* Read the data into the host buffer */
337 if (grxsts
.hb
.bcnt
> 0) {
339 int word_count
= (grxsts
.hb
.bcnt
+ 3) / 4;
341 for (i
= 0; i
< word_count
; i
++) {
342 (void)ifxusb_rreg(data_fifo
++);
346 //fprintf(stderr, "Received %u bytes\n", (unsigned)grxsts.hb.bcnt);
350 //fprintf(stderr, "** Unexpected GRXSTS packet status 1 **\n");
354 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
355 //fprintf(stderr, "Waiting for RXSTSQLVL intr 2, GINTSTS = %08x\n", gintsts.d32);
357 /* Wait for receive status queue interrupt */
359 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
360 } while (gintsts
.b
.rxstsqlvl
== 0);
362 //fprintf(stderr, "Got RXSTSQLVL intr 2, GINTSTS = %08x\n", gintsts.d32);
365 grxsts
.d32
= ifxusb_rreg(&global_regs
->grxstsp
);
366 //fprintf(stderr, "GRXSTS: %08x\n", grxsts.d32);
368 /* Clear RXSTSQLVL in GINTSTS */
370 gintsts
.b
.rxstsqlvl
= 1;
371 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
373 switch (grxsts
.hb
.pktsts
) {
374 case IFXUSB_HSTS_XFER_COMP
:
378 //fprintf(stderr, "** Unexpected GRXSTS packet status 2 **\n");
382 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
383 //fprintf(stderr, "Waiting for HCINTR intr 2, GINTSTS = %08x\n", gintsts.d32);
385 /* Wait for host channel interrupt */
387 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
388 } while (gintsts
.b
.hcintr
== 0);
390 //fprintf(stderr, "Got HCINTR intr 2, GINTSTS = %08x\n", gintsts.d32);
393 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
394 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
397 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
398 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
401 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
402 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
405 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
408 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
411 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
414 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
415 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
422 * Send handshake packet
426 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
427 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
430 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
431 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
434 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
435 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
438 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
441 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
444 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
447 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
448 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
450 /* Make sure channel is disabled */
451 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
453 //fprintf(stderr, "Channel already enabled 3, HCCHAR = %08x\n", hcchar.d32);
456 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
461 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
462 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
465 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
466 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
469 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
470 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
473 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
474 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
477 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
480 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
483 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
485 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
486 //if (hcchar.b.chen) {
487 // fprintf(stderr, "** Channel _still_ enabled 3, HCCHAR = %08x **\n", hcchar.d32);
493 hctsiz
.b
.xfersize
= 0;
495 hctsiz
.b
.pid
= IFXUSB_HC_PID_DATA1
;
496 ifxusb_wreg(&hc_regs
->hctsiz
, hctsiz
.d32
);
499 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
500 hcchar
.b
.eptype
= IFXUSB_EP_TYPE_CTRL
;
505 ifxusb_wreg(&hc_regs
->hcchar
, hcchar
.d32
);
507 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
508 //fprintf(stderr, "Waiting for HCINTR intr 3, GINTSTS = %08x\n", gintsts.d32);
510 /* Wait for host channel interrupt */
512 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
513 } while (gintsts
.b
.hcintr
== 0);
515 //fprintf(stderr, "Got HCINTR intr 3, GINTSTS = %08x\n", gintsts.d32);
518 ifxusb_wreg(&hc_regs
->hcintmsk
, 0x0000);
521 ifxusb_wreg(&hc_global_regs
->haintmsk
, 0x0000);
524 haint
.d32
= ifxusb_rreg(&hc_global_regs
->haint
);
525 //fprintf(stderr, "HAINT: %08x\n", haint.d32);
528 hcint
.d32
= ifxusb_rreg(&hc_regs
->hcint
);
529 //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
532 hcchar
.d32
= ifxusb_rreg(&hc_regs
->hcchar
);
533 //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
536 ifxusb_wreg(&hc_regs
->hcint
, hcint
.d32
);
539 ifxusb_wreg(&hc_global_regs
->haint
, haint
.d32
);
542 ifxusb_wreg(&global_regs
->gintsts
, gintsts
.d32
);
545 gintsts
.d32
= ifxusb_rreg(&global_regs
->gintsts
);
546 //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
548 #endif //__WITH_HS_ELECT_TST__