1 /* 2 * Copyright (C) Marvell International Ltd. and its affiliates 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <i2c.h> 9 #include <spl.h> 10 #include <asm/io.h> 11 #include <asm/arch/cpu.h> 12 #include <asm/arch/soc.h> 13 14 #include "ddr3_hw_training.h" 15 #include "xor.h" 16 #include "xor_regs.h" 17 18 static void ddr3_flush_l1_line(u32 line); 19 20 extern u32 pbs_pattern[2][LEN_16BIT_PBS_PATTERN]; 21 extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN]; 22 #if defined(MV88F78X60) 23 extern u32 pbs_pattern_64b[2][LEN_PBS_PATTERN]; 24 #endif 25 extern u32 pbs_dq_mapping[PUP_NUM_64BIT][DQ_NUM]; 26 27 #if defined(MV88F78X60) || defined(MV88F672X) 28 /* PBS locked dq (per pup) */ 29 u32 pbs_locked_dq[MAX_PUP_NUM][DQ_NUM] = { { 0 } }; 30 u32 pbs_locked_dm[MAX_PUP_NUM] = { 0 }; 31 u32 pbs_locked_value[MAX_PUP_NUM][DQ_NUM] = { { 0 } }; 32 33 int per_bit_data[MAX_PUP_NUM][DQ_NUM]; 34 #endif 35 36 static u32 sdram_data[LEN_KILLER_PATTERN] __aligned(32) = { 0 }; 37 38 static struct crc_dma_desc dma_desc __aligned(32) = { 0 }; 39 40 #define XOR_TIMEOUT 0x8000000 41 42 struct xor_channel_t { 43 struct crc_dma_desc *desc; 44 unsigned long desc_phys_addr; 45 }; 46 47 #define XOR_CAUSE_DONE_MASK(chan) ((0x1 | 0x2) << (chan * 16)) 48 49 void xor_waiton_eng(int chan) 50 { 51 int timeout; 52 53 timeout = 0; 54 while (!(reg_read(XOR_CAUSE_REG(XOR_UNIT(chan))) & 55 XOR_CAUSE_DONE_MASK(XOR_CHAN(chan)))) { 56 if (timeout > XOR_TIMEOUT) 57 goto timeout; 58 59 timeout++; 60 } 61 62 timeout = 0; 63 while (mv_xor_state_get(chan) != MV_IDLE) { 64 if (timeout > XOR_TIMEOUT) 65 goto timeout; 66 67 timeout++; 68 } 69 70 /* Clear int */ 71 reg_write(XOR_CAUSE_REG(XOR_UNIT(chan)), 72 ~(XOR_CAUSE_DONE_MASK(XOR_CHAN(chan)))); 73 74 timeout: 75 return; 76 } 77 78 static int special_compare_pattern(u32 uj) 79 { 80 if ((uj == 30) || (uj == 31) || (uj == 61) || (uj == 62) || 81 (uj == 93) || (uj == 94) || (uj == 126) || (uj == 127)) 82 return 1; 83 84 return 0; 85 } 86 87 /* 88 * Compare code extracted as its used by multiple functions. This 89 * reduces code-size and makes it easier to maintain it. Additionally 90 * the code is not indented that much and therefore easier to read. 91 */ 92 static void compare_pattern_v1(u32 uj, u32 *pup, u32 *pattern, 93 u32 pup_groups, int debug_dqs) 94 { 95 u32 val; 96 u32 uk; 97 u32 var1; 98 u32 var2; 99 __maybe_unused u32 dq; 100 101 if (((sdram_data[uj]) != (pattern[uj])) && (*pup != 0xFF)) { 102 for (uk = 0; uk < PUP_NUM_32BIT; uk++) { 103 val = CMP_BYTE_SHIFT * uk; 104 var1 = ((sdram_data[uj] >> val) & CMP_BYTE_MASK); 105 var2 = ((pattern[uj] >> val) & CMP_BYTE_MASK); 106 107 if (var1 != var2) { 108 *pup |= (1 << (uk + (PUP_NUM_32BIT * 109 (uj % pup_groups)))); 110 111 #ifdef MV_DEBUG_DQS 112 if (!debug_dqs) 113 continue; 114 115 for (dq = 0; dq < DQ_NUM; dq++) { 116 val = uk + (PUP_NUM_32BIT * 117 (uj % pup_groups)); 118 if (((var1 >> dq) & 0x1) != 119 ((var2 >> dq) & 0x1)) 120 per_bit_data[val][dq] = 1; 121 else 122 per_bit_data[val][dq] = 0; 123 } 124 #endif 125 } 126 } 127 } 128 } 129 130 static void compare_pattern_v2(u32 uj, u32 *pup, u32 *pattern) 131 { 132 u32 val; 133 u32 uk; 134 u32 var1; 135 u32 var2; 136 137 if (((sdram_data[uj]) != (pattern[uj])) && (*pup != 0x3)) { 138 /* Found error */ 139 for (uk = 0; uk < PUP_NUM_32BIT; uk++) { 140 val = CMP_BYTE_SHIFT * uk; 141 var1 = (sdram_data[uj] >> val) & CMP_BYTE_MASK; 142 var2 = (pattern[uj] >> val) & CMP_BYTE_MASK; 143 if (var1 != var2) 144 *pup |= (1 << (uk % PUP_NUM_16BIT)); 145 } 146 } 147 } 148 149 /* 150 * Name: ddr3_sdram_compare 151 * Desc: Execute compare per PUP 152 * Args: unlock_pup Bit array of the unlock pups 153 * new_locked_pup Output bit array of the pups with failed compare 154 * pattern Pattern to compare 155 * pattern_len Length of pattern (in bytes) 156 * sdram_offset offset address to the SDRAM 157 * write write to the SDRAM before read 158 * mask compare pattern with mask; 159 * mask_pattern Mask to compare pattern 160 * 161 * Notes: 162 * Returns: MV_OK if success, other error code if fail. 163 */ 164 int ddr3_sdram_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup, 165 u32 *new_locked_pup, u32 *pattern, 166 u32 pattern_len, u32 sdram_offset, int write, 167 int mask, u32 *mask_pattern, 168 int special_compare) 169 { 170 u32 uj; 171 __maybe_unused u32 pup_groups; 172 __maybe_unused u32 dq; 173 174 #if !defined(MV88F67XX) 175 if (dram_info->num_of_std_pups == PUP_NUM_64BIT) 176 pup_groups = 2; 177 else 178 pup_groups = 1; 179 #endif 180 181 ddr3_reset_phy_read_fifo(); 182 183 /* Check if need to write to sdram before read */ 184 if (write == 1) 185 ddr3_dram_sram_burst((u32)pattern, sdram_offset, pattern_len); 186 187 ddr3_dram_sram_burst(sdram_offset, (u32)sdram_data, pattern_len); 188 189 /* Compare read result to write */ 190 for (uj = 0; uj < pattern_len; uj++) { 191 if (special_compare && special_compare_pattern(uj)) 192 continue; 193 194 #if defined(MV88F78X60) || defined(MV88F672X) 195 compare_pattern_v1(uj, new_locked_pup, pattern, pup_groups, 1); 196 #elif defined(MV88F67XX) 197 compare_pattern_v2(uj, new_locked_pup, pattern); 198 #endif 199 } 200 201 return MV_OK; 202 } 203 204 #if defined(MV88F78X60) || defined(MV88F672X) 205 /* 206 * Name: ddr3_sdram_dm_compare 207 * Desc: Execute compare per PUP 208 * Args: unlock_pup Bit array of the unlock pups 209 * new_locked_pup Output bit array of the pups with failed compare 210 * pattern Pattern to compare 211 * pattern_len Length of pattern (in bytes) 212 * sdram_offset offset address to the SDRAM 213 * write write to the SDRAM before read 214 * mask compare pattern with mask; 215 * mask_pattern Mask to compare pattern 216 * 217 * Notes: 218 * Returns: MV_OK if success, other error code if fail. 219 */ 220 int ddr3_sdram_dm_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup, 221 u32 *new_locked_pup, u32 *pattern, 222 u32 sdram_offset) 223 { 224 u32 uj, uk, var1, var2, pup_groups; 225 u32 val; 226 u32 pup = 0; 227 228 if (dram_info->num_of_std_pups == PUP_NUM_64BIT) 229 pup_groups = 2; 230 else 231 pup_groups = 1; 232 233 ddr3_dram_sram_burst((u32)pattern, SDRAM_PBS_TX_OFFS, 234 LEN_PBS_PATTERN); 235 ddr3_dram_sram_burst(SDRAM_PBS_TX_OFFS, (u32)sdram_data, 236 LEN_PBS_PATTERN); 237 238 /* Validate the correctness of the results */ 239 for (uj = 0; uj < LEN_PBS_PATTERN; uj++) 240 compare_pattern_v1(uj, &pup, pattern, pup_groups, 0); 241 242 /* Test the DM Signals */ 243 *(u32 *)(SDRAM_PBS_TX_OFFS + 0x10) = 0x12345678; 244 *(u32 *)(SDRAM_PBS_TX_OFFS + 0x14) = 0x12345678; 245 246 sdram_data[0] = *(u32 *)(SDRAM_PBS_TX_OFFS + 0x10); 247 sdram_data[1] = *(u32 *)(SDRAM_PBS_TX_OFFS + 0x14); 248 249 for (uj = 0; uj < 2; uj++) { 250 if (((sdram_data[uj]) != (pattern[uj])) && 251 (*new_locked_pup != 0xFF)) { 252 for (uk = 0; uk < PUP_NUM_32BIT; uk++) { 253 val = CMP_BYTE_SHIFT * uk; 254 var1 = ((sdram_data[uj] >> val) & CMP_BYTE_MASK); 255 var2 = ((pattern[uj] >> val) & CMP_BYTE_MASK); 256 if (var1 != var2) { 257 *new_locked_pup |= (1 << (uk + 258 (PUP_NUM_32BIT * (uj % pup_groups)))); 259 *new_locked_pup |= pup; 260 } 261 } 262 } 263 } 264 265 return MV_OK; 266 } 267 268 /* 269 * Name: ddr3_sdram_pbs_compare 270 * Desc: Execute SRAM compare per PUP and DQ. 271 * Args: pup_locked bit array of locked pups 272 * is_tx Indicate whether Rx or Tx 273 * pbs_pattern_idx Index of PBS pattern 274 * pbs_curr_val The PBS value 275 * pbs_lock_val The value to set to locked PBS 276 * skew_array Global array to update with the compare results 277 * ai_unlock_pup_dq_array bit array of the locked / unlocked pups per dq. 278 * Notes: 279 * Returns: MV_OK if success, other error code if fail. 280 */ 281 int ddr3_sdram_pbs_compare(MV_DRAM_INFO *dram_info, u32 pup_locked, 282 int is_tx, u32 pbs_pattern_idx, 283 u32 pbs_curr_val, u32 pbs_lock_val, 284 u32 *skew_array, u8 *unlock_pup_dq_array, 285 u32 ecc) 286 { 287 /* bit array failed dq per pup for current compare */ 288 u32 pbs_write_pup[DQ_NUM] = { 0 }; 289 u32 update_pup; /* pup as HW convention */ 290 u32 max_pup; /* maximal pup index */ 291 u32 pup_addr; 292 u32 ui, dq, pup; 293 int var1, var2; 294 u32 sdram_offset, pup_groups, tmp_pup; 295 u32 *pattern_ptr; 296 u32 val; 297 298 /* Choose pattern */ 299 switch (dram_info->ddr_width) { 300 #if defined(MV88F672X) 301 case 16: 302 pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx]; 303 break; 304 #endif 305 case 32: 306 pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx]; 307 break; 308 #if defined(MV88F78X60) 309 case 64: 310 pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx]; 311 break; 312 #endif 313 default: 314 return MV_FAIL; 315 } 316 317 max_pup = dram_info->num_of_std_pups; 318 319 sdram_offset = SDRAM_PBS_I_OFFS + pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS; 320 321 if (dram_info->num_of_std_pups == PUP_NUM_64BIT) 322 pup_groups = 2; 323 else 324 pup_groups = 1; 325 326 ddr3_reset_phy_read_fifo(); 327 328 /* Check if need to write to sdram before read */ 329 if (is_tx == 1) { 330 ddr3_dram_sram_burst((u32)pattern_ptr, sdram_offset, 331 LEN_PBS_PATTERN); 332 } 333 334 ddr3_dram_sram_read(sdram_offset, (u32)sdram_data, LEN_PBS_PATTERN); 335 336 /* Compare read result to write */ 337 for (ui = 0; ui < LEN_PBS_PATTERN; ui++) { 338 if ((sdram_data[ui]) != (pattern_ptr[ui])) { 339 /* found error */ 340 /* error in low pup group */ 341 for (pup = 0; pup < PUP_NUM_32BIT; pup++) { 342 val = CMP_BYTE_SHIFT * pup; 343 var1 = ((sdram_data[ui] >> val) & 344 CMP_BYTE_MASK); 345 var2 = ((pattern_ptr[ui] >> val) & 346 CMP_BYTE_MASK); 347 348 if (var1 != var2) { 349 if (dram_info->ddr_width > 16) { 350 tmp_pup = (pup + PUP_NUM_32BIT * 351 (ui % pup_groups)); 352 } else { 353 tmp_pup = (pup % PUP_NUM_16BIT); 354 } 355 356 update_pup = (1 << tmp_pup); 357 if (ecc && (update_pup != 0x1)) 358 continue; 359 360 /* 361 * Pup is failed - Go over all DQs and 362 * look for failures 363 */ 364 for (dq = 0; dq < DQ_NUM; dq++) { 365 val = tmp_pup * (1 - ecc) + 366 ecc * ECC_PUP; 367 if (((var1 >> dq) & 0x1) != 368 ((var2 >> dq) & 0x1)) { 369 if (pbs_locked_dq[val][dq] == 1 && 370 pbs_locked_value[val][dq] != pbs_curr_val) 371 continue; 372 373 /* 374 * Activate write to 375 * update PBS to 376 * pbs_lock_val 377 */ 378 pbs_write_pup[dq] |= 379 update_pup; 380 381 /* 382 * Update the 383 * unlock_pup_dq_array 384 */ 385 unlock_pup_dq_array[dq] &= 386 ~update_pup; 387 388 /* 389 * Lock PBS value for 390 * failed bits in 391 * compare operation 392 */ 393 skew_array[tmp_pup * DQ_NUM + dq] = 394 pbs_curr_val; 395 } 396 } 397 } 398 } 399 } 400 } 401 402 pup_addr = (is_tx == 1) ? PUP_PBS_TX : PUP_PBS_RX; 403 404 /* Set last failed bits PBS to min / max pbs value */ 405 for (dq = 0; dq < DQ_NUM; dq++) { 406 for (pup = 0; pup < max_pup; pup++) { 407 if (pbs_write_pup[dq] & (1 << pup)) { 408 val = pup * (1 - ecc) + ecc * ECC_PUP; 409 if (pbs_locked_dq[val][dq] == 1 && 410 pbs_locked_value[val][dq] != pbs_curr_val) 411 continue; 412 413 /* Mark the dq as locked */ 414 pbs_locked_dq[val][dq] = 1; 415 pbs_locked_value[val][dq] = pbs_curr_val; 416 ddr3_write_pup_reg(pup_addr + 417 pbs_dq_mapping[val][dq], 418 CS0, val, 0, pbs_lock_val); 419 } 420 } 421 } 422 423 return MV_OK; 424 } 425 #endif 426 427 /* 428 * Name: ddr3_sdram_direct_compare 429 * Desc: Execute compare per PUP without DMA (no burst mode) 430 * Args: unlock_pup Bit array of the unlock pups 431 * new_locked_pup Output bit array of the pups with failed compare 432 * pattern Pattern to compare 433 * pattern_len Length of pattern (in bytes) 434 * sdram_offset offset address to the SDRAM 435 * write write to the SDRAM before read 436 * mask compare pattern with mask; 437 * auiMaskPatter Mask to compare pattern 438 * 439 * Notes: 440 * Returns: MV_OK if success, other error code if fail. 441 */ 442 int ddr3_sdram_direct_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup, 443 u32 *new_locked_pup, u32 *pattern, 444 u32 pattern_len, u32 sdram_offset, 445 int write, int mask, u32 *mask_pattern) 446 { 447 u32 uj, uk, pup_groups; 448 u32 *sdram_addr; /* used to read from SDRAM */ 449 450 sdram_addr = (u32 *)sdram_offset; 451 452 if (dram_info->num_of_std_pups == PUP_NUM_64BIT) 453 pup_groups = 2; 454 else 455 pup_groups = 1; 456 457 /* Check if need to write before read */ 458 if (write == 1) { 459 for (uk = 0; uk < pattern_len; uk++) { 460 *sdram_addr = pattern[uk]; 461 sdram_addr++; 462 } 463 } 464 465 sdram_addr = (u32 *)sdram_offset; 466 467 for (uk = 0; uk < pattern_len; uk++) { 468 sdram_data[uk] = *sdram_addr; 469 sdram_addr++; 470 } 471 472 /* Compare read result to write */ 473 for (uj = 0; uj < pattern_len; uj++) { 474 if (dram_info->ddr_width > 16) { 475 compare_pattern_v1(uj, new_locked_pup, pattern, 476 pup_groups, 0); 477 } else { 478 compare_pattern_v2(uj, new_locked_pup, pattern); 479 } 480 } 481 482 return MV_OK; 483 } 484 485 /* 486 * Name: ddr3_dram_sram_burst 487 * Desc: Read from the SDRAM in burst of 64 bytes 488 * Args: src 489 * dst 490 * Notes: Using the XOR mechanism 491 * Returns: MV_OK if success, other error code if fail. 492 */ 493 int ddr3_dram_sram_burst(u32 src, u32 dst, u32 len) 494 { 495 u32 chan, byte_count, cs_num, byte; 496 struct xor_channel_t channel; 497 498 chan = 0; 499 byte_count = len * 4; 500 501 /* Wait for previous transfer completion */ 502 while (mv_xor_state_get(chan) != MV_IDLE) 503 ; 504 505 /* Build the channel descriptor */ 506 channel.desc = &dma_desc; 507 508 /* Enable Address Override and set correct src and dst */ 509 if (src < SRAM_BASE) { 510 /* src is DRAM CS, dst is SRAM */ 511 cs_num = (src / (1 + SDRAM_CS_SIZE)); 512 reg_write(XOR_ADDR_OVRD_REG(0, 0), 513 ((cs_num << 1) | (1 << 0))); 514 channel.desc->src_addr0 = (src % (1 + SDRAM_CS_SIZE)); 515 channel.desc->dst_addr = dst; 516 } else { 517 /* src is SRAM, dst is DRAM CS */ 518 cs_num = (dst / (1 + SDRAM_CS_SIZE)); 519 reg_write(XOR_ADDR_OVRD_REG(0, 0), 520 ((cs_num << 25) | (1 << 24))); 521 channel.desc->src_addr0 = (src); 522 channel.desc->dst_addr = (dst % (1 + SDRAM_CS_SIZE)); 523 channel.desc->src_addr0 = src; 524 channel.desc->dst_addr = (dst % (1 + SDRAM_CS_SIZE)); 525 } 526 527 channel.desc->src_addr1 = 0; 528 channel.desc->byte_cnt = byte_count; 529 channel.desc->next_desc_ptr = 0; 530 channel.desc->status = 1 << 31; 531 channel.desc->desc_cmd = 0x0; 532 channel.desc_phys_addr = (unsigned long)&dma_desc; 533 534 ddr3_flush_l1_line((u32)&dma_desc); 535 536 /* Issue the transfer */ 537 if (mv_xor_transfer(chan, MV_DMA, channel.desc_phys_addr) != MV_OK) 538 return MV_FAIL; 539 540 /* Wait for completion */ 541 xor_waiton_eng(chan); 542 543 if (dst > SRAM_BASE) { 544 for (byte = 0; byte < byte_count; byte += 0x20) 545 cache_inv(dst + byte); 546 } 547 548 return MV_OK; 549 } 550 551 /* 552 * Name: ddr3_flush_l1_line 553 * Desc: 554 * Args: 555 * Notes: 556 * Returns: MV_OK if success, other error code if fail. 557 */ 558 static void ddr3_flush_l1_line(u32 line) 559 { 560 u32 reg; 561 562 #if defined(MV88F672X) 563 reg = 1; 564 #else 565 reg = reg_read(REG_SAMPLE_RESET_LOW_ADDR) & 566 (1 << REG_SAMPLE_RESET_CPU_ARCH_OFFS); 567 #ifdef MV88F67XX 568 reg = ~reg & (1 << REG_SAMPLE_RESET_CPU_ARCH_OFFS); 569 #endif 570 #endif 571 572 if (reg) { 573 /* V7 Arch mode */ 574 flush_l1_v7(line); 575 flush_l1_v7(line + CACHE_LINE_SIZE); 576 } else { 577 /* V6 Arch mode */ 578 flush_l1_v6(line); 579 flush_l1_v6(line + CACHE_LINE_SIZE); 580 } 581 } 582 583 int ddr3_dram_sram_read(u32 src, u32 dst, u32 len) 584 { 585 u32 ui; 586 u32 *dst_ptr, *src_ptr; 587 588 dst_ptr = (u32 *)dst; 589 src_ptr = (u32 *)src; 590 591 for (ui = 0; ui < len; ui++) { 592 *dst_ptr = *src_ptr; 593 dst_ptr++; 594 src_ptr++; 595 } 596 597 return MV_OK; 598 } 599 600 int ddr3_sdram_dqs_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup, 601 u32 *new_locked_pup, u32 *pattern, 602 u32 pattern_len, u32 sdram_offset, int write, 603 int mask, u32 *mask_pattern, 604 int special_compare) 605 { 606 u32 uj, pup_groups; 607 608 if (dram_info->num_of_std_pups == PUP_NUM_64BIT) 609 pup_groups = 2; 610 else 611 pup_groups = 1; 612 613 ddr3_reset_phy_read_fifo(); 614 615 /* Check if need to write to sdram before read */ 616 if (write == 1) 617 ddr3_dram_sram_burst((u32)pattern, sdram_offset, pattern_len); 618 619 ddr3_dram_sram_burst(sdram_offset, (u32)sdram_data, pattern_len); 620 621 /* Compare read result to write */ 622 for (uj = 0; uj < pattern_len; uj++) { 623 if (special_compare && special_compare_pattern(uj)) 624 continue; 625 626 if (dram_info->ddr_width > 16) { 627 compare_pattern_v1(uj, new_locked_pup, pattern, 628 pup_groups, 1); 629 } else { 630 compare_pattern_v2(uj, new_locked_pup, pattern); 631 } 632 } 633 634 return MV_OK; 635 } 636 637 void ddr3_reset_phy_read_fifo(void) 638 { 639 u32 reg; 640 641 /* reset read FIFO */ 642 reg = reg_read(REG_DRAM_TRAINING_ADDR); 643 /* Start Auto Read Leveling procedure */ 644 reg |= (1 << REG_DRAM_TRAINING_RL_OFFS); 645 646 /* 0x15B0 - Training Register */ 647 reg_write(REG_DRAM_TRAINING_ADDR, reg); 648 649 reg = reg_read(REG_DRAM_TRAINING_2_ADDR); 650 reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS) + 651 (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS)); 652 653 /* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset */ 654 /* 0x15B8 - Training SW 2 Register */ 655 reg_write(REG_DRAM_TRAINING_2_ADDR, reg); 656 657 do { 658 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) & 659 (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS); 660 } while (reg); /* Wait for '0' */ 661 662 reg = reg_read(REG_DRAM_TRAINING_ADDR); 663 664 /* Clear Auto Read Leveling procedure */ 665 reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS); 666 667 /* 0x15B0 - Training Register */ 668 reg_write(REG_DRAM_TRAINING_ADDR, reg); 669 } 670