jtag.c (8252B)
1 /* jtag transport 2 * 3 * Copyright 2015 Brian Swetland <swetland@frotz.net> 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <string.h> 19 #include <stdlib.h> 20 21 #include <fw/types.h> 22 23 #include "debugger.h" 24 #include "rswdp.h" 25 #include "jtag.h" 26 27 static const char *JSTATE[17] = { 28 "RESET", "IDLE", "DRSELECT", "DRCAPTURE", 29 "DRSHIFT", "DREXIT1", "DRPAUSE", "DREXIT2", 30 "DRUPDATE", "IRSELECT", "IRCAPTURE", "IRSHIFT", 31 "IREXIT1", "IRPAUSE", "IREXIT1", "IRUPDATE", 32 "UNKNOWN" 33 }; 34 35 static u64 ONES = 0xFFFFFFFFFFFFFFFFUL; 36 37 void jtag_txn_init(jtag_txn *tx) { 38 memset(tx, 0, sizeof(jtag_txn)); 39 tx->state = JTAG_UNKNOWN; 40 } 41 42 int jtag_txn_exec(jtag_txn *t) { 43 unsigned n, off = 0; 44 int r; 45 if (t->status) { 46 return t->status; 47 } 48 //xprintf(XCORE, "jtag exec %d bits\n", t->txc); 49 r = jtag_io(t->txc, t->tms, t->tdi, t->tdo); 50 for (n = 0; n < t->rxc; n++) { 51 unsigned count = t->bits[n]; 52 if (t->ptr[n]) { 53 unsigned bit = 0; 54 u64 x = 0; 55 while (count > 0) { 56 x |= ((u64) ((t->tdo[off >> 5] >> (off & 31)) & 1)) << bit; 57 off++; 58 bit++; 59 count--; 60 } 61 *t->ptr[n] = x; 62 } else { 63 off += count; 64 } 65 } 66 return r; 67 } 68 69 void jtag_txn_append(jtag_txn *t, unsigned count, u64 tms, u64 tdi, u64 *tdo) { 70 unsigned txc = t->txc; 71 72 if (txc == JTAG_MAX_RESULTS) { 73 xprintf(XCORE, "jtag append txn overflow\n"); 74 t->status = -1; 75 return; 76 } 77 if ((count > 64) || ((JTAG_MAX_BITS - t->bitcount) < count)) { 78 xprintf(XCORE, "jtag append bits overflow\n"); 79 t->status = -1; 80 return; 81 } 82 t->bitcount += count; 83 84 // xprintf(XCORE, "jtag append %2d bits %016lx %016lx\n", count, tms, tdi); 85 86 t->ptr[t->rxc] = tdo; 87 t->bits[t->rxc] = count; 88 t->rxc++; 89 90 while (count > 0) { 91 t->tms[txc >> 5] |= (tms & 1) << (txc & 31); 92 t->tdi[txc >> 5] |= (tdi & 1) << (txc & 31); 93 tms >>= 1; 94 tdi >>= 1; 95 count--; 96 txc++; 97 } 98 t->txc = txc; 99 } 100 101 void jtag_txn_move(jtag_txn *t, unsigned dst) { 102 if (t->state == dst) { 103 // nothing to do 104 return; 105 } 106 switch (t->state) { 107 case JTAG_IDLE: 108 if (dst == JTAG_IRSHIFT) { 109 // Idle -> SelDR -> SelIR -> CapIR -> ShiftIR 110 // 1 1 0 0 111 jtag_txn_append(t, 4, 0b0011, 0b1111, NULL); 112 } else if (dst == JTAG_DRSHIFT) { 113 // Idle -> SelDR -> CapDR -> ShiftDR 114 // 1 0 0 115 jtag_txn_append(t, 3, 0b001, 0b111, NULL); 116 } else { 117 goto oops; 118 } 119 break; 120 case JTAG_DRPAUSE: 121 case JTAG_IRPAUSE: 122 if (dst == JTAG_IRSHIFT) { 123 // PauseDR -> Exit2DR -> UpDR -> SelDR -> SelIR -> CapIR -> ShiftIR 124 // PauseIR -> Exit2IR -> UpIR -> SelDR -> SelIR -> CapIR -> ShiftIR 125 // 1 1 1 1 0 0 126 jtag_txn_append(t, 6, 0b001111, 0b111111, NULL); 127 } else if (dst == JTAG_DRSHIFT) { 128 // PauseDR -> Exit2DR -> UpDR -> SelDR -> CapDR -> ShiftDR 129 // PauseIR -> Exit2IR -> UpIR -> SelDR -> CapDR -> ShiftDR 130 // 1 1 1 0 0 131 jtag_txn_append(t, 5, 0b00111, 0b11111, NULL); 132 } else if (dst == JTAG_IDLE) { 133 // PauseDR -> Exit2DR -> UpDR -> Idle 134 // PauseIR -> Exit2IR -> UpIR -> Idle 135 // 1 1 0 136 jtag_txn_append(t, 3, 0b011, 0b111, NULL); 137 } else { 138 goto oops; 139 } 140 break; 141 case JTAG_DREXIT1: 142 case JTAG_IREXIT1: 143 if (dst == JTAG_IRSHIFT) { 144 // Exit1DR -> UpDR -> SelDR -> SelIR -> CapIR -> ShiftIR 145 // Exit1IR -> UpIR -> SelDR -> SelIR -> CapIR -> ShiftIR 146 // 1 1 1 0 0 147 jtag_txn_append(t, 5, 0b00111, 0b11111, NULL); 148 } else if (dst == JTAG_DRSHIFT) { 149 // Exit1DR -> UpDR -> SelDR -> CapDR -> ShiftDR 150 // Exit1IR -> UpIR -> SelDR -> CapDR -> ShiftDR 151 // 1 1 0 0 152 jtag_txn_append(t, 4, 0b0011, 0b1111, NULL); 153 } else if (dst == JTAG_IDLE) { 154 // Exit1DR -> UpDR -> Idle 155 // Exit1IR -> UpIR -> Idle 156 // 1 0 157 jtag_txn_append(t, 2, 0b01, 0b11, NULL); 158 } else if (dst == JTAG_DRPAUSE) { 159 // Exit1DR -> PauseDR 160 // Exit1IR -> PauseIR 161 // 0 162 jtag_txn_append(t, 1, 0b0, 0b1, NULL); 163 } else { 164 goto oops; 165 } 166 break; 167 default: 168 oops: 169 xprintf(XCORE, "jtag move from %s to %s unsupported\n", 170 JSTATE[t->state], JSTATE[dst]); 171 t->status = -1; 172 t->state = JTAG_UNKNOWN; 173 return; 174 } 175 t->state = dst; 176 } 177 178 void jtag_cjtag_open(jtag_txn *t) { 179 jtag_txn_move(t, JTAG_IDLE); 180 // Idle -> SelDR -> CapDR -> Exit1DR -> UpDR ZBS#1 181 // 1 0 1 1 182 // UpDR -> SelDR -> CapDR -> Exit1DR -> UpDR ZBS#2 183 // 1 0 1 1 184 // UpDR -> SelDR -> CapDR -> ShiftDR -> Exit1DR -> UpDR -> Idle One Bit Scan 185 // 1 0 0 1 1 0 186 jtag_txn_append(t, 14, 0b01100111011101, 0, NULL); 187 } 188 189 void jtag_cjtag_cmd(jtag_txn *t, unsigned cp0, unsigned cp1) { 190 jtag_txn_move(t, JTAG_IDLE); 191 if ((cp0 > 15) || (cp1 > 15)) { 192 xprintf(XCORE, "jtag invalid cjtag parameters %d %d\n", cp0, cp1); 193 t->status = -1; 194 return; 195 } 196 if (cp0 == 0) { 197 // Idle -> SelDR -> CapDR -> Exit1DR -> UpDR -> Idle 198 // 1 0 1 1 0 199 jtag_txn_append(t, 5, 0b01101, 0, NULL); 200 } else { 201 // Idle -> SelDR -> CapDR -> ShiftDR (xN) -> Exit1DR -> UpDR -> Idle 202 // 1 0 0 1 1 0 203 jtag_txn_append(t, 5 + cp0, ((0b011 << cp0) << 2) | 0b01, 0, NULL); 204 } 205 if (cp1 == 0) { 206 // Idle -> SelDR -> CapDR -> Exit1DR -> UpDR -> Idle 207 // 1 0 1 1 0 208 jtag_txn_append(t, 5, 0b01101, 0, NULL); 209 } else { 210 // Idle -> SelDR -> CapDR -> ShiftDR (xN) -> Exit1DR -> UpDR -> Idle 211 // 1 0 0 1 1 0 212 jtag_txn_append(t, 5 + cp1, ((0b011 << cp1) << 2) | 0b01, 0, NULL); 213 } 214 } 215 216 void jtag_any_to_rti(jtag_txn *t) { 217 // 5x TMS=1 is sufficient, but throw a couple more in for luck 218 jtag_txn_append(t, 9, 0xFF, 0x1FF, NULL); 219 t->state = JTAG_IDLE; 220 } 221 222 static void _jtag_shiftir(jtag_txn *t, unsigned count, u64 tx, u64 *rx) { 223 // all bits but last, tms=0 (stay in ShiftIR), last tms=1 (goto Exit1IR) 224 if (t->state != JTAG_IRSHIFT) { 225 xprintf(XCORE, "jtag invalid state (%s) in shiftir\n", JSTATE[t->state]); 226 t->status = -1; 227 } 228 if (t->ir_pre) { 229 jtag_txn_append(t, t->ir_pre, 0, ONES, NULL); 230 } 231 if (t->ir_post) { 232 u64 tms = 1UL << (t->ir_post - 1); 233 jtag_txn_append(t, count, 0, tx, rx); 234 jtag_txn_append(t, t->ir_post, tms, ONES, NULL); 235 } else { 236 u64 tms = 1UL << (count - 1); 237 jtag_txn_append(t, count, tms, tx, rx); 238 } 239 t->state = JTAG_IREXIT1; 240 } 241 242 static void _jtag_shiftdr(jtag_txn *t, unsigned count, u64 tx, u64 *rx) { 243 if (t->state != JTAG_DRSHIFT) { 244 xprintf(XCORE, "jtag invalid state (%s) in shiftir\n", JSTATE[t->state]); 245 t->status = -1; 246 } 247 // all bits but last, tms=0 (stay in ShiftDR), last tms=1 (goto Exit1DR) 248 if (t->dr_pre) { 249 jtag_txn_append(t, t->dr_pre, 0, ONES, NULL); 250 } 251 if (t->dr_post) { 252 u64 tms = 1UL << (t->dr_post - 1); 253 jtag_txn_append(t, count, 0, tx, rx); 254 jtag_txn_append(t, t->dr_post, tms, ONES, NULL); 255 } else { 256 u64 tms = 1UL << (count - 1); 257 jtag_txn_append(t, count, tms, tx, rx); 258 } 259 t->state = JTAG_DREXIT1; 260 } 261 262 void jtag_ir(jtag_txn *t, unsigned count, u64 ir) { 263 jtag_txn_move(t, JTAG_IRSHIFT); 264 _jtag_shiftir(t, count, ir, NULL); 265 jtag_txn_move(t, JTAG_IDLE); 266 } 267 268 void jtag_dr(jtag_txn *t, unsigned count, u64 dr, u64 *out) { 269 jtag_txn_move(t, JTAG_DRSHIFT); 270 _jtag_shiftdr(t, count, dr, out); 271 jtag_txn_move(t, JTAG_IDLE); 272 } 273 274 void jtag_ir_p(jtag_txn *t, unsigned count, u64 ir) { 275 jtag_txn_move(t, JTAG_IRSHIFT); 276 _jtag_shiftir(t, count, ir, NULL); 277 jtag_txn_move(t, JTAG_IRPAUSE); 278 } 279 280 void jtag_dr_p(jtag_txn *t, unsigned count, u64 dr, u64 *out) { 281 jtag_txn_move(t, JTAG_DRSHIFT); 282 _jtag_shiftdr(t, count, dr, out); 283 jtag_txn_move(t, JTAG_DRPAUSE); 284 } 285 286