1 |
17 |
wfjm |
/* $Id: usb_fifo_init.c 450 2012-01-05 23:21:41Z mueller $ */
|
2 |
|
|
/*
|
3 |
|
|
* Copyright 2011-2012 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
4 |
|
|
* Code was forked from ixo-jtag.svn.sourceforge.net on 2011-07-17
|
5 |
|
|
* The data fifo treatment is partially inspired by work of Marco Oster
|
6 |
|
|
* done at ZITI, Heidelberg in 2010.
|
7 |
|
|
*
|
8 |
|
|
* - original copyright and licence disclaimer (of usb_jtag_init) -------------
|
9 |
|
|
* - Code that turns a Cypress FX2 USB Controller into an USB JTAG adapter
|
10 |
|
|
* - Copyright (C) 2005..2007 Kolja Waschk, ixo.de
|
11 |
|
|
* - This code is part of usbjtag. usbjtag is free software;
|
12 |
|
|
*-----------------------------------------------------------------------------
|
13 |
|
|
*
|
14 |
|
|
* This program is free software; you may redistribute and/or modify it under
|
15 |
|
|
* the terms of the GNU General Public License as published by the Free
|
16 |
|
|
* Software Foundation, either version 2, or at your option any later version.
|
17 |
|
|
*
|
18 |
|
|
* This program is distributed in the hope that it will be useful, but
|
19 |
|
|
* WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
20 |
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
21 |
|
|
* for complete details.
|
22 |
|
|
*
|
23 |
|
|
*-----------------------------------------------------------------------------
|
24 |
|
|
*
|
25 |
|
|
* USB FIFO setup
|
26 |
|
|
*
|
27 |
|
|
* Revision History:
|
28 |
|
|
*
|
29 |
|
|
* Date Rev Version Comment
|
30 |
|
|
* 2012-01-04 450 1.5 new FLAGS layout (D=8-FF,C=4-EF,B=6-FF,A=indexed)
|
31 |
|
|
* 2012-01-02 448 1.4 add support for sync fifo w/ int. clock (_ic)
|
32 |
|
|
* 2011-07-24 398 1.1 support 0,2, or 3 data FIFO's
|
33 |
|
|
* 2011-07-23 397 1.0 Initial version, factored out from usb_jtag_init()
|
34 |
|
|
*
|
35 |
|
|
*-----------------------------------------------------------------------------
|
36 |
|
|
*/
|
37 |
|
|
|
38 |
|
|
#include "fx2regs.h"
|
39 |
|
|
#include "syncdelay.h"
|
40 |
|
|
|
41 |
|
|
//-----------------------------------------------------------------------------
|
42 |
|
|
|
43 |
|
|
void usb_fifo_init(void) // Called once at startup
|
44 |
|
|
{
|
45 |
|
|
// set the CPU clock to 48MHz, enable USB clock output to FPGA
|
46 |
|
|
// Note: CLKOUT not connected on nexys2, nexys3 and atlys...
|
47 |
|
|
CPUCS = bmCLKOE | bmCLKSPD1;
|
48 |
|
|
|
49 |
|
|
// setup FIFO mode
|
50 |
|
|
// bmIFCLKSRC clock source: 0 external clock; 1 internal clock
|
51 |
|
|
// bm3048MHZ clock frequency: 0 30 MHz; 1 48 MHz
|
52 |
|
|
// bmIFCLKOE IFCLK pin output enable: 0 tri-state; 1 drive
|
53 |
|
|
// bmIFCLKPOL clock polarity: 0 rising edge active; 1 falling edge active
|
54 |
|
|
// bmASYNC fifo mode: 0 synchrounous; 1 asynchronous
|
55 |
|
|
// IFCFG interface mode: bmIFCFGMASK=11->slave fifo
|
56 |
|
|
|
57 |
|
|
#if defined(USE_IC30)
|
58 |
|
|
// Use internal 30 MHz, enable output, slave sync FIFO, slave FIFO mode
|
59 |
|
|
IFCONFIG = bmIFCLKSRC | bmIFCLKOE | bmIFCFGMASK;
|
60 |
|
|
#else
|
61 |
|
|
// Use internal 30 MHz, enable output, slave async FIFO, slave FIFO mode
|
62 |
|
|
IFCONFIG = bmIFCLKSRC | bmIFCLKOE | bmASYNC | bmIFCFGMASK;
|
63 |
|
|
#endif
|
64 |
|
|
|
65 |
|
|
// Setup PA7 as FLAGD
|
66 |
|
|
PORTACFG = 0x80; SYNCDELAY; // 1000 0000: FLAGD=1, SLCS=0
|
67 |
|
|
|
68 |
|
|
// setup usage of FLAG pins
|
69 |
|
|
// goal is to support EP4(out) and EP6/EP8(in) synchronous slave fifos
|
70 |
|
|
// for synchronous operation usage of empty/full and almost empty/full
|
71 |
|
|
// flags is needed, the later are realized with the programmable flags.
|
72 |
|
|
// the three empty/full flags are setup as fixed flags, while the three
|
73 |
|
|
// almost (or programmable) flags are channeled over one indexed flag pin.
|
74 |
|
|
// FLAGA = indexed, PF (the default)
|
75 |
|
|
// FLAGB = EP6 FF
|
76 |
|
|
// FLAGC = EP4 EF
|
77 |
|
|
// FLAGD = EP8 FF
|
78 |
|
|
|
79 |
|
|
PINFLAGSAB = 0xE0; SYNCDELAY; // 1110 0000: B EP6 FF, A indexed
|
80 |
|
|
PINFLAGSCD = 0xF9; SYNCDELAY; // 1111 1001: D EP8 FF, C EP4 EF
|
81 |
|
|
|
82 |
|
|
// define endpoint configuration
|
83 |
|
|
|
84 |
|
|
FIFORESET = 0x80; SYNCDELAY; // From now on, NAK all
|
85 |
|
|
REVCTL = 3; SYNCDELAY; // Allow FW access to FIFO buffer
|
86 |
|
|
|
87 |
|
|
// FIFOs used for JTAG emulation
|
88 |
|
|
// EP1 IN
|
89 |
|
|
// EP2 OUT
|
90 |
|
|
|
91 |
|
|
EP1OUTCFG = 0x00; SYNCDELAY; // EP1 OUT: inactive
|
92 |
|
|
EP1INCFG = 0xA0; SYNCDELAY; // EP1 IN: active, bulk
|
93 |
|
|
|
94 |
|
|
EP2FIFOCFG = 0x00; SYNCDELAY; // EP2 slave: 0, not used as slave
|
95 |
|
|
FIFORESET = 0x02; SYNCDELAY; // EP2 reset (0x02! see comment below)
|
96 |
|
|
EP2CFG = 0xA2; SYNCDELAY; // EP2: 1010 0010: VAL,OUT,BULK,DOUBLE
|
97 |
|
|
|
98 |
|
|
// TMR (Rev *D) page 117: auto in/out initialization sequence
|
99 |
|
|
// Auto IN transfers
|
100 |
|
|
// 1. setup EPxCFG
|
101 |
|
|
// 2. reset the FIFO
|
102 |
|
|
// 3. set EPxFIFOCFG.3 = 1
|
103 |
|
|
// 4. set EPxAUTOINLENH:L
|
104 |
|
|
// Auto OUT transfers
|
105 |
|
|
// 1. setup EPxCFG
|
106 |
|
|
// 2. reset the FIFO
|
107 |
|
|
// 3. arm OUT buffers by writing OUTPKTEND N times w/ skip=1 (N=buf depth)
|
108 |
|
|
// 4. set EPxFIFOCFG.4 = 1
|
109 |
|
|
|
110 |
|
|
// 2 FIFOs used for DATA transfer:
|
111 |
|
|
// EP4 OUT DOUBLE
|
112 |
|
|
// EP6 IN QUAD
|
113 |
|
|
|
114 |
|
|
#if defined(USE_2FIFO) || defined(USE_3FIFO)
|
115 |
|
|
EP4CFG = 0xA2; SYNCDELAY; // EP4: 1010 0010: VAL,OUT,BULK,DOUBLE
|
116 |
|
|
#if defined(USE_3FIFO)
|
117 |
|
|
EP6CFG = 0xE2; SYNCDELAY; // EP6: 1110 0010: VAL,IN,BULK,DOUBLE
|
118 |
|
|
EP8CFG = 0xE2; SYNCDELAY; // EP8: 1110 0010: VAL,IN,BULK,DOUBLE
|
119 |
|
|
#else
|
120 |
|
|
EP6CFG = 0xE0; SYNCDELAY; // EP6: 1110 0000: VAL,IN,BULK,QUAD
|
121 |
|
|
EP8CFG = 0x02; SYNCDELAY; // EP8: disabled
|
122 |
|
|
#endif
|
123 |
|
|
|
124 |
|
|
// Note: the description of the FIFORESET in the TMR, Rev *D (2011) is
|
125 |
|
|
// wrong. The TMR asks to write 0x80,0x82,0x84,0x86,0x88,0x00, e.g
|
126 |
|
|
// on page 117, also in other contexts.
|
127 |
|
|
// This doesn't work, FIFO's are in fact not reset !
|
128 |
|
|
// The proper sequence is 0x80,0x02,0x04,0x06,0x08,0x00, as for
|
129 |
|
|
// example stated in http://www.cypress.com/?id=4&rID=32093
|
130 |
|
|
FIFORESET = 0x04; SYNCDELAY; // EP4 reset
|
131 |
|
|
FIFORESET = 0x06; SYNCDELAY; // EP6 reset
|
132 |
|
|
FIFORESET = 0x08; SYNCDELAY; // EP8 reset
|
133 |
|
|
FIFORESET = 0x00; SYNCDELAY; // Restore normal behaviour
|
134 |
|
|
|
135 |
|
|
// !! really needed here, before buffers are armed !!
|
136 |
|
|
REVCTL = 0; SYNCDELAY; // Reset FW access to FIFO buffer
|
137 |
|
|
|
138 |
|
|
// EP4 OUT setup ---------------------------------------------------
|
139 |
|
|
OUTPKTEND = 0x84; SYNCDELAY; // arm all EP4 buffers
|
140 |
|
|
OUTPKTEND = 0x84; SYNCDELAY;
|
141 |
|
|
// !! hardware only arms endpoint when AUTOOUT 0->1 transition seen
|
142 |
|
|
// !! --> clean AUTOOUT to handle for example back-to-back firmware loads
|
143 |
|
|
EP4FIFOCFG = 0x00; SYNCDELAY; // EP4: force AUTOOUT 0->1 transition
|
144 |
|
|
EP4FIFOCFG = 0x10; SYNCDELAY; // EP4: 0001 0000: AUTOOUT, BYTE
|
145 |
|
|
// setup programmable fifo threshold as 'almost empty' at 3 bytes to go
|
146 |
|
|
// --> keep active low logic for prgrammable flags
|
147 |
|
|
// --> set flag 1 when fill >= threshold (DECIS=1)
|
148 |
|
|
// --> almost empty thus at fill<4, effective threshold thus 3 !!
|
149 |
|
|
EP4FIFOPFH = 0x80; SYNCDELAY; // 0000 0000: DECIS=1, PFC8=0
|
150 |
|
|
EP4FIFOPFL = 0x04; SYNCDELAY; // PFC = 4 = 0 0000 0100
|
151 |
|
|
|
152 |
|
|
// EP6 IN setup ---------------------------------------------------
|
153 |
|
|
EP6FIFOCFG = 0x0C; SYNCDELAY; // EP6: 0000 1100: AUTOIN, ZEROLEN, BYTE
|
154 |
|
|
EP6AUTOINLENH = 0x02; SYNCDELAY; // 512 byte buffers
|
155 |
|
|
EP6AUTOINLENL = 0x00; SYNCDELAY;
|
156 |
|
|
|
157 |
|
|
// setup programmable fifo threshold as 'almost full' at 3 bytes to go
|
158 |
|
|
// --> keep active low logic for prgrammable flags
|
159 |
|
|
// --> set flag 1 when fill <= threshold (DECIS=0)
|
160 |
|
|
// --> use full buffer fill
|
161 |
|
|
// --> for dual buffered: (PKSTAT=0, PKTS=1) [in case 3 fifo's used]
|
162 |
|
|
// --> for quad buffered: (PKSTAT=0, PKTS=3) [in case 2 fifo's used]
|
163 |
|
|
// --> effective threshold thus 3 in both bases
|
164 |
|
|
#if defined(USE_3FIFO)
|
165 |
|
|
EP6FIFOPFH = 0x09; SYNCDELAY; // 0000 1001: DECIS=0, PK=0:1, PFC8=1
|
166 |
|
|
#else
|
167 |
|
|
EP6FIFOPFH = 0x19; SYNCDELAY; // 0001 1001: DECIS=0, PK=0:3, PFC8=1
|
168 |
|
|
#endif
|
169 |
|
|
EP6FIFOPFL = 0xfc; SYNCDELAY; // PFC = 508 = 1 1111 1100
|
170 |
|
|
|
171 |
|
|
#if defined(USE_3FIFO)
|
172 |
|
|
// EP8 IN setup ---------------------------------------------------
|
173 |
|
|
EP8FIFOCFG = 0x0C; SYNCDELAY; // EP8: 0000 1100: AUTOIN, ZEROLEN, BYTE
|
174 |
|
|
EP8AUTOINLENH = 0x02; SYNCDELAY; // 512 byte buffers
|
175 |
|
|
EP8AUTOINLENL = 0x00; SYNCDELAY;
|
176 |
|
|
// setup programmable fifo threshold as 'almost full' at 4 bytes to go
|
177 |
|
|
// like for EP6 above
|
178 |
|
|
EP8FIFOPFH = 0x41; SYNCDELAY; // 0100 0001: DECIS=0, PKSTAT=1, PFC8=1
|
179 |
|
|
EP8FIFOPFL = 0xfc; SYNCDELAY; // PFC = 508 = 1 1111 1100
|
180 |
|
|
|
181 |
|
|
#else
|
182 |
|
|
// EP8 setup
|
183 |
|
|
EP8FIFOCFG = 0x00; SYNCDELAY; // EP8 slave: 0, not used as slave
|
184 |
|
|
#endif
|
185 |
|
|
|
186 |
|
|
#else
|
187 |
|
|
// no FIFOs used for DATA transfer
|
188 |
|
|
// EP4,6,8 inactive
|
189 |
|
|
EP4CFG = 0x02; SYNCDELAY; // EP4: disabled
|
190 |
|
|
EP6CFG = 0x02; SYNCDELAY; // EP6: disabled
|
191 |
|
|
EP8CFG = 0x02; SYNCDELAY; // EP8: disabled
|
192 |
|
|
|
193 |
|
|
FIFORESET = 0x04; SYNCDELAY; // EP4 reset
|
194 |
|
|
FIFORESET = 0x06; SYNCDELAY; // EP6 reset
|
195 |
|
|
FIFORESET = 0x08; SYNCDELAY; // EP8 reset
|
196 |
|
|
FIFORESET = 0x00; SYNCDELAY; // Restore normal behaviour
|
197 |
|
|
|
198 |
|
|
EP4FIFOCFG = 0x00; SYNCDELAY; // EP4 slave: 0, not used as slave
|
199 |
|
|
EP6FIFOCFG = 0x00; SYNCDELAY; // EP6 slave: 0, not used as slave
|
200 |
|
|
EP8FIFOCFG = 0x00; SYNCDELAY; // EP8 slave: 0, not used as slave
|
201 |
|
|
|
202 |
|
|
REVCTL = 0; SYNCDELAY; // Reset FW access to FIFO buffer
|
203 |
|
|
#endif
|
204 |
|
|
|
205 |
|
|
// the EP2 endpoint does not come up armed. It is used with double buffering
|
206 |
|
|
// so write dummy byte counts twice.
|
207 |
|
|
SYNCDELAY; //
|
208 |
|
|
EP2BCL = 0x80; SYNCDELAY; // arm EP2OUT
|
209 |
|
|
EP2BCL = 0x80; SYNCDELAY; // arm EP2OUT
|
210 |
|
|
}
|