2ae31bc54cfdc05348286452c029d67f403a3752
[fw/openocd] / src / jtag / zy1000 / jtag_minidriver.h
1 /***************************************************************************
2  *   Copyright (C) 2007-2010 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  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
18  ***************************************************************************/
19
20 /* used to test manual mode */
21 #define TEST_MANUAL() 0
22 #define VERBOSE(a)
23
24 #if BUILD_ZY1000_MASTER
25
26 #define ZY1000_PEEK(a, b) do {b = *((volatile uint32_t *)(a)); } while (0)
27 #define ZY1000_POKE(a, b) do {*((volatile uint32_t *)(a)) = b; } while (0)
28 extern volatile void *zy1000_jtag_master;
29 #define ZY1000_JTAG_BASE ((unsigned long)zy1000_jtag_master)
30
31 #else
32
33 /* redirect this to TCP/IP */
34 #define ZY1000_JTAG_BASE 0
35 extern void zy1000_tcpout(uint32_t address, uint32_t data);
36 extern uint32_t zy1000_tcpin(uint32_t address);
37 #define ZY1000_PEEK(a, b) b = zy1000_tcpin(a)
38 #define ZY1000_POKE(a, b) zy1000_tcpout(a, b)
39
40 #endif
41
42 #if BUILD_ZY1000_MASTER
43 /* FIFO empty? */
44 static inline void waitIdle(void)
45 {
46         uint32_t empty;
47         do {
48                 ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty);
49         } while ((empty & 0x100) == 0);
50 }
51
52 static inline void zy1000_flush_readqueue(void)
53 {
54         /* Not used w/hardware fifo */
55 }
56 static inline void zy1000_flush_callbackqueue(void)
57 {
58         /* Not used w/hardware fifo */
59 }
60 #else
61 extern void waitIdle(void);
62 void zy1000_flush_readqueue(void);
63 void zy1000_flush_callbackqueue(void);
64 void zy1000_jtag_add_callback4(jtag_callback_t callback,
65                 jtag_callback_data_t data0,
66                 jtag_callback_data_t data1,
67                 jtag_callback_data_t data2,
68                 jtag_callback_data_t data3);
69 void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0);
70 #endif
71
72 static inline void waitQueue(void)
73 {
74 /*      waitIdle(); */
75 }
76
77 static inline void sampleShiftRegister(void)
78 {
79 #if 0
80         uint32_t dummy;
81         waitIdle();
82         ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, dummy);
83 #endif
84 }
85
86 static inline void setCurrentState(enum tap_state state)
87 {
88         uint32_t a;
89         a = state;
90         int repeat = 0;
91         if (state == TAP_RESET) {
92                 /* The FPGA nor we know the current state of the CPU TAP */
93                 /* controller. This will move it to TAP for sure. */
94                 /*  */
95                 /* 5 should be enough here, 7 is what OpenOCD uses */
96                 repeat = 7;
97         }
98         waitQueue();
99         sampleShiftRegister();
100         ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | a);
101
102 }
103
104 /*
105  * Enter state and cause repeat transitions *out* of that state. So if the endState != state, then
106  * the transition from state to endState counts as a transition out of state.
107  */
108 static inline void shiftValueInner(const enum tap_state state,
109         const enum tap_state endState,
110         int repeat,
111         uint32_t value)
112 {
113         uint32_t a, b;
114         a = state;
115         b = endState;
116         waitQueue();
117         sampleShiftRegister();
118         ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value);
119 #if 1
120 #if TEST_MANUAL()
121         if ((state == TAP_DRSHIFT) && (endState != TAP_DRSHIFT)) {
122                 int i;
123                 setCurrentState(state);
124                 for (i = 0; i < repeat; i++) {
125                         int tms;
126                         tms = 0;
127                         if ((i == repeat-1) && (state != endState))
128                                 tms = 1;
129                                         /* shift out value */
130                         waitIdle();
131                         ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, (((value >> i)&1) << 1) | tms);
132                 }
133                 waitIdle();
134                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
135                 waitIdle();
136                 /* ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT); // set this state and things
137                  * break => expected */
138                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRPAUSE);      /* set this and things will
139                                                                          * work => expected. Not
140                                                                          * setting this is not
141                                                                          * sufficient to make things
142                                                                          * break. */
143                 setCurrentState(endState);
144         } else
145                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
146
147 #else
148         /* fast version */
149         ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
150 #endif
151 #else
152         /* maximum debug version */
153         if ((repeat > 0) && ((state == TAP_DRSHIFT) || (state == TAP_SI))) {
154                 int i;
155                 /* sample shift register for every bit. */
156                 for (i = 0; i < repeat-1; i++) {
157                         sampleShiftRegister();
158                         ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> i);
159                         ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | a);
160                 }
161                 sampleShiftRegister();
162                 ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> (repeat-1));
163                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | b);
164         } else {
165                 sampleShiftRegister();
166                 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
167         }
168         sampleShiftRegister();
169 #endif
170 }
171
172 static inline void interface_jtag_add_dr_out_core(struct jtag_tap *target_tap,
173         int num_fields,
174         const int *num_bits,
175         const uint32_t *value,
176         enum tap_state end_state)
177 {
178         enum tap_state pause_state = TAP_DRSHIFT;
179
180         struct jtag_tap *tap, *nextTap;
181         for (tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = nextTap) {
182                 nextTap = jtag_tap_next_enabled(tap);
183                 if (nextTap == NULL)
184                         pause_state = end_state;
185                 if (tap == target_tap) {
186                         int j;
187                         for (j = 0; j < (num_fields-1); j++)
188                                 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[j], value[j]);
189                         shiftValueInner(TAP_DRSHIFT, pause_state, num_bits[j], value[j]);
190                 } else {
191                         /* program the scan field to 1 bit length, and ignore it's value */
192                         shiftValueInner(TAP_DRSHIFT, pause_state, 1, 0);
193                 }
194         }
195 }
196
197 static inline void interface_jtag_add_dr_out(struct jtag_tap *target_tap,
198         int num_fields,
199         const int *num_bits,
200         const uint32_t *value,
201         enum tap_state end_state)
202 {
203
204         int singletap = (jtag_tap_next_enabled(jtag_tap_next_enabled(NULL)) == NULL);
205         if ((singletap) && (num_fields == 3)) {
206                 /* used by embeddedice_write_reg_inner() */
207                 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[0], value[0]);
208                 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[1], value[1]);
209                 shiftValueInner(TAP_DRSHIFT, end_state, num_bits[2], value[2]);
210         } else if ((singletap) && (num_fields == 2)) {
211                 /* used by arm7 code */
212                 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[0], value[0]);
213                 shiftValueInner(TAP_DRSHIFT, end_state, num_bits[1], value[1]);
214         } else
215                 interface_jtag_add_dr_out_core(target_tap, num_fields, num_bits, value, end_state);
216 }
217
218 #if BUILD_ZY1000_MASTER
219 #define interface_jtag_add_callback(callback, in) callback(in)
220 #define interface_jtag_add_callback4(callback, in, data1, data2, \
221                 data3) jtag_set_error(callback(in, data1, data2, data3))
222 #else
223 #define interface_jtag_add_callback(callback, in) zy1000_jtag_add_callback(callback, in)
224 #define interface_jtag_add_callback4(callback, in, data1, data2, data3) zy1000_jtag_add_callback4( \
225         callback, \
226         in, \
227         data1, \
228         data2, \
229         data3)
230 #endif