Spy-Bi-Wire support, from examples by Mark rages.
[goodfet] / firmware / apps / jtag / jtagxscale.c
1 /*! 
2   \file jtagxscale.c
3   \author Dave Huseby <dave@linuxprogrammer.org>
4   \brief Intel XScale JTAG
5 */
6
7 #include "platform.h"
8 #include "command.h"
9 #include "jtag.h"
10 #include "jtagxscale.h"
11
12 #define JTAGXSCALE_APP
13
14 /* Handles XScale JTAG commands.  Forwards others to JTAG. */
15 void jtag_xscale_handle_fn( uint8_t const app,
16                                                         uint8_t const verb,
17                                                         uint32_t const len);
18
19 // define the jtag xscale app's app_t
20 app_t const jtagxscale_app = {
21
22         /* app number */
23         JTAGXSCALE,
24
25         /* handle fn */
26         jtag_xscale_handle_fn,
27
28         /* name */
29         "JTAG XScale",
30
31         /* desc */
32         "\tThe JTAG Xscale app extends the JTAG app adding support\n"
33         "\tfor JTAG'ing Intel XScale devices.\n"
34 };
35
36
37 /* From the Intel XScale Core Developer's Manual:
38  *
39  * The Intel XScale® core provides test features compatible with IEEE Standard
40  * Test Access Port and Boundary Scan Architecture (IEEE Std. 1149.1). These 
41  * features include a TAP controller, a 5 or 7 bit instruction register, and 
42  * test data registers to support software debug. The size of the instruction 
43  * register depends on which variant of the Intel XScale® core is being used.
44  * This can be found out by examining the CoreGen field of Coprocessor 15, ID 
45  * Register (bits 15:13). (See Table 7-4, "ID Register" on page 7-81 for more 
46  * details.) A CoreGen value of 0x1 means the JTAG instruction register size 
47  * is 5 bits and a CoreGen value of 0x2 means the JTAG instruction register 
48  * size is 7 bits.
49  *
50  */
51
52 /* NOTE: I heavily cribbed from the ARM7TDMI jtag implementation. Credit where
53  * credit is due. */
54
55 /* this handles shifting arbitrary length bit strings into the instruction
56  * register and clocking out bits while leaving the JTAG state machine in a
57  * known state. it also handle bit swapping. */
58 unsigned long jtag_xscale_shift_n(unsigned long word,
59                                   unsigned char nbits,
60                                   unsigned char flags)
61 {
62     unsigned int bit;
63     unsigned long high = 1;
64     unsigned long mask;
65
66     for (bit = (nbits - 1) / 8; bit > 0; bit--)
67         high <<= 8;
68     
69     high <<= ((nbits - 1) % 8);
70
71     mask = high - 1;
72
73     if (flags & LSB) 
74     {
75         /* clock the bits into the IR from LSB to MSB order */
76         for (bit = nbits; bit > 0; bit--) 
77         {
78             /* write MOSI on trailing edge of previous clock */
79             if (word & 1)
80             {
81                 SETMOSI;
82             }
83             else
84             {
85                 CLRMOSI;
86             }
87             word >>= 1;
88
89             if (bit == 1 && !(flags & NOEND))
90                 SETTMS; /* TMS high on last bit to exit. */
91
92             /* tick tock the clock line */
93             XTT;
94
95             /* read MISO on trailing edge */
96             if (READMISO)
97             {
98                 word += (high);
99             }
100         }
101     } 
102     else 
103     {
104         /* clock the bits into the IR from MSB to LSB order */
105         for (bit = nbits; bit > 0; bit--) 
106         {
107             /* write MOSI on trailing edge of previous clock */
108             if (word & high)
109             {
110                 SETMOSI;
111             }
112             else
113             {
114                 CLRMOSI;
115             }
116             word = (word & mask) << 1;
117
118             if (bit == 1 && !(flags & NOEND))
119                 SETTMS;//TMS high on last bit to exit.
120
121             /* tick tock the clock line */
122             XTT;
123
124             /* read MISO on trailing edge */
125             word |= (READMISO);
126         }
127     }
128
129     SETMOSI;
130
131     if (!(flags & NOEND))
132     {
133         /* exit state */
134         XTT;
135
136         /* update state */
137         if (!(flags & NORETIDLE))
138         {
139             CLRTMS;
140             XTT;
141         }
142     }
143
144     return word;
145 }
146
147
148 /* this handles shifting in the IDCODE instruction and shifting the result
149  * out the TDO and return it. */
150 unsigned long jtag_xscale_idcode()
151 {
152     /* NOTE: this assumes that we're in the run-test-idle state */
153
154     /* get into the shift-ir state */
155     SHIFT_IR;
156
157     /* shift the ID code instruction into the IR and return to run-test-idle */
158     jtag_xscale_shift_n(XSCALE_IR_IDCODE, 5, LSB);
159
160     /* get into the shift-dr state */
161     SHIFT_DR;
162
163     /* now clock out the 32 bit ID code and return back to run-test-idle */
164     return jtag_xscale_shift_n(0, 32, LSB);
165 }
166
167 /* Handles XScale JTAG commands.  Forwards others to JTAG. */
168 void jtag_xscale_handle_fn( uint8_t const app,
169                                                         uint8_t const verb,
170                                                         uint32_t const len)
171 {    
172     switch(verb) 
173     {
174         /*
175          * Standard Commands
176          */
177         case SETUP:
178
179             /* set up the pin I/O for JTAG */
180             jtagsetup();
181
182             /* reset to run-test-idle state */
183             RUN_TEST_IDLE;
184
185             /* send back OK */
186             txdata(app, OK, 0);
187
188             break;
189
190         case START:
191         case STOP:
192         case PEEK:
193         case POKE:
194         case READ:
195         case WRITE:
196         default:
197  
198             /* send back OK */
199             txdata(app, OK, 0);
200
201             break;
202
203         /*
204          * XScale Commands
205          */
206         case XSCALE_GET_CHIP_ID:
207
208             /* reset to run-test-idle state */
209             RUN_TEST_IDLE;
210
211             /* put the ID code in the data buffer */
212             cmddatalong[0] = jtag_xscale_idcode();
213
214             /* send it back to the client */
215             txdata(app,verb,4);
216
217             break;
218     }
219 }