1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved. 4 * 5 * Authors: Shlomi Gridish <gridish@freescale.com> 6 * Li Yang <leoli@freescale.com> 7 * Based on cpm2_common.c from Dan Malek (dmalek@jlc.net) 8 * 9 * Description: 10 * General Purpose functions for the global management of the 11 * QUICC Engine (QE). 12 */ 13 #include <linux/bitmap.h> 14 #include <linux/errno.h> 15 #include <linux/sched.h> 16 #include <linux/kernel.h> 17 #include <linux/param.h> 18 #include <linux/string.h> 19 #include <linux/spinlock.h> 20 #include <linux/mm.h> 21 #include <linux/interrupt.h> 22 #include <linux/module.h> 23 #include <linux/delay.h> 24 #include <linux/ioport.h> 25 #include <linux/iopoll.h> 26 #include <linux/crc32.h> 27 #include <linux/mod_devicetable.h> 28 #include <linux/of_platform.h> 29 #include <soc/fsl/qe/immap_qe.h> 30 #include <soc/fsl/qe/qe.h> 31 32 static void qe_snums_init(void); 33 static int qe_sdma_init(void); 34 35 static DEFINE_SPINLOCK(qe_lock); 36 DEFINE_SPINLOCK(cmxgcr_lock); 37 EXPORT_SYMBOL(cmxgcr_lock); 38 39 /* We allocate this here because it is used almost exclusively for 40 * the communication processor devices. 41 */ 42 struct qe_immap __iomem *qe_immr; 43 EXPORT_SYMBOL(qe_immr); 44 45 static u8 snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */ 46 static DECLARE_BITMAP(snum_state, QE_NUM_OF_SNUM); 47 static unsigned int qe_num_of_snum; 48 49 static phys_addr_t qebase = -1; 50 51 static struct device_node *qe_get_device_node(void) 52 { 53 struct device_node *qe; 54 55 /* 56 * Newer device trees have an "fsl,qe" compatible property for the QE 57 * node, but we still need to support older device trees. 58 */ 59 qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); 60 if (qe) 61 return qe; 62 return of_find_node_by_type(NULL, "qe"); 63 } 64 65 static phys_addr_t get_qe_base(void) 66 { 67 struct device_node *qe; 68 int ret; 69 struct resource res; 70 71 if (qebase != -1) 72 return qebase; 73 74 qe = qe_get_device_node(); 75 if (!qe) 76 return qebase; 77 78 ret = of_address_to_resource(qe, 0, &res); 79 if (!ret) 80 qebase = res.start; 81 of_node_put(qe); 82 83 return qebase; 84 } 85 86 void qe_reset(void) 87 { 88 if (qe_immr == NULL) 89 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE); 90 91 qe_snums_init(); 92 93 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID, 94 QE_CR_PROTOCOL_UNSPECIFIED, 0); 95 96 /* Reclaim the MURAM memory for our use. */ 97 qe_muram_init(); 98 99 if (qe_sdma_init()) 100 panic("sdma init failed!"); 101 } 102 103 int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input) 104 { 105 unsigned long flags; 106 u8 mcn_shift = 0, dev_shift = 0; 107 u32 val; 108 int ret; 109 110 spin_lock_irqsave(&qe_lock, flags); 111 if (cmd == QE_RESET) { 112 qe_iowrite32be((u32)(cmd | QE_CR_FLG), &qe_immr->cp.cecr); 113 } else { 114 if (cmd == QE_ASSIGN_PAGE) { 115 /* Here device is the SNUM, not sub-block */ 116 dev_shift = QE_CR_SNUM_SHIFT; 117 } else if (cmd == QE_ASSIGN_RISC) { 118 /* Here device is the SNUM, and mcnProtocol is 119 * e_QeCmdRiscAssignment value */ 120 dev_shift = QE_CR_SNUM_SHIFT; 121 mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT; 122 } else { 123 if (device == QE_CR_SUBBLOCK_USB) 124 mcn_shift = QE_CR_MCN_USB_SHIFT; 125 else 126 mcn_shift = QE_CR_MCN_NORMAL_SHIFT; 127 } 128 129 qe_iowrite32be(cmd_input, &qe_immr->cp.cecdr); 130 qe_iowrite32be((cmd | QE_CR_FLG | ((u32)device << dev_shift) | (u32)mcn_protocol << mcn_shift), 131 &qe_immr->cp.cecr); 132 } 133 134 /* wait for the QE_CR_FLG to clear */ 135 ret = readx_poll_timeout_atomic(qe_ioread32be, &qe_immr->cp.cecr, val, 136 (val & QE_CR_FLG) == 0, 0, 100); 137 /* On timeout, ret is -ETIMEDOUT, otherwise it will be 0. */ 138 spin_unlock_irqrestore(&qe_lock, flags); 139 140 return ret == 0; 141 } 142 EXPORT_SYMBOL(qe_issue_cmd); 143 144 /* Set a baud rate generator. This needs lots of work. There are 145 * 16 BRGs, which can be connected to the QE channels or output 146 * as clocks. The BRGs are in two different block of internal 147 * memory mapped space. 148 * The BRG clock is the QE clock divided by 2. 149 * It was set up long ago during the initial boot phase and is 150 * is given to us. 151 * Baud rate clocks are zero-based in the driver code (as that maps 152 * to port numbers). Documentation uses 1-based numbering. 153 */ 154 static unsigned int brg_clk = 0; 155 156 #define CLK_GRAN (1000) 157 #define CLK_GRAN_LIMIT (5) 158 159 unsigned int qe_get_brg_clk(void) 160 { 161 struct device_node *qe; 162 u32 brg; 163 unsigned int mod; 164 165 if (brg_clk) 166 return brg_clk; 167 168 qe = qe_get_device_node(); 169 if (!qe) 170 return brg_clk; 171 172 if (!of_property_read_u32(qe, "brg-frequency", &brg)) 173 brg_clk = brg; 174 175 of_node_put(qe); 176 177 /* round this if near to a multiple of CLK_GRAN */ 178 mod = brg_clk % CLK_GRAN; 179 if (mod) { 180 if (mod < CLK_GRAN_LIMIT) 181 brg_clk -= mod; 182 else if (mod > (CLK_GRAN - CLK_GRAN_LIMIT)) 183 brg_clk += CLK_GRAN - mod; 184 } 185 186 return brg_clk; 187 } 188 EXPORT_SYMBOL(qe_get_brg_clk); 189 190 #define PVR_VER_836x 0x8083 191 #define PVR_VER_832x 0x8084 192 193 static bool qe_general4_errata(void) 194 { 195 #ifdef CONFIG_PPC32 196 return pvr_version_is(PVR_VER_836x) || pvr_version_is(PVR_VER_832x); 197 #endif 198 return false; 199 } 200 201 /* Program the BRG to the given sampling rate and multiplier 202 * 203 * @brg: the BRG, QE_BRG1 - QE_BRG16 204 * @rate: the desired sampling rate 205 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or 206 * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01, 207 * then 'multiplier' should be 8. 208 */ 209 int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier) 210 { 211 u32 divisor, tempval; 212 u32 div16 = 0; 213 214 if ((brg < QE_BRG1) || (brg > QE_BRG16)) 215 return -EINVAL; 216 217 divisor = qe_get_brg_clk() / (rate * multiplier); 218 219 if (divisor > QE_BRGC_DIVISOR_MAX + 1) { 220 div16 = QE_BRGC_DIV16; 221 divisor /= 16; 222 } 223 224 /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says 225 that the BRG divisor must be even if you're not using divide-by-16 226 mode. */ 227 if (qe_general4_errata()) 228 if (!div16 && (divisor & 1) && (divisor > 3)) 229 divisor++; 230 231 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | 232 QE_BRGC_ENABLE | div16; 233 234 qe_iowrite32be(tempval, &qe_immr->brg.brgc[brg - QE_BRG1]); 235 236 return 0; 237 } 238 EXPORT_SYMBOL(qe_setbrg); 239 240 /* Convert a string to a QE clock source enum 241 * 242 * This function takes a string, typically from a property in the device 243 * tree, and returns the corresponding "enum qe_clock" value. 244 */ 245 enum qe_clock qe_clock_source(const char *source) 246 { 247 unsigned int i; 248 249 if (strcasecmp(source, "none") == 0) 250 return QE_CLK_NONE; 251 252 if (strcmp(source, "tsync_pin") == 0) 253 return QE_TSYNC_PIN; 254 255 if (strcmp(source, "rsync_pin") == 0) 256 return QE_RSYNC_PIN; 257 258 if (strncasecmp(source, "brg", 3) == 0) { 259 i = simple_strtoul(source + 3, NULL, 10); 260 if ((i >= 1) && (i <= 16)) 261 return (QE_BRG1 - 1) + i; 262 else 263 return QE_CLK_DUMMY; 264 } 265 266 if (strncasecmp(source, "clk", 3) == 0) { 267 i = simple_strtoul(source + 3, NULL, 10); 268 if ((i >= 1) && (i <= 24)) 269 return (QE_CLK1 - 1) + i; 270 else 271 return QE_CLK_DUMMY; 272 } 273 274 return QE_CLK_DUMMY; 275 } 276 EXPORT_SYMBOL(qe_clock_source); 277 278 /* Initialize SNUMs (thread serial numbers) according to 279 * QE Module Control chapter, SNUM table 280 */ 281 static void qe_snums_init(void) 282 { 283 static const u8 snum_init_76[] = { 284 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D, 285 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89, 286 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9, 287 0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D, 288 0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D, 289 0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D, 290 0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD, 291 0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD, 292 0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED, 293 0xF4, 0xF5, 0xFC, 0xFD, 294 }; 295 static const u8 snum_init_46[] = { 296 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D, 297 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89, 298 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9, 299 0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19, 300 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59, 301 0x68, 0x69, 0x78, 0x79, 0x80, 0x81, 302 }; 303 struct device_node *qe; 304 const u8 *snum_init; 305 int i; 306 307 bitmap_zero(snum_state, QE_NUM_OF_SNUM); 308 qe_num_of_snum = 28; /* The default number of snum for threads is 28 */ 309 qe = qe_get_device_node(); 310 if (qe) { 311 i = of_property_read_variable_u8_array(qe, "fsl,qe-snums", 312 snums, 1, QE_NUM_OF_SNUM); 313 if (i > 0) { 314 of_node_put(qe); 315 qe_num_of_snum = i; 316 return; 317 } 318 /* 319 * Fall back to legacy binding of using the value of 320 * fsl,qe-num-snums to choose one of the static arrays 321 * above. 322 */ 323 of_property_read_u32(qe, "fsl,qe-num-snums", &qe_num_of_snum); 324 of_node_put(qe); 325 } 326 327 if (qe_num_of_snum == 76) { 328 snum_init = snum_init_76; 329 } else if (qe_num_of_snum == 28 || qe_num_of_snum == 46) { 330 snum_init = snum_init_46; 331 } else { 332 pr_err("QE: unsupported value of fsl,qe-num-snums: %u\n", qe_num_of_snum); 333 return; 334 } 335 memcpy(snums, snum_init, qe_num_of_snum); 336 } 337 338 int qe_get_snum(void) 339 { 340 unsigned long flags; 341 int snum = -EBUSY; 342 int i; 343 344 spin_lock_irqsave(&qe_lock, flags); 345 i = find_first_zero_bit(snum_state, qe_num_of_snum); 346 if (i < qe_num_of_snum) { 347 set_bit(i, snum_state); 348 snum = snums[i]; 349 } 350 spin_unlock_irqrestore(&qe_lock, flags); 351 352 return snum; 353 } 354 EXPORT_SYMBOL(qe_get_snum); 355 356 void qe_put_snum(u8 snum) 357 { 358 const u8 *p = memchr(snums, snum, qe_num_of_snum); 359 360 if (p) 361 clear_bit(p - snums, snum_state); 362 } 363 EXPORT_SYMBOL(qe_put_snum); 364 365 static int qe_sdma_init(void) 366 { 367 struct sdma __iomem *sdma = &qe_immr->sdma; 368 static s32 sdma_buf_offset = -ENOMEM; 369 370 /* allocate 2 internal temporary buffers (512 bytes size each) for 371 * the SDMA */ 372 if (sdma_buf_offset < 0) { 373 sdma_buf_offset = qe_muram_alloc(512 * 2, 4096); 374 if (sdma_buf_offset < 0) 375 return -ENOMEM; 376 } 377 378 qe_iowrite32be((u32)sdma_buf_offset & QE_SDEBCR_BA_MASK, 379 &sdma->sdebcr); 380 qe_iowrite32be((QE_SDMR_GLB_1_MSK | (0x1 << QE_SDMR_CEN_SHIFT)), 381 &sdma->sdmr); 382 383 return 0; 384 } 385 386 /* The maximum number of RISCs we support */ 387 #define MAX_QE_RISC 4 388 389 /* Firmware information stored here for qe_get_firmware_info() */ 390 static struct qe_firmware_info qe_firmware_info; 391 392 /* 393 * Set to 1 if QE firmware has been uploaded, and therefore 394 * qe_firmware_info contains valid data. 395 */ 396 static int qe_firmware_uploaded; 397 398 /* 399 * Upload a QE microcode 400 * 401 * This function is a worker function for qe_upload_firmware(). It does 402 * the actual uploading of the microcode. 403 */ 404 static void qe_upload_microcode(const void *base, 405 const struct qe_microcode *ucode) 406 { 407 const __be32 *code = base + be32_to_cpu(ucode->code_offset); 408 unsigned int i; 409 410 if (ucode->major || ucode->minor || ucode->revision) 411 printk(KERN_INFO "qe-firmware: " 412 "uploading microcode '%s' version %u.%u.%u\n", 413 ucode->id, ucode->major, ucode->minor, ucode->revision); 414 else 415 printk(KERN_INFO "qe-firmware: " 416 "uploading microcode '%s'\n", ucode->id); 417 418 /* Use auto-increment */ 419 qe_iowrite32be(be32_to_cpu(ucode->iram_offset) | QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR, 420 &qe_immr->iram.iadd); 421 422 for (i = 0; i < be32_to_cpu(ucode->count); i++) 423 qe_iowrite32be(be32_to_cpu(code[i]), &qe_immr->iram.idata); 424 425 /* Set I-RAM Ready Register */ 426 qe_iowrite32be(QE_IRAM_READY, &qe_immr->iram.iready); 427 } 428 429 /* 430 * Upload a microcode to the I-RAM at a specific address. 431 * 432 * See Documentation/powerpc/qe_firmware.rst for information on QE microcode 433 * uploading. 434 * 435 * Currently, only version 1 is supported, so the 'version' field must be 436 * set to 1. 437 * 438 * The SOC model and revision are not validated, they are only displayed for 439 * informational purposes. 440 * 441 * 'calc_size' is the calculated size, in bytes, of the firmware structure and 442 * all of the microcode structures, minus the CRC. 443 * 444 * 'length' is the size that the structure says it is, including the CRC. 445 */ 446 int qe_upload_firmware(const struct qe_firmware *firmware) 447 { 448 unsigned int i; 449 unsigned int j; 450 u32 crc; 451 size_t calc_size; 452 size_t length; 453 const struct qe_header *hdr; 454 455 if (!firmware) { 456 printk(KERN_ERR "qe-firmware: invalid pointer\n"); 457 return -EINVAL; 458 } 459 460 hdr = &firmware->header; 461 length = be32_to_cpu(hdr->length); 462 463 /* Check the magic */ 464 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || 465 (hdr->magic[2] != 'F')) { 466 printk(KERN_ERR "qe-firmware: not a microcode\n"); 467 return -EPERM; 468 } 469 470 /* Check the version */ 471 if (hdr->version != 1) { 472 printk(KERN_ERR "qe-firmware: unsupported version\n"); 473 return -EPERM; 474 } 475 476 /* Validate some of the fields */ 477 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) { 478 printk(KERN_ERR "qe-firmware: invalid data\n"); 479 return -EINVAL; 480 } 481 482 /* Validate the length and check if there's a CRC */ 483 calc_size = struct_size(firmware, microcode, firmware->count); 484 485 for (i = 0; i < firmware->count; i++) 486 /* 487 * For situations where the second RISC uses the same microcode 488 * as the first, the 'code_offset' and 'count' fields will be 489 * zero, so it's okay to add those. 490 */ 491 calc_size += sizeof(__be32) * 492 be32_to_cpu(firmware->microcode[i].count); 493 494 /* Validate the length */ 495 if (length != calc_size + sizeof(__be32)) { 496 printk(KERN_ERR "qe-firmware: invalid length\n"); 497 return -EPERM; 498 } 499 500 /* Validate the CRC */ 501 crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size)); 502 if (crc != crc32(0, firmware, calc_size)) { 503 printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n"); 504 return -EIO; 505 } 506 507 /* 508 * If the microcode calls for it, split the I-RAM. 509 */ 510 if (!firmware->split) 511 qe_setbits_be16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR); 512 513 if (firmware->soc.model) 514 printk(KERN_INFO 515 "qe-firmware: firmware '%s' for %u V%u.%u\n", 516 firmware->id, be16_to_cpu(firmware->soc.model), 517 firmware->soc.major, firmware->soc.minor); 518 else 519 printk(KERN_INFO "qe-firmware: firmware '%s'\n", 520 firmware->id); 521 522 /* 523 * The QE only supports one microcode per RISC, so clear out all the 524 * saved microcode information and put in the new. 525 */ 526 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info)); 527 strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id)); 528 qe_firmware_info.extended_modes = be64_to_cpu(firmware->extended_modes); 529 memcpy(qe_firmware_info.vtraps, firmware->vtraps, 530 sizeof(firmware->vtraps)); 531 532 /* Loop through each microcode. */ 533 for (i = 0; i < firmware->count; i++) { 534 const struct qe_microcode *ucode = &firmware->microcode[i]; 535 536 /* Upload a microcode if it's present */ 537 if (ucode->code_offset) 538 qe_upload_microcode(firmware, ucode); 539 540 /* Program the traps for this processor */ 541 for (j = 0; j < 16; j++) { 542 u32 trap = be32_to_cpu(ucode->traps[j]); 543 544 if (trap) 545 qe_iowrite32be(trap, 546 &qe_immr->rsp[i].tibcr[j]); 547 } 548 549 /* Enable traps */ 550 qe_iowrite32be(be32_to_cpu(ucode->eccr), 551 &qe_immr->rsp[i].eccr); 552 } 553 554 qe_firmware_uploaded = 1; 555 556 return 0; 557 } 558 EXPORT_SYMBOL(qe_upload_firmware); 559 560 /* 561 * Get info on the currently-loaded firmware 562 * 563 * This function also checks the device tree to see if the boot loader has 564 * uploaded a firmware already. 565 */ 566 struct qe_firmware_info *qe_get_firmware_info(void) 567 { 568 static int initialized; 569 struct device_node *qe; 570 struct device_node *fw = NULL; 571 const char *sprop; 572 573 /* 574 * If we haven't checked yet, and a driver hasn't uploaded a firmware 575 * yet, then check the device tree for information. 576 */ 577 if (qe_firmware_uploaded) 578 return &qe_firmware_info; 579 580 if (initialized) 581 return NULL; 582 583 initialized = 1; 584 585 qe = qe_get_device_node(); 586 if (!qe) 587 return NULL; 588 589 /* Find the 'firmware' child node */ 590 fw = of_get_child_by_name(qe, "firmware"); 591 of_node_put(qe); 592 593 /* Did we find the 'firmware' node? */ 594 if (!fw) 595 return NULL; 596 597 qe_firmware_uploaded = 1; 598 599 /* Copy the data into qe_firmware_info*/ 600 sprop = of_get_property(fw, "id", NULL); 601 if (sprop) 602 strlcpy(qe_firmware_info.id, sprop, 603 sizeof(qe_firmware_info.id)); 604 605 of_property_read_u64(fw, "extended-modes", 606 &qe_firmware_info.extended_modes); 607 608 of_property_read_u32_array(fw, "virtual-traps", qe_firmware_info.vtraps, 609 ARRAY_SIZE(qe_firmware_info.vtraps)); 610 611 of_node_put(fw); 612 613 return &qe_firmware_info; 614 } 615 EXPORT_SYMBOL(qe_get_firmware_info); 616 617 unsigned int qe_get_num_of_risc(void) 618 { 619 struct device_node *qe; 620 unsigned int num_of_risc = 0; 621 622 qe = qe_get_device_node(); 623 if (!qe) 624 return num_of_risc; 625 626 of_property_read_u32(qe, "fsl,qe-num-riscs", &num_of_risc); 627 628 of_node_put(qe); 629 630 return num_of_risc; 631 } 632 EXPORT_SYMBOL(qe_get_num_of_risc); 633 634 unsigned int qe_get_num_of_snums(void) 635 { 636 return qe_num_of_snum; 637 } 638 EXPORT_SYMBOL(qe_get_num_of_snums); 639 640 static int __init qe_init(void) 641 { 642 struct device_node *np; 643 644 np = of_find_compatible_node(NULL, NULL, "fsl,qe"); 645 if (!np) 646 return -ENODEV; 647 qe_reset(); 648 of_node_put(np); 649 return 0; 650 } 651 subsys_initcall(qe_init); 652 653 #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) 654 static int qe_resume(struct platform_device *ofdev) 655 { 656 if (!qe_alive_during_sleep()) 657 qe_reset(); 658 return 0; 659 } 660 661 static int qe_probe(struct platform_device *ofdev) 662 { 663 return 0; 664 } 665 666 static const struct of_device_id qe_ids[] = { 667 { .compatible = "fsl,qe", }, 668 { }, 669 }; 670 671 static struct platform_driver qe_driver = { 672 .driver = { 673 .name = "fsl-qe", 674 .of_match_table = qe_ids, 675 }, 676 .probe = qe_probe, 677 .resume = qe_resume, 678 }; 679 680 builtin_platform_driver(qe_driver); 681 #endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */ 682