1 /***************************************************************************
2 * Copyright (C) 2011 by Martin Schmoelzer *
3 * <martin.schmoelzer@student.tuwien.ac.at> *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
29 /** Delay value for SCAN operations with less than maximum TCK frequency */
32 /** Delay value for CLOCK_TCK operations */
35 /** Delay value for CLOCK_TMS operations with less than maximum frequency */
39 * Perform JTAG SCAN-IN operation at maximum TCK frequency.
41 * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
42 * stored in the EP2 IN buffer.
44 * @param out_offset offset in OUT2BUF where payload data starts
46 void jtag_scan_in(u8 out_offset, u8 in_offset)
48 u8 scan_size_bytes, bits_last_byte;
49 u8 tms_count_start, tms_count_end;
50 u8 tms_sequence_start, tms_sequence_end;
55 /* Get parameters from OUT2BUF */
56 scan_size_bytes = OUT2BUF[out_offset];
57 bits_last_byte = OUT2BUF[out_offset + 1];
58 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
59 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
60 tms_sequence_start = OUT2BUF[out_offset + 3];
61 tms_sequence_end = OUT2BUF[out_offset + 4];
63 if (tms_count_start > 0) {
64 jtag_clock_tms(tms_count_start, tms_sequence_start);
67 outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
69 /* Shift all bytes except the last byte */
70 for (i = 0; i < scan_size_bytes - 1; i++) {
73 for (j = 0; j < 8; j++) {
74 OUTB = outb_buffer; /* TCK changes here */
75 OUTB = (outb_buffer | PIN_TCK);
76 tdo_data = tdo_data >> 1;
83 /* Copy TDO data to IN2BUF */
84 IN2BUF[i + in_offset] = tdo_data;
89 /* Shift the last byte */
90 for (j = 0; j < bits_last_byte; j++) {
91 /* Assert TMS signal if requested and this is the last bit */
92 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
93 outb_buffer |= PIN_TMS;
95 tms_sequence_end = tms_sequence_end >> 1;
98 OUTB = outb_buffer; /* TCK change here */
99 OUTB = (outb_buffer | PIN_TCK);
100 tdo_data = tdo_data >> 1;
106 tdo_data = tdo_data >> (8 - bits_last_byte);
108 /* Copy TDO data to IN2BUF */
109 IN2BUF[i + in_offset] = tdo_data;
111 /* Move to correct end state */
112 if (tms_count_end > 0) {
113 jtag_clock_tms(tms_count_end, tms_sequence_end);
118 * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
120 * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
121 * data is not sampled.
122 * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
124 * @param out_offset offset in OUT2BUF where payload data starts
126 void jtag_scan_out(u8 out_offset)
128 u8 scan_size_bytes, bits_last_byte;
129 u8 tms_count_start, tms_count_end;
130 u8 tms_sequence_start, tms_sequence_end;
135 /* Get parameters from OUT2BUF */
136 scan_size_bytes = OUT2BUF[out_offset];
137 bits_last_byte = OUT2BUF[out_offset + 1];
138 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
139 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
140 tms_sequence_start = OUT2BUF[out_offset + 3];
141 tms_sequence_end = OUT2BUF[out_offset + 4];
143 if (tms_count_start > 0) {
144 jtag_clock_tms(tms_count_start, tms_sequence_start);
147 outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
149 /* Shift all bytes except the last byte */
150 for (i = 0; i < scan_size_bytes - 1; i++) {
151 tdi_data = OUT2BUF[i + out_offset + 5];
153 for (j = 0; j < 8; j++) {
154 if (tdi_data & 0x01) {
155 outb_buffer |= PIN_TDI;
158 outb_buffer &= ~PIN_TDI;
161 OUTB = outb_buffer; /* TDI and TCK change here */
162 tdi_data = tdi_data >> 1;
163 OUTB = (outb_buffer | PIN_TCK);
167 tdi_data = OUT2BUF[i + out_offset + 5];
169 /* Shift the last byte */
170 for (j = 0; j < bits_last_byte; j++) {
171 if (tdi_data & 0x01) {
172 outb_buffer |= PIN_TDI;
175 outb_buffer &= ~PIN_TDI;
178 /* Assert TMS signal if requested and this is the last bit */
179 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
180 outb_buffer |= PIN_TMS;
182 tms_sequence_end = tms_sequence_end >> 1;
185 OUTB = outb_buffer; /* TDI and TCK change here */
186 tdi_data = tdi_data >> 1;
187 OUTB = (outb_buffer | PIN_TCK);
190 /* Move to correct end state */
191 if (tms_count_end > 0) {
192 jtag_clock_tms(tms_count_end, tms_sequence_end);
197 * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
199 * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
200 * data is sampled and stored in the EP2 IN buffer.
201 * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
203 * @param out_offset offset in OUT2BUF where payload data starts
205 void jtag_scan_io(u8 out_offset, u8 in_offset)
207 u8 scan_size_bytes, bits_last_byte;
208 u8 tms_count_start, tms_count_end;
209 u8 tms_sequence_start, tms_sequence_end;
210 u8 tdi_data, tdo_data, i, j;
214 /* Get parameters from OUT2BUF */
215 scan_size_bytes = OUT2BUF[out_offset];
216 bits_last_byte = OUT2BUF[out_offset + 1];
217 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
218 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
219 tms_sequence_start = OUT2BUF[out_offset + 3];
220 tms_sequence_end = OUT2BUF[out_offset + 4];
222 if (tms_count_start > 0) {
223 jtag_clock_tms(tms_count_start, tms_sequence_start);
226 outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
228 /* Shift all bytes except the last byte */
229 for (i = 0; i < scan_size_bytes - 1; i++) {
230 tdi_data = OUT2BUF[i + out_offset + 5];
233 for (j = 0; j < 8; j++) {
234 if (tdi_data & 0x01) {
235 outb_buffer |= PIN_TDI;
238 outb_buffer &= ~PIN_TDI;
241 OUTB = outb_buffer; /* TDI and TCK change here */
242 tdi_data = tdi_data >> 1;
243 OUTB = (outb_buffer | PIN_TCK);
244 tdo_data = tdo_data >> 1;
251 /* Copy TDO data to IN2BUF */
252 IN2BUF[i + in_offset] = tdo_data;
255 tdi_data = OUT2BUF[i + out_offset + 5];
258 /* Shift the last byte */
259 for (j = 0; j < bits_last_byte; j++) {
260 if (tdi_data & 0x01) {
261 outb_buffer |= PIN_TDI;
264 outb_buffer &= ~PIN_TDI;
267 /* Assert TMS signal if requested and this is the last bit */
268 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
269 outb_buffer |= PIN_TMS;
271 tms_sequence_end = tms_sequence_end >> 1;
274 OUTB = outb_buffer; /* TDI and TCK change here */
275 tdi_data = tdi_data >> 1;
276 OUTB = (outb_buffer | PIN_TCK);
277 tdo_data = tdo_data >> 1;
283 tdo_data = tdo_data >> (8 - bits_last_byte);
285 /* Copy TDO data to IN2BUF */
286 IN2BUF[i + in_offset] = tdo_data;
288 /* Move to correct end state */
289 if (tms_count_end > 0) {
290 jtag_clock_tms(tms_count_end, tms_sequence_end);
295 * Generate TCK clock cycles.
297 * @param count number of TCK clock cyclces to generate.
299 void jtag_clock_tck(u16 count)
304 for ( i = 0; i < count; i++ ) {
306 for(j = 0; j < delay_tck; j++);
309 for(j = 0; j < delay_tck; j++);
314 * Perform TAP-FSM state transitions at maximum TCK frequency.
316 * @param count the number of state transitions to perform.
317 * @param sequence the TMS pin levels for each state transition, starting with
318 * the least-significant bit.
320 void jtag_clock_tms(u8 count, u8 sequence)
322 volatile u8 outb_buffer;
325 outb_buffer = OUTB & ~(PIN_TCK);
327 for ( i = 0; i < count; i++ ) {
328 /* Set TMS pin according to sequence parameter */
329 if ( sequence & 0x1 ) {
330 outb_buffer |= PIN_TMS;
333 outb_buffer &= ~PIN_TMS;
337 sequence = sequence >> 1;
338 OUTB = outb_buffer | PIN_TCK;
343 * Perform TAP-FSM state transitions at less than maximum TCK frequency.
345 * @param count the number of state transitions to perform.
346 * @param sequence the TMS pin levels for each state transition, starting with
347 * the least-significant bit.
349 void jtag_slow_clock_tms(u8 count, u8 sequence)
355 * Get current JTAG signal states.
357 * @return a 16-bit integer where the most-significant byte contains the state
358 * of the JTAG input signals and the least-significant byte cotains the state
359 * of the JTAG output signals.
361 u16 jtag_get_signals(void)
363 u8 input_signal_state, output_signal_state;
365 input_signal_state = 0;
366 output_signal_state = 0;
368 /* Get states of input pins */
370 input_signal_state |= SIGNAL_TDO;
373 input_signal_state |= SIGNAL_BRKOUT;
376 input_signal_state |= SIGNAL_TRAP;
379 /* Using RTCK this way would be extremely slow,
380 * implemented only for the sake of completeness */
381 input_signal_state |= SIGNAL_RTCK;
384 /* Get states of output pins */
385 output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT;
387 return ((u16)input_signal_state << 8) | ((u16)output_signal_state);
391 * Set state of JTAG output signals.
393 * @param low signals which should be de-asserted.
394 * @param high signals which should be asserted.
396 void jtag_set_signals(u8 low, u8 high)
398 OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
399 OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
403 * Configure TCK delay parameters.
405 * @param scan number of delay cycles in shift operations.
406 * @param tck number of delay cycles in clock_tck operations.
407 * @param tms number of delay cycles in clock_tms operations.
409 void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms)