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