linux/drivers/misc/altera-stapl/altera-jtag.c
<<
>>
Prefs
   1/*
   2 * altera-jtag.c
   3 *
   4 * altera FPGA driver
   5 *
   6 * Copyright (C) Altera Corporation 1998-2001
   7 * Copyright (C) 2010 NetUP Inc.
   8 * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 *
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24 */
  25
  26#include <linux/delay.h>
  27#include <linux/firmware.h>
  28#include <linux/slab.h>
  29#include <misc/altera.h>
  30#include "altera-exprt.h"
  31#include "altera-jtag.h"
  32
  33#define alt_jtag_io(a, b, c)\
  34                astate->config->jtag_io(astate->config->dev, a, b, c);
  35
  36#define alt_malloc(a)   kzalloc(a, GFP_KERNEL);
  37
  38/*
  39 * This structure shows, for each JTAG state, which state is reached after
  40 * a single TCK clock cycle with TMS high or TMS low, respectively.  This
  41 * describes all possible state transitions in the JTAG state machine.
  42 */
  43struct altera_jtag_machine {
  44        enum altera_jtag_state tms_high;
  45        enum altera_jtag_state tms_low;
  46};
  47
  48static const struct altera_jtag_machine altera_transitions[] = {
  49        /* RESET     */ { RESET,        IDLE },
  50        /* IDLE      */ { DRSELECT,     IDLE },
  51        /* DRSELECT  */ { IRSELECT,     DRCAPTURE },
  52        /* DRCAPTURE */ { DREXIT1,      DRSHIFT },
  53        /* DRSHIFT   */ { DREXIT1,      DRSHIFT },
  54        /* DREXIT1   */ { DRUPDATE,     DRPAUSE },
  55        /* DRPAUSE   */ { DREXIT2,      DRPAUSE },
  56        /* DREXIT2   */ { DRUPDATE,     DRSHIFT },
  57        /* DRUPDATE  */ { DRSELECT,     IDLE },
  58        /* IRSELECT  */ { RESET,        IRCAPTURE },
  59        /* IRCAPTURE */ { IREXIT1,      IRSHIFT },
  60        /* IRSHIFT   */ { IREXIT1,      IRSHIFT },
  61        /* IREXIT1   */ { IRUPDATE,     IRPAUSE },
  62        /* IRPAUSE   */ { IREXIT2,      IRPAUSE },
  63        /* IREXIT2   */ { IRUPDATE,     IRSHIFT },
  64        /* IRUPDATE  */ { DRSELECT,     IDLE }
  65};
  66
  67/*
  68 * This table contains the TMS value to be used to take the NEXT STEP on
  69 * the path to the desired state.  The array index is the current state,
  70 * and the bit position is the desired endstate.  To find out which state
  71 * is used as the intermediate state, look up the TMS value in the
  72 * altera_transitions[] table.
  73 */
  74static const u16 altera_jtag_path_map[16] = {
  75        /* RST  RTI     SDRS    CDR     SDR     E1DR    PDR     E2DR */
  76        0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF,
  77        /* UDR  SIRS    CIR     SIR     E1IR    PIR     E2IR    UIR */
  78        0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD
  79};
  80
  81/* Flag bits for alt_jtag_io() function */
  82#define TMS_HIGH   1
  83#define TMS_LOW    0
  84#define TDI_HIGH   1
  85#define TDI_LOW    0
  86#define READ_TDO   1
  87#define IGNORE_TDO 0
  88
  89int altera_jinit(struct altera_state *astate)
  90{
  91        struct altera_jtag *js = &astate->js;
  92
  93        /* initial JTAG state is unknown */
  94        js->jtag_state = ILLEGAL_JTAG_STATE;
  95
  96        /* initialize to default state */
  97        js->drstop_state = IDLE;
  98        js->irstop_state = IDLE;
  99        js->dr_pre  = 0;
 100        js->dr_post = 0;
 101        js->ir_pre  = 0;
 102        js->ir_post = 0;
 103        js->dr_length    = 0;
 104        js->ir_length    = 0;
 105
 106        js->dr_pre_data  = NULL;
 107        js->dr_post_data = NULL;
 108        js->ir_pre_data  = NULL;
 109        js->ir_post_data = NULL;
 110        js->dr_buffer    = NULL;
 111        js->ir_buffer    = NULL;
 112
 113        return 0;
 114}
 115
 116int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state)
 117{
 118        js->drstop_state = state;
 119
 120        return 0;
 121}
 122
 123int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state)
 124{
 125        js->irstop_state = state;
 126
 127        return 0;
 128}
 129
 130int altera_set_dr_pre(struct altera_jtag *js,
 131                                u32 count, u32 start_index,
 132                                u8 *preamble_data)
 133{
 134        int status = 0;
 135        u32 i;
 136        u32 j;
 137
 138        if (count > js->dr_pre) {
 139                kfree(js->dr_pre_data);
 140                js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
 141                if (js->dr_pre_data == NULL)
 142                        status = -ENOMEM;
 143                else
 144                        js->dr_pre = count;
 145        } else
 146                js->dr_pre = count;
 147
 148        if (status == 0) {
 149                for (i = 0; i < count; ++i) {
 150                        j = i + start_index;
 151
 152                        if (preamble_data == NULL)
 153                                js->dr_pre_data[i >> 3] |= (1 << (i & 7));
 154                        else {
 155                                if (preamble_data[j >> 3] & (1 << (j & 7)))
 156                                        js->dr_pre_data[i >> 3] |=
 157                                                        (1 << (i & 7));
 158                                else
 159                                        js->dr_pre_data[i >> 3] &=
 160                                                        ~(u32)(1 << (i & 7));
 161
 162                        }
 163                }
 164        }
 165
 166        return status;
 167}
 168
 169int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index,
 170                                                        u8 *preamble_data)
 171{
 172        int status = 0;
 173        u32 i;
 174        u32 j;
 175
 176        if (count > js->ir_pre) {
 177                kfree(js->ir_pre_data);
 178                js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
 179                if (js->ir_pre_data == NULL)
 180                        status = -ENOMEM;
 181                else
 182                        js->ir_pre = count;
 183
 184        } else
 185                js->ir_pre = count;
 186
 187        if (status == 0) {
 188                for (i = 0; i < count; ++i) {
 189                        j = i + start_index;
 190                        if (preamble_data == NULL)
 191                                js->ir_pre_data[i >> 3] |= (1 << (i & 7));
 192                        else {
 193                                if (preamble_data[j >> 3] & (1 << (j & 7)))
 194                                        js->ir_pre_data[i >> 3] |=
 195                                                        (1 << (i & 7));
 196                                else
 197                                        js->ir_pre_data[i >> 3] &=
 198                                                        ~(u32)(1 << (i & 7));
 199
 200                        }
 201                }
 202        }
 203
 204        return status;
 205}
 206
 207int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index,
 208                                                u8 *postamble_data)
 209{
 210        int status = 0;
 211        u32 i;
 212        u32 j;
 213
 214        if (count > js->dr_post) {
 215                kfree(js->dr_post_data);
 216                js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3);
 217
 218                if (js->dr_post_data == NULL)
 219                        status = -ENOMEM;
 220                else
 221                        js->dr_post = count;
 222
 223        } else
 224                js->dr_post = count;
 225
 226        if (status == 0) {
 227                for (i = 0; i < count; ++i) {
 228                        j = i + start_index;
 229
 230                        if (postamble_data == NULL)
 231                                js->dr_post_data[i >> 3] |= (1 << (i & 7));
 232                        else {
 233                                if (postamble_data[j >> 3] & (1 << (j & 7)))
 234                                        js->dr_post_data[i >> 3] |=
 235                                                                (1 << (i & 7));
 236                                else
 237                                        js->dr_post_data[i >> 3] &=
 238                                            ~(u32)(1 << (i & 7));
 239
 240                        }
 241                }
 242        }
 243
 244        return status;
 245}
 246
 247int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index,
 248                                                u8 *postamble_data)
 249{
 250        int status = 0;
 251        u32 i;
 252        u32 j;
 253
 254        if (count > js->ir_post) {
 255                kfree(js->ir_post_data);
 256                js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3);
 257                if (js->ir_post_data == NULL)
 258                        status = -ENOMEM;
 259                else
 260                        js->ir_post = count;
 261
 262        } else
 263                js->ir_post = count;
 264
 265        if (status != 0)
 266                return status;
 267
 268        for (i = 0; i < count; ++i) {
 269                j = i + start_index;
 270
 271                if (postamble_data == NULL)
 272                        js->ir_post_data[i >> 3] |= (1 << (i & 7));
 273                else {
 274                        if (postamble_data[j >> 3] & (1 << (j & 7)))
 275                                js->ir_post_data[i >> 3] |= (1 << (i & 7));
 276                        else
 277                                js->ir_post_data[i >> 3] &=
 278                                    ~(u32)(1 << (i & 7));
 279
 280                }
 281        }
 282
 283        return status;
 284}
 285
 286static void altera_jreset_idle(struct altera_state *astate)
 287{
 288        struct altera_jtag *js = &astate->js;
 289        int i;
 290        /* Go to Test Logic Reset (no matter what the starting state may be) */
 291        for (i = 0; i < 5; ++i)
 292                alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
 293
 294        /* Now step to Run Test / Idle */
 295        alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
 296        js->jtag_state = IDLE;
 297}
 298
 299int altera_goto_jstate(struct altera_state *astate,
 300                                        enum altera_jtag_state state)
 301{
 302        struct altera_jtag *js = &astate->js;
 303        int tms;
 304        int count = 0;
 305        int status = 0;
 306
 307        if (js->jtag_state == ILLEGAL_JTAG_STATE)
 308                /* initialize JTAG chain to known state */
 309                altera_jreset_idle(astate);
 310
 311        if (js->jtag_state == state) {
 312                /*
 313                 * We are already in the desired state.
 314                 * If it is a stable state, loop here.
 315                 * Otherwise do nothing (no clock cycles).
 316                 */
 317                if ((state == IDLE) || (state == DRSHIFT) ||
 318                        (state == DRPAUSE) || (state == IRSHIFT) ||
 319                                (state == IRPAUSE)) {
 320                        alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
 321                } else if (state == RESET)
 322                        alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
 323
 324        } else {
 325                while ((js->jtag_state != state) && (count < 9)) {
 326                        /* Get TMS value to take a step toward desired state */
 327                        tms = (altera_jtag_path_map[js->jtag_state] &
 328                                                        (1 << state))
 329                                                        ? TMS_HIGH : TMS_LOW;
 330
 331                        /* Take a step */
 332                        alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
 333
 334                        if (tms)
 335                                js->jtag_state =
 336                                        altera_transitions[js->jtag_state].tms_high;
 337                        else
 338                                js->jtag_state =
 339                                        altera_transitions[js->jtag_state].tms_low;
 340
 341                        ++count;
 342                }
 343        }
 344
 345        if (js->jtag_state != state)
 346                status = -EREMOTEIO;
 347
 348        return status;
 349}
 350
 351int altera_wait_cycles(struct altera_state *astate,
 352                                        s32 cycles,
 353                                        enum altera_jtag_state wait_state)
 354{
 355        struct altera_jtag *js = &astate->js;
 356        int tms;
 357        s32 count;
 358        int status = 0;
 359
 360        if (js->jtag_state != wait_state)
 361                status = altera_goto_jstate(astate, wait_state);
 362
 363        if (status == 0) {
 364                /*
 365                 * Set TMS high to loop in RESET state
 366                 * Set TMS low to loop in any other stable state
 367                 */
 368                tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW;
 369
 370                for (count = 0L; count < cycles; count++)
 371                        alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
 372
 373        }
 374
 375        return status;
 376}
 377
 378int altera_wait_msecs(struct altera_state *astate,
 379                        s32 microseconds, enum altera_jtag_state wait_state)
 380/*
 381 * Causes JTAG hardware to sit in the specified stable
 382 * state for the specified duration of real time.  If
 383 * no JTAG operations have been performed yet, then only
 384 * a delay is performed.  This permits the WAIT USECS
 385 * statement to be used in VECTOR programs without causing
 386 * any JTAG operations.
 387 * Returns 0 for success, else appropriate error code.
 388 */
 389{
 390        struct altera_jtag *js = &astate->js;
 391        int status = 0;
 392
 393        if ((js->jtag_state != ILLEGAL_JTAG_STATE) &&
 394            (js->jtag_state != wait_state))
 395                status = altera_goto_jstate(astate, wait_state);
 396
 397        if (status == 0)
 398                /* Wait for specified time interval */
 399                udelay(microseconds);
 400
 401        return status;
 402}
 403
 404static void altera_concatenate_data(u8 *buffer,
 405                                u8 *preamble_data,
 406                                u32 preamble_count,
 407                                u8 *target_data,
 408                                u32 start_index,
 409                                u32 target_count,
 410                                u8 *postamble_data,
 411                                u32 postamble_count)
 412/*
 413 * Copies preamble data, target data, and postamble data
 414 * into one buffer for IR or DR scans.
 415 */
 416{
 417        u32 i, j, k;
 418
 419        for (i = 0L; i < preamble_count; ++i) {
 420                if (preamble_data[i >> 3L] & (1L << (i & 7L)))
 421                        buffer[i >> 3L] |= (1L << (i & 7L));
 422                else
 423                        buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
 424
 425        }
 426
 427        j = start_index;
 428        k = preamble_count + target_count;
 429        for (; i < k; ++i, ++j) {
 430                if (target_data[j >> 3L] & (1L << (j & 7L)))
 431                        buffer[i >> 3L] |= (1L << (i & 7L));
 432                else
 433                        buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
 434
 435        }
 436
 437        j = 0L;
 438        k = preamble_count + target_count + postamble_count;
 439        for (; i < k; ++i, ++j) {
 440                if (postamble_data[j >> 3L] & (1L << (j & 7L)))
 441                        buffer[i >> 3L] |= (1L << (i & 7L));
 442                else
 443                        buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
 444
 445        }
 446}
 447
 448static int alt_jtag_drscan(struct altera_state *astate,
 449                        int start_state,
 450                        int count,
 451                        u8 *tdi,
 452                        u8 *tdo)
 453{
 454        int i = 0;
 455        int tdo_bit = 0;
 456        int status = 1;
 457
 458        /* First go to DRSHIFT state */
 459        switch (start_state) {
 460        case 0:                                         /* IDLE */
 461                alt_jtag_io(1, 0, 0);   /* DRSELECT */
 462                alt_jtag_io(0, 0, 0);   /* DRCAPTURE */
 463                alt_jtag_io(0, 0, 0);   /* DRSHIFT */
 464                break;
 465
 466        case 1:                                         /* DRPAUSE */
 467                alt_jtag_io(1, 0, 0);   /* DREXIT2 */
 468                alt_jtag_io(1, 0, 0);   /* DRUPDATE */
 469                alt_jtag_io(1, 0, 0);   /* DRSELECT */
 470                alt_jtag_io(0, 0, 0);   /* DRCAPTURE */
 471                alt_jtag_io(0, 0, 0);   /* DRSHIFT */
 472                break;
 473
 474        case 2:                                         /* IRPAUSE */
 475                alt_jtag_io(1, 0, 0);   /* IREXIT2 */
 476                alt_jtag_io(1, 0, 0);   /* IRUPDATE */
 477                alt_jtag_io(1, 0, 0);   /* DRSELECT */
 478                alt_jtag_io(0, 0, 0);   /* DRCAPTURE */
 479                alt_jtag_io(0, 0, 0);   /* DRSHIFT */
 480                break;
 481
 482        default:
 483                status = 0;
 484        }
 485
 486        if (status) {
 487                /* loop in the SHIFT-DR state */
 488                for (i = 0; i < count; i++) {
 489                        tdo_bit = alt_jtag_io(
 490                                        (i == count - 1),
 491                                        tdi[i >> 3] & (1 << (i & 7)),
 492                                        (tdo != NULL));
 493
 494                        if (tdo != NULL) {
 495                                if (tdo_bit)
 496                                        tdo[i >> 3] |= (1 << (i & 7));
 497                                else
 498                                        tdo[i >> 3] &= ~(u32)(1 << (i & 7));
 499
 500                        }
 501                }
 502
 503                alt_jtag_io(0, 0, 0);   /* DRPAUSE */
 504        }
 505
 506        return status;
 507}
 508
 509static int alt_jtag_irscan(struct altera_state *astate,
 510                    int start_state,
 511                    int count,
 512                    u8 *tdi,
 513                    u8 *tdo)
 514{
 515        int i = 0;
 516        int tdo_bit = 0;
 517        int status = 1;
 518
 519        /* First go to IRSHIFT state */
 520        switch (start_state) {
 521        case 0:                                         /* IDLE */
 522                alt_jtag_io(1, 0, 0);   /* DRSELECT */
 523                alt_jtag_io(1, 0, 0);   /* IRSELECT */
 524                alt_jtag_io(0, 0, 0);   /* IRCAPTURE */
 525                alt_jtag_io(0, 0, 0);   /* IRSHIFT */
 526                break;
 527
 528        case 1:                                         /* DRPAUSE */
 529                alt_jtag_io(1, 0, 0);   /* DREXIT2 */
 530                alt_jtag_io(1, 0, 0);   /* DRUPDATE */
 531                alt_jtag_io(1, 0, 0);   /* DRSELECT */
 532                alt_jtag_io(1, 0, 0);   /* IRSELECT */
 533                alt_jtag_io(0, 0, 0);   /* IRCAPTURE */
 534                alt_jtag_io(0, 0, 0);   /* IRSHIFT */
 535                break;
 536
 537        case 2:                                         /* IRPAUSE */
 538                alt_jtag_io(1, 0, 0);   /* IREXIT2 */
 539                alt_jtag_io(1, 0, 0);   /* IRUPDATE */
 540                alt_jtag_io(1, 0, 0);   /* DRSELECT */
 541                alt_jtag_io(1, 0, 0);   /* IRSELECT */
 542                alt_jtag_io(0, 0, 0);   /* IRCAPTURE */
 543                alt_jtag_io(0, 0, 0);   /* IRSHIFT */
 544                break;
 545
 546        default:
 547                status = 0;
 548        }
 549
 550        if (status) {
 551                /* loop in the SHIFT-IR state */
 552                for (i = 0; i < count; i++) {
 553                        tdo_bit = alt_jtag_io(
 554                                      (i == count - 1),
 555                                      tdi[i >> 3] & (1 << (i & 7)),
 556                                      (tdo != NULL));
 557                        if (tdo != NULL) {
 558                                if (tdo_bit)
 559                                        tdo[i >> 3] |= (1 << (i & 7));
 560                                else
 561                                        tdo[i >> 3] &= ~(u32)(1 << (i & 7));
 562
 563                        }
 564                }
 565
 566                alt_jtag_io(0, 0, 0);   /* IRPAUSE */
 567        }
 568
 569        return status;
 570}
 571
 572static void altera_extract_target_data(u8 *buffer,
 573                                u8 *target_data,
 574                                u32 start_index,
 575                                u32 preamble_count,
 576                                u32 target_count)
 577/*
 578 * Copies target data from scan buffer, filtering out
 579 * preamble and postamble data.
 580 */
 581{
 582        u32 i;
 583        u32 j;
 584        u32 k;
 585
 586        j = preamble_count;
 587        k = start_index + target_count;
 588        for (i = start_index; i < k; ++i, ++j) {
 589                if (buffer[j >> 3] & (1 << (j & 7)))
 590                        target_data[i >> 3] |= (1 << (i & 7));
 591                else
 592                        target_data[i >> 3] &= ~(u32)(1 << (i & 7));
 593
 594        }
 595}
 596
 597int altera_irscan(struct altera_state *astate,
 598                                u32 count,
 599                                u8 *tdi_data,
 600                                u32 start_index)
 601/* Shifts data into instruction register */
 602{
 603        struct altera_jtag *js = &astate->js;
 604        int start_code = 0;
 605        u32 alloc_chars = 0;
 606        u32 shift_count = js->ir_pre + count + js->ir_post;
 607        int status = 0;
 608        enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
 609
 610        switch (js->jtag_state) {
 611        case ILLEGAL_JTAG_STATE:
 612        case RESET:
 613        case IDLE:
 614                start_code = 0;
 615                start_state = IDLE;
 616                break;
 617
 618        case DRSELECT:
 619        case DRCAPTURE:
 620        case DRSHIFT:
 621        case DREXIT1:
 622        case DRPAUSE:
 623        case DREXIT2:
 624        case DRUPDATE:
 625                start_code = 1;
 626                start_state = DRPAUSE;
 627                break;
 628
 629        case IRSELECT:
 630        case IRCAPTURE:
 631        case IRSHIFT:
 632        case IREXIT1:
 633        case IRPAUSE:
 634        case IREXIT2:
 635        case IRUPDATE:
 636                start_code = 2;
 637                start_state = IRPAUSE;
 638                break;
 639
 640        default:
 641                status = -EREMOTEIO;
 642                break;
 643        }
 644
 645        if (status == 0)
 646                if (js->jtag_state != start_state)
 647                        status = altera_goto_jstate(astate, start_state);
 648
 649        if (status == 0) {
 650                if (shift_count > js->ir_length) {
 651                        alloc_chars = (shift_count + 7) >> 3;
 652                        kfree(js->ir_buffer);
 653                        js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
 654                        if (js->ir_buffer == NULL)
 655                                status = -ENOMEM;
 656                        else
 657                                js->ir_length = alloc_chars * 8;
 658
 659                }
 660        }
 661
 662        if (status == 0) {
 663                /*
 664                 * Copy preamble data, IR data,
 665                 * and postamble data into a buffer
 666                 */
 667                altera_concatenate_data(js->ir_buffer,
 668                                        js->ir_pre_data,
 669                                        js->ir_pre,
 670                                        tdi_data,
 671                                        start_index,
 672                                        count,
 673                                        js->ir_post_data,
 674                                        js->ir_post);
 675                /* Do the IRSCAN */
 676                alt_jtag_irscan(astate,
 677                                start_code,
 678                                shift_count,
 679                                js->ir_buffer,
 680                                NULL);
 681
 682                /* alt_jtag_irscan() always ends in IRPAUSE state */
 683                js->jtag_state = IRPAUSE;
 684        }
 685
 686        if (status == 0)
 687                if (js->irstop_state != IRPAUSE)
 688                        status = altera_goto_jstate(astate, js->irstop_state);
 689
 690
 691        return status;
 692}
 693
 694int altera_swap_ir(struct altera_state *astate,
 695                            u32 count,
 696                            u8 *in_data,
 697                            u32 in_index,
 698                            u8 *out_data,
 699                            u32 out_index)
 700/* Shifts data into instruction register, capturing output data */
 701{
 702        struct altera_jtag *js = &astate->js;
 703        int start_code = 0;
 704        u32 alloc_chars = 0;
 705        u32 shift_count = js->ir_pre + count + js->ir_post;
 706        int status = 0;
 707        enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
 708
 709        switch (js->jtag_state) {
 710        case ILLEGAL_JTAG_STATE:
 711        case RESET:
 712        case IDLE:
 713                start_code = 0;
 714                start_state = IDLE;
 715                break;
 716
 717        case DRSELECT:
 718        case DRCAPTURE:
 719        case DRSHIFT:
 720        case DREXIT1:
 721        case DRPAUSE:
 722        case DREXIT2:
 723        case DRUPDATE:
 724                start_code = 1;
 725                start_state = DRPAUSE;
 726                break;
 727
 728        case IRSELECT:
 729        case IRCAPTURE:
 730        case IRSHIFT:
 731        case IREXIT1:
 732        case IRPAUSE:
 733        case IREXIT2:
 734        case IRUPDATE:
 735                start_code = 2;
 736                start_state = IRPAUSE;
 737                break;
 738
 739        default:
 740                status = -EREMOTEIO;
 741                break;
 742        }
 743
 744        if (status == 0)
 745                if (js->jtag_state != start_state)
 746                        status = altera_goto_jstate(astate, start_state);
 747
 748        if (status == 0) {
 749                if (shift_count > js->ir_length) {
 750                        alloc_chars = (shift_count + 7) >> 3;
 751                        kfree(js->ir_buffer);
 752                        js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
 753                        if (js->ir_buffer == NULL)
 754                                status = -ENOMEM;
 755                        else
 756                                js->ir_length = alloc_chars * 8;
 757
 758                }
 759        }
 760
 761        if (status == 0) {
 762                /*
 763                 * Copy preamble data, IR data,
 764                 * and postamble data into a buffer
 765                 */
 766                altera_concatenate_data(js->ir_buffer,
 767                                        js->ir_pre_data,
 768                                        js->ir_pre,
 769                                        in_data,
 770                                        in_index,
 771                                        count,
 772                                        js->ir_post_data,
 773                                        js->ir_post);
 774
 775                /* Do the IRSCAN */
 776                alt_jtag_irscan(astate,
 777                                start_code,
 778                                shift_count,
 779                                js->ir_buffer,
 780                                js->ir_buffer);
 781
 782                /* alt_jtag_irscan() always ends in IRPAUSE state */
 783                js->jtag_state = IRPAUSE;
 784        }
 785
 786        if (status == 0)
 787                if (js->irstop_state != IRPAUSE)
 788                        status = altera_goto_jstate(astate, js->irstop_state);
 789
 790
 791        if (status == 0)
 792                /* Now extract the returned data from the buffer */
 793                altera_extract_target_data(js->ir_buffer,
 794                                        out_data, out_index,
 795                                        js->ir_pre, count);
 796
 797        return status;
 798}
 799
 800int altera_drscan(struct altera_state *astate,
 801                                u32 count,
 802                                u8 *tdi_data,
 803                                u32 start_index)
 804/* Shifts data into data register (ignoring output data) */
 805{
 806        struct altera_jtag *js = &astate->js;
 807        int start_code = 0;
 808        u32 alloc_chars = 0;
 809        u32 shift_count = js->dr_pre + count + js->dr_post;
 810        int status = 0;
 811        enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
 812
 813        switch (js->jtag_state) {
 814        case ILLEGAL_JTAG_STATE:
 815        case RESET:
 816        case IDLE:
 817                start_code = 0;
 818                start_state = IDLE;
 819                break;
 820
 821        case DRSELECT:
 822        case DRCAPTURE:
 823        case DRSHIFT:
 824        case DREXIT1:
 825        case DRPAUSE:
 826        case DREXIT2:
 827        case DRUPDATE:
 828                start_code = 1;
 829                start_state = DRPAUSE;
 830                break;
 831
 832        case IRSELECT:
 833        case IRCAPTURE:
 834        case IRSHIFT:
 835        case IREXIT1:
 836        case IRPAUSE:
 837        case IREXIT2:
 838        case IRUPDATE:
 839                start_code = 2;
 840                start_state = IRPAUSE;
 841                break;
 842
 843        default:
 844                status = -EREMOTEIO;
 845                break;
 846        }
 847
 848        if (status == 0)
 849                if (js->jtag_state != start_state)
 850                        status = altera_goto_jstate(astate, start_state);
 851
 852        if (status == 0) {
 853                if (shift_count > js->dr_length) {
 854                        alloc_chars = (shift_count + 7) >> 3;
 855                        kfree(js->dr_buffer);
 856                        js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
 857                        if (js->dr_buffer == NULL)
 858                                status = -ENOMEM;
 859                        else
 860                                js->dr_length = alloc_chars * 8;
 861
 862                }
 863        }
 864
 865        if (status == 0) {
 866                /*
 867                 * Copy preamble data, DR data,
 868                 * and postamble data into a buffer
 869                 */
 870                altera_concatenate_data(js->dr_buffer,
 871                                        js->dr_pre_data,
 872                                        js->dr_pre,
 873                                        tdi_data,
 874                                        start_index,
 875                                        count,
 876                                        js->dr_post_data,
 877                                        js->dr_post);
 878                /* Do the DRSCAN */
 879                alt_jtag_drscan(astate, start_code, shift_count,
 880                                js->dr_buffer, NULL);
 881                /* alt_jtag_drscan() always ends in DRPAUSE state */
 882                js->jtag_state = DRPAUSE;
 883        }
 884
 885        if (status == 0)
 886                if (js->drstop_state != DRPAUSE)
 887                        status = altera_goto_jstate(astate, js->drstop_state);
 888
 889        return status;
 890}
 891
 892int altera_swap_dr(struct altera_state *astate, u32 count,
 893                                u8 *in_data, u32 in_index,
 894                                u8 *out_data, u32 out_index)
 895/* Shifts data into data register, capturing output data */
 896{
 897        struct altera_jtag *js = &astate->js;
 898        int start_code = 0;
 899        u32 alloc_chars = 0;
 900        u32 shift_count = js->dr_pre + count + js->dr_post;
 901        int status = 0;
 902        enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
 903
 904        switch (js->jtag_state) {
 905        case ILLEGAL_JTAG_STATE:
 906        case RESET:
 907        case IDLE:
 908                start_code = 0;
 909                start_state = IDLE;
 910                break;
 911
 912        case DRSELECT:
 913        case DRCAPTURE:
 914        case DRSHIFT:
 915        case DREXIT1:
 916        case DRPAUSE:
 917        case DREXIT2:
 918        case DRUPDATE:
 919                start_code = 1;
 920                start_state = DRPAUSE;
 921                break;
 922
 923        case IRSELECT:
 924        case IRCAPTURE:
 925        case IRSHIFT:
 926        case IREXIT1:
 927        case IRPAUSE:
 928        case IREXIT2:
 929        case IRUPDATE:
 930                start_code = 2;
 931                start_state = IRPAUSE;
 932                break;
 933
 934        default:
 935                status = -EREMOTEIO;
 936                break;
 937        }
 938
 939        if (status == 0)
 940                if (js->jtag_state != start_state)
 941                        status = altera_goto_jstate(astate, start_state);
 942
 943        if (status == 0) {
 944                if (shift_count > js->dr_length) {
 945                        alloc_chars = (shift_count + 7) >> 3;
 946                        kfree(js->dr_buffer);
 947                        js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
 948
 949                        if (js->dr_buffer == NULL)
 950                                status = -ENOMEM;
 951                        else
 952                                js->dr_length = alloc_chars * 8;
 953
 954                }
 955        }
 956
 957        if (status == 0) {
 958                /*
 959                 * Copy preamble data, DR data,
 960                 * and postamble data into a buffer
 961                 */
 962                altera_concatenate_data(js->dr_buffer,
 963                                js->dr_pre_data,
 964                                js->dr_pre,
 965                                in_data,
 966                                in_index,
 967                                count,
 968                                js->dr_post_data,
 969                                js->dr_post);
 970
 971                /* Do the DRSCAN */
 972                alt_jtag_drscan(astate,
 973                                start_code,
 974                                shift_count,
 975                                js->dr_buffer,
 976                                js->dr_buffer);
 977
 978                /* alt_jtag_drscan() always ends in DRPAUSE state */
 979                js->jtag_state = DRPAUSE;
 980        }
 981
 982        if (status == 0)
 983                if (js->drstop_state != DRPAUSE)
 984                        status = altera_goto_jstate(astate, js->drstop_state);
 985
 986        if (status == 0)
 987                /* Now extract the returned data from the buffer */
 988                altera_extract_target_data(js->dr_buffer,
 989                                        out_data,
 990                                        out_index,
 991                                        js->dr_pre,
 992                                        count);
 993
 994        return status;
 995}
 996
 997void altera_free_buffers(struct altera_state *astate)
 998{
 999        struct altera_jtag *js = &astate->js;
1000        /* If the JTAG interface was used, reset it to TLR */
1001        if (js->jtag_state != ILLEGAL_JTAG_STATE)
1002                altera_jreset_idle(astate);
1003
1004        kfree(js->dr_pre_data);
1005        js->dr_pre_data = NULL;
1006
1007        kfree(js->dr_post_data);
1008        js->dr_post_data = NULL;
1009
1010        kfree(js->dr_buffer);
1011        js->dr_buffer = NULL;
1012
1013        kfree(js->ir_pre_data);
1014        js->ir_pre_data = NULL;
1015
1016        kfree(js->ir_post_data);
1017        js->ir_post_data = NULL;
1018
1019        kfree(js->ir_buffer);
1020        js->ir_buffer = NULL;
1021}
1022