Dick Hollenbeck <dick@softplc.com> adds jtag_add_clocks() and implements those in...
[fw/openocd] / src / jtag / dummy.c
1 /***************************************************************************\r
2  *   Copyright (C) 2008 by Ã˜yvind Harboe                                   *\r
3  *   oyvind.harboe@zylin.com                                               *\r
4  *                                                                         *\r
5  *   This program is free software; you can redistribute it and/or modify  *\r
6  *   it under the terms of the GNU General Public License as published by  *\r
7  *   the Free Software Foundation; either version 2 of the License, or     *\r
8  *   (at your option) any later version.                                   *\r
9  *                                                                         *\r
10  *   This program is distributed in the hope that it will be useful,       *\r
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
13  *   GNU General Public License for more details.                          *\r
14  *                                                                         *\r
15  *   You should have received a copy of the GNU General Public License     *\r
16  *   along with this program; if not, write to the                         *\r
17  *   Free Software Foundation, Inc.,                                       *\r
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
19  ***************************************************************************/\r
20 #ifdef HAVE_CONFIG_H\r
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include "replacements.h"\r
25 \r
26 #include "jtag.h"\r
27 #include "bitbang.h"\r
28 \r
29 \r
30 /* my private tap controller state, which tracks state for calling code */\r
31 static tap_state_t dummy_state = TAP_RESET;\r
32 \r
33 static int dummy_clock;         /* edge detector */\r
34 \r
35 static int clock_count;         /* count clocks in any stable state, only stable states */\r
36 \r
37 \r
38 static tap_state_t tap_state_transition(tap_state_t cur_state, int tms);\r
39 \r
40 static u32 dummy_data;\r
41 \r
42 \r
43 int dummy_speed(int speed);\r
44 int dummy_register_commands(struct command_context_s *cmd_ctx);\r
45 int dummy_init(void);\r
46 int dummy_quit(void);\r
47 static int dummy_khz(int khz, int *jtag_speed);\r
48 static int dummy_speed_div(int speed, int *khz);\r
49 \r
50 \r
51 /* The dummy driver is used to easily check the code path\r
52  * where the target is unresponsive.\r
53  */\r
54 jtag_interface_t dummy_interface =\r
55 {\r
56         .name = "dummy",\r
57 \r
58         .execute_queue = bitbang_execute_queue,\r
59 \r
60         .speed = dummy_speed,\r
61         .register_commands = dummy_register_commands,\r
62         .khz = dummy_khz,\r
63         .speed_div = dummy_speed_div,\r
64 \r
65         .init = dummy_init,\r
66         .quit = dummy_quit,\r
67 };\r
68 \r
69 int dummy_read(void);\r
70 void dummy_write(int tck, int tms, int tdi);\r
71 void dummy_reset(int trst, int srst);\r
72 void dummy_led(int on);\r
73 \r
74 bitbang_interface_t dummy_bitbang =\r
75 {\r
76         .read = dummy_read,\r
77         .write = dummy_write,\r
78         .reset = dummy_reset,\r
79         .blink = dummy_led\r
80 };\r
81 \r
82 int dummy_read(void)\r
83 {\r
84         int data = 1 & dummy_data;\r
85         dummy_data = (dummy_data >> 1) | (1<<31);\r
86         return data;\r
87 }\r
88 \r
89 \r
90 void dummy_write(int tck, int tms, int tdi)\r
91 {\r
92         /* TAP standard: "state transitions occur on rising edge of clock" */\r
93         if( tck != dummy_clock )\r
94         {\r
95                 if( tck )\r
96                 {\r
97                         int old_state = dummy_state;\r
98                         dummy_state = tap_state_transition( old_state, tms );\r
99 \r
100                         if( old_state != dummy_state )\r
101                         {\r
102                                 if( clock_count )\r
103                                 {\r
104                                         LOG_DEBUG("dummy_tap: %d stable clocks", clock_count);\r
105                                         clock_count = 0;\r
106                                 }\r
107 \r
108                                 LOG_DEBUG("dummy_tap: %s", jtag_state_name(dummy_state) );\r
109 \r
110 #if defined(DEBUG)\r
111                                 if(dummy_state == TAP_DRCAPTURE)\r
112                                         dummy_data = 0x01255043;\r
113 #endif\r
114                         }\r
115                         else\r
116                         {\r
117                                 /* this is a stable state clock edge, no change of state here,\r
118                                  * simply increment clock_count for subsequent logging\r
119                                  */\r
120                                 ++clock_count;\r
121                         }\r
122                 }\r
123                 dummy_clock = tck;\r
124         }\r
125 }\r
126 \r
127 void dummy_reset(int trst, int srst)\r
128 {\r
129         dummy_clock = 0;\r
130 \r
131         if (trst || (srst && (jtag_reset_config & RESET_SRST_PULLS_TRST)))\r
132                 dummy_state = TAP_RESET;\r
133 \r
134         LOG_DEBUG("reset to: %s", jtag_state_name(dummy_state) );\r
135 }\r
136 \r
137 static int dummy_khz(int khz, int *jtag_speed)\r
138 {\r
139         if (khz==0)\r
140         {\r
141                 *jtag_speed=0;\r
142         }\r
143         else\r
144         {\r
145                 *jtag_speed=64000/khz;\r
146         }\r
147         return ERROR_OK;\r
148 }\r
149 \r
150 static int dummy_speed_div(int speed, int *khz)\r
151 {\r
152         if (speed==0)\r
153         {\r
154                 *khz = 0;\r
155         }\r
156         else\r
157         {\r
158                 *khz=64000/speed;\r
159         }\r
160 \r
161         return ERROR_OK;\r
162 }\r
163 \r
164 int dummy_speed(int speed)\r
165 {\r
166         return ERROR_OK;\r
167 }\r
168 \r
169 int dummy_register_commands(struct command_context_s *cmd_ctx)\r
170 {\r
171         return ERROR_OK;\r
172 }\r
173 \r
174 int dummy_init(void)\r
175 {\r
176         bitbang_interface = &dummy_bitbang;\r
177 \r
178         return ERROR_OK;\r
179 }\r
180 \r
181 int dummy_quit(void)\r
182 {\r
183         return ERROR_OK;\r
184 }\r
185 \r
186 void dummy_led(int on)\r
187 {\r
188 }\r
189 \r
190 \r
191 /**\r
192  * Function tap_state_transition\r
193  * takes a current TAP state and returns the next state according to the tms value.\r
194  *\r
195  * Even though there is code to duplicate this elsewhere, we do it here a little\r
196  * differently just to get a second opinion, i.e. a verification, on state tracking\r
197  * in that other logic. Plus array lookups without index checking are no favorite thing.\r
198  * This is educational for developers new to TAP controllers.\r
199  */\r
200 static tap_state_t tap_state_transition(tap_state_t cur_state, int tms)\r
201 {\r
202         tap_state_t new_state;\r
203 \r
204         if (tms)\r
205         {\r
206                 switch (cur_state)\r
207                 {\r
208                 case TAP_RESET:\r
209                         new_state = cur_state;\r
210                         break;\r
211                 case TAP_IDLE:\r
212                 case TAP_DRUPDATE:\r
213                 case TAP_IRUPDATE:\r
214                         new_state = TAP_DRSELECT;\r
215                         break;\r
216                 case TAP_DRSELECT:\r
217                         new_state = TAP_IRSELECT;\r
218                         break;\r
219                 case TAP_DRCAPTURE:\r
220                 case TAP_DRSHIFT:\r
221                         new_state = TAP_DREXIT1;\r
222                         break;\r
223                 case TAP_DREXIT1:\r
224                 case TAP_DREXIT2:\r
225                         new_state = TAP_DRUPDATE;\r
226                         break;\r
227                 case TAP_DRPAUSE:\r
228                         new_state = TAP_DREXIT2;\r
229                         break;\r
230                 case TAP_IRSELECT:\r
231                         new_state = TAP_RESET;\r
232                         break;\r
233                 case TAP_IRCAPTURE:\r
234                 case TAP_IRSHIFT:\r
235                         new_state = TAP_IREXIT1;\r
236                         break;\r
237                 case TAP_IREXIT1:\r
238                 case TAP_IREXIT2:\r
239                         new_state = TAP_IRUPDATE;\r
240                         break;\r
241                 case TAP_IRPAUSE:\r
242                         new_state = TAP_IREXIT2;\r
243                         break;\r
244                 default:\r
245                         LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );\r
246                         exit(1);\r
247                         break;\r
248                 }\r
249         }\r
250         else\r
251         {\r
252                 switch (cur_state)\r
253                 {\r
254                 case TAP_RESET:\r
255                 case TAP_IDLE:\r
256                 case TAP_DRUPDATE:\r
257                 case TAP_IRUPDATE:\r
258                         new_state = TAP_IDLE;\r
259                         break;\r
260                 case TAP_DRSELECT:\r
261                         new_state = TAP_DRCAPTURE;\r
262                         break;\r
263                 case TAP_DRCAPTURE:\r
264                 case TAP_DRSHIFT:\r
265                 case TAP_DREXIT2:\r
266                         new_state = TAP_DRSHIFT;\r
267                         break;\r
268                 case TAP_DREXIT1:\r
269                 case TAP_DRPAUSE:\r
270                         new_state = TAP_DRPAUSE;\r
271                         break;\r
272                 case TAP_IRSELECT:\r
273                         new_state = TAP_IRCAPTURE;\r
274                         break;\r
275                 case TAP_IRCAPTURE:\r
276                 case TAP_IRSHIFT:\r
277                 case TAP_IREXIT2:\r
278                         new_state = TAP_IRSHIFT;\r
279                         break;\r
280                 case TAP_IREXIT1:\r
281                 case TAP_IRPAUSE:\r
282                         new_state = TAP_IRPAUSE;\r
283                         break;\r
284                 default:\r
285                         LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );\r
286                         exit(1);\r
287                         break;\r
288                 }\r
289         }\r
290 \r
291         return new_state;\r
292 }\r