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