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