]> git.sur5r.net Git - openocd/blob - src/jtag/zy1000/jtag_minidriver.h
zy1000: FPGA revC wip
[openocd] / src / jtag / zy1000 / jtag_minidriver.h
1 /***************************************************************************
2  *   Copyright (C) 2007-2009 by Ã˜yvind Harboe                              *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18  ***************************************************************************/
19
20 #include <cyg/hal/hal_io.h>             // low level i/o
21 #include <cyg/hal/hal_intr.h>             // low level i/o
22
23 //#define VERBOSE(a) a
24 #define VERBOSE(a)
25
26 /* used to test manual mode */
27 #define TEST_MANUAL() 0
28
29 #if 0
30 int  diag_printf(const char *fmt, ...);
31 #define ZY1000_POKE(a, b) HAL_WRITE_UINT32(a, b); diag_printf("poke 0x%08x,0x%08x\n", a, b)
32 #define ZY1000_PEEK(a, b) HAL_READ_UINT32(a, b); diag_printf("peek 0x%08x = 0x%08x\n", a, b)
33 #else
34 #define ZY1000_PEEK(a, b) HAL_READ_UINT32(a, b)
35
36 #ifdef CYGPKG_HAL_NIOS2
37 #define ZY1000_POKE(a, b) \
38                  {/* This will flush the bridge FIFO. Overflowed bridge FIFO fails. We must \
39                  flush every "often". No precise system has been found, but 4 seems solid. \
40                   This code goes away once the FPGA has been fixed. */ \
41 \
42 CYG_INTERRUPT_STATE _old_; \
43 HAL_DISABLE_INTERRUPTS(_old_); \
44 HAL_WRITE_UINT32(a, b);\
45  static int overflow_counter = 0; \
46    if (++overflow_counter >= 1) \
47    { \
48            /* clear FIFO */ \
49            cyg_uint32 empty; ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty); \
50            overflow_counter = 0; \
51    } \
52    /* NB! interrupts must be restored *after* read */ \
53    HAL_RESTORE_INTERRUPTS(_old_); \
54 }\
55
56 #else
57 #define ZY1000_POKE(a, b) HAL_WRITE_UINT32(a, b)
58 #endif
59
60 #endif
61
62 // FIFO empty?
63 static __inline__ void waitIdle(void)
64 {
65         cyg_uint32 empty;
66         do
67         {
68                 ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty);
69         } while ((empty & 0x100) == 0);
70 }
71
72 static __inline__ void waitQueue(void)
73 {
74 //      waitIdle();
75 }
76
77 static void sampleShiftRegister(void)
78 {
79 #if 0
80         cyg_uint32 dummy;
81         waitIdle();
82         ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, dummy);
83 #endif
84 }
85
86 /* -O3 will inline this for us */
87 static void setCurrentState(enum tap_state state)
88 {
89         cyg_uint32 a;
90         a = state;
91         int repeat = 0;
92         if (state == TAP_RESET)
93         {
94                 // The FPGA nor we know the current state of the CPU TAP
95                 // controller. This will move it to TAP for sure.
96                 //
97                 // 5 should be enough here, 7 is what OpenOCD uses
98                 repeat = 7;
99         }
100         waitQueue();
101         sampleShiftRegister();
102         ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | a);
103
104 }
105
106 /*
107  * Enter state and cause repeat transitions *out* of that state. So if the endState != state, then
108  * the transition from state to endState counts as a transition out of state.
109  */
110 static __inline__ void shiftValueInner(const enum tap_state state, const enum tap_state endState, int repeat, cyg_uint32 value)
111 {
112         cyg_uint32 a,b;
113         a = state;
114         b = endState;
115         waitQueue();
116         sampleShiftRegister();
117         ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value);
118 #if 1
119 #if TEST_MANUAL()
120         if ((state == TAP_DRSHIFT) && (endState != TAP_DRSHIFT))
121         {
122                 int i;
123                 setCurrentState(state);
124                 for (i = 0; i < repeat; i++)
125                 {
126                         int tms;
127                         tms = 0;
128                         if ((i == repeat-1) && (state != endState))
129                         {
130                                 tms = 1;
131                         }
132                         /* shift out value */
133                         waitIdle();
134                         ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, (((value >> i)&1) << 1) | tms);
135                 }
136                 waitIdle();
137                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
138                 waitIdle();
139                 //ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT); // set this state and things break => expected
140                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRPAUSE); // set this and things will work => expected. Not setting this is not sufficient to make things break.
141                 setCurrentState(endState);
142         } else
143         {
144                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
145         }
146 #else
147         /* fast version */
148         ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
149 #endif
150 #else
151         /* maximum debug version */
152         if ((repeat > 0) && ((state == TAP_DRSHIFT)||(state == TAP_SI)))
153         {
154                 int i;
155                 /* sample shift register for every bit. */
156                 for (i = 0; i < repeat-1; i++)
157                 {
158                         sampleShiftRegister();
159                         ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> i);
160                         ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | a);
161                 }
162                 sampleShiftRegister();
163                 ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> (repeat-1));
164                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | b);
165         } else
166         {
167                 sampleShiftRegister();
168                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
169         }
170         sampleShiftRegister();
171 #endif
172 }
173
174
175
176 static __inline__ void interface_jtag_add_dr_out_core(struct jtag_tap *target_tap,
177                 int num_fields,
178                 const int *num_bits,
179                 const uint32_t *value,
180                 enum tap_state end_state)
181 {
182         enum tap_state pause_state = TAP_DRSHIFT;
183
184         struct jtag_tap *tap, *nextTap;
185         for (tap = jtag_tap_next_enabled(NULL); tap!= NULL; tap = nextTap)
186         {
187                 nextTap = jtag_tap_next_enabled(tap);
188                 if (nextTap == NULL)
189                 {
190                         pause_state = end_state;
191                 }
192                 if (tap == target_tap)
193                 {
194                         int j;
195                         for (j = 0; j < (num_fields-1); j++)
196                         {
197                                 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[j], value[j]);
198                         }
199                         shiftValueInner(TAP_DRSHIFT, pause_state, num_bits[j], value[j]);
200                 } else
201                 {
202                         /* program the scan field to 1 bit length, and ignore it's value */
203                         shiftValueInner(TAP_DRSHIFT, pause_state, 1, 0);
204                 }
205         }
206 }
207
208 static __inline__ void interface_jtag_add_dr_out(struct jtag_tap *target_tap,
209                 int num_fields,
210                 const int *num_bits,
211                 const uint32_t *value,
212                 enum tap_state end_state)
213 {
214
215         int singletap = (jtag_tap_next_enabled(jtag_tap_next_enabled(NULL)) == NULL);
216         if ((singletap) && (num_fields == 3))
217         {
218                 /* used by embeddedice_write_reg_inner() */
219                 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[0], value[0]);
220                 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[1], value[1]);
221                 shiftValueInner(TAP_DRSHIFT, end_state, num_bits[2], value[2]);
222         } else if ((singletap) && (num_fields == 2))
223         {
224                 /* used by arm7 code */
225                 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[0], value[0]);
226                 shiftValueInner(TAP_DRSHIFT, end_state, num_bits[1], value[1]);
227         } else
228         {
229                 interface_jtag_add_dr_out_core(target_tap, num_fields, num_bits, value, end_state);
230         }
231 }
232
233 #define interface_jtag_add_callback(callback, in) callback(in)
234
235 #define interface_jtag_add_callback4(callback, in, data1, data2, data3) jtag_set_error(callback(in, data1, data2, data3))