1 /* 2 * Copyright (C) 2006-2009 Freescale Semiconductor, Inc. 3 * 4 * Dave Liu <daveliu@freescale.com> 5 * based on source code of Shlomi Gridish 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <command.h> 12 #include <linux/errno.h> 13 #include <asm/io.h> 14 #include <linux/immap_qe.h> 15 #include <fsl_qe.h> 16 #ifdef CONFIG_LS102XA 17 #include <asm/arch/immap_ls102xa.h> 18 #endif 19 20 #define MPC85xx_DEVDISR_QE_DISABLE 0x1 21 22 qe_map_t *qe_immr = NULL; 23 #ifdef CONFIG_QE 24 static qe_snum_t snums[QE_NUM_OF_SNUM]; 25 #endif 26 27 DECLARE_GLOBAL_DATA_PTR; 28 29 void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data) 30 { 31 u32 cecr; 32 33 if (cmd == QE_RESET) { 34 out_be32(&qe_immr->cp.cecr,(u32) (cmd | QE_CR_FLG)); 35 } else { 36 out_be32(&qe_immr->cp.cecdr, cmd_data); 37 out_be32(&qe_immr->cp.cecr, (sbc | QE_CR_FLG | 38 ((u32) mcn<<QE_CR_PROTOCOL_SHIFT) | cmd)); 39 } 40 /* Wait for the QE_CR_FLG to clear */ 41 do { 42 cecr = in_be32(&qe_immr->cp.cecr); 43 } while (cecr & QE_CR_FLG); 44 45 return; 46 } 47 48 #ifdef CONFIG_QE 49 uint qe_muram_alloc(uint size, uint align) 50 { 51 uint retloc; 52 uint align_mask, off; 53 uint savebase; 54 55 align_mask = align - 1; 56 savebase = gd->arch.mp_alloc_base; 57 58 off = gd->arch.mp_alloc_base & align_mask; 59 if (off != 0) 60 gd->arch.mp_alloc_base += (align - off); 61 62 if ((off = size & align_mask) != 0) 63 size += (align - off); 64 65 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) { 66 gd->arch.mp_alloc_base = savebase; 67 printf("%s: ran out of ram.\n", __FUNCTION__); 68 } 69 70 retloc = gd->arch.mp_alloc_base; 71 gd->arch.mp_alloc_base += size; 72 73 memset((void *)&qe_immr->muram[retloc], 0, size); 74 75 __asm__ __volatile__("sync"); 76 77 return retloc; 78 } 79 #endif 80 81 void *qe_muram_addr(uint offset) 82 { 83 return (void *)&qe_immr->muram[offset]; 84 } 85 86 #ifdef CONFIG_QE 87 static void qe_sdma_init(void) 88 { 89 volatile sdma_t *p; 90 uint sdma_buffer_base; 91 92 p = (volatile sdma_t *)&qe_immr->sdma; 93 94 /* All of DMA transaction in bus 1 */ 95 out_be32(&p->sdaqr, 0); 96 out_be32(&p->sdaqmr, 0); 97 98 /* Allocate 2KB temporary buffer for sdma */ 99 sdma_buffer_base = qe_muram_alloc(2048, 4096); 100 out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK); 101 102 /* Clear sdma status */ 103 out_be32(&p->sdsr, 0x03000000); 104 105 /* Enable global mode on bus 1, and 2KB buffer size */ 106 out_be32(&p->sdmr, QE_SDMR_GLB_1_MSK | (0x3 << QE_SDMR_CEN_SHIFT)); 107 } 108 109 /* This table is a list of the serial numbers of the Threads, taken from the 110 * "SNUM Table" chart in the QE Reference Manual. The order is not important, 111 * we just need to know what the SNUMs are for the threads. 112 */ 113 static u8 thread_snum[] = { 114 /* Evthreads 16-29 are not supported in MPC8309 */ 115 #if !defined(CONFIG_MPC8309) 116 0x04, 0x05, 0x0c, 0x0d, 117 0x14, 0x15, 0x1c, 0x1d, 118 0x24, 0x25, 0x2c, 0x2d, 119 0x34, 0x35, 120 #endif 121 0x88, 0x89, 0x98, 0x99, 122 0xa8, 0xa9, 0xb8, 0xb9, 123 0xc8, 0xc9, 0xd8, 0xd9, 124 0xe8, 0xe9, 0x08, 0x09, 125 0x18, 0x19, 0x28, 0x29, 126 0x38, 0x39, 0x48, 0x49, 127 0x58, 0x59, 0x68, 0x69, 128 0x78, 0x79, 0x80, 0x81 129 }; 130 131 static void qe_snums_init(void) 132 { 133 int i; 134 135 for (i = 0; i < QE_NUM_OF_SNUM; i++) { 136 snums[i].state = QE_SNUM_STATE_FREE; 137 snums[i].num = thread_snum[i]; 138 } 139 } 140 141 int qe_get_snum(void) 142 { 143 int snum = -EBUSY; 144 int i; 145 146 for (i = 0; i < QE_NUM_OF_SNUM; i++) { 147 if (snums[i].state == QE_SNUM_STATE_FREE) { 148 snums[i].state = QE_SNUM_STATE_USED; 149 snum = snums[i].num; 150 break; 151 } 152 } 153 154 return snum; 155 } 156 157 void qe_put_snum(u8 snum) 158 { 159 int i; 160 161 for (i = 0; i < QE_NUM_OF_SNUM; i++) { 162 if (snums[i].num == snum) { 163 snums[i].state = QE_SNUM_STATE_FREE; 164 break; 165 } 166 } 167 } 168 169 void qe_init(uint qe_base) 170 { 171 /* Init the QE IMMR base */ 172 qe_immr = (qe_map_t *)qe_base; 173 174 #ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR 175 /* 176 * Upload microcode to IRAM for those SOCs which do not have ROM in QE. 177 */ 178 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR); 179 180 /* enable the microcode in IRAM */ 181 out_be32(&qe_immr->iram.iready,QE_IRAM_READY); 182 #endif 183 184 gd->arch.mp_alloc_base = QE_DATAONLY_BASE; 185 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE; 186 187 qe_sdma_init(); 188 qe_snums_init(); 189 } 190 #endif 191 192 #ifdef CONFIG_U_QE 193 void u_qe_init(void) 194 { 195 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET); 196 197 u_qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR); 198 out_be32(&qe_immr->iram.iready, QE_IRAM_READY); 199 } 200 #endif 201 202 #ifdef CONFIG_U_QE 203 void u_qe_resume(void) 204 { 205 qe_map_t *qe_immrr; 206 207 qe_immrr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET); 208 u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr); 209 out_be32(&qe_immrr->iram.iready, QE_IRAM_READY); 210 } 211 #endif 212 213 void qe_reset(void) 214 { 215 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID, 216 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0); 217 } 218 219 #ifdef CONFIG_QE 220 void qe_assign_page(uint snum, uint para_ram_base) 221 { 222 u32 cecr; 223 224 out_be32(&qe_immr->cp.cecdr, para_ram_base); 225 out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT) 226 | QE_CR_FLG | QE_ASSIGN_PAGE); 227 228 /* Wait for the QE_CR_FLG to clear */ 229 do { 230 cecr = in_be32(&qe_immr->cp.cecr); 231 } while (cecr & QE_CR_FLG ); 232 233 return; 234 } 235 #endif 236 237 /* 238 * brg: 0~15 as BRG1~BRG16 239 rate: baud rate 240 * BRG input clock comes from the BRGCLK (internal clock generated from 241 the QE clock, it is one-half of the QE clock), If need the clock source 242 from CLKn pin, we have te change the function. 243 */ 244 245 #define BRG_CLK (gd->arch.brg_clk) 246 247 #ifdef CONFIG_QE 248 int qe_set_brg(uint brg, uint rate) 249 { 250 volatile uint *bp; 251 u32 divisor; 252 int div16 = 0; 253 254 if (brg >= QE_NUM_OF_BRGS) 255 return -EINVAL; 256 bp = (uint *)&qe_immr->brg.brgc1; 257 bp += brg; 258 259 divisor = (BRG_CLK / rate); 260 if (divisor > QE_BRGC_DIVISOR_MAX + 1) { 261 div16 = 1; 262 divisor /= 16; 263 } 264 265 *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE; 266 __asm__ __volatile__("sync"); 267 268 if (div16) { 269 *bp |= QE_BRGC_DIV16; 270 __asm__ __volatile__("sync"); 271 } 272 273 return 0; 274 } 275 #endif 276 277 /* Set ethernet MII clock master 278 */ 279 int qe_set_mii_clk_src(int ucc_num) 280 { 281 u32 cmxgcr; 282 283 /* check if the UCC number is in range. */ 284 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) { 285 printf("%s: ucc num not in ranges\n", __FUNCTION__); 286 return -EINVAL; 287 } 288 289 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr); 290 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK; 291 cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT); 292 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr); 293 294 return 0; 295 } 296 297 /* Firmware information stored here for qe_get_firmware_info() */ 298 static struct qe_firmware_info qe_firmware_info; 299 300 /* 301 * Set to 1 if QE firmware has been uploaded, and therefore 302 * qe_firmware_info contains valid data. 303 */ 304 static int qe_firmware_uploaded; 305 306 /* 307 * Upload a QE microcode 308 * 309 * This function is a worker function for qe_upload_firmware(). It does 310 * the actual uploading of the microcode. 311 */ 312 static void qe_upload_microcode(const void *base, 313 const struct qe_microcode *ucode) 314 { 315 const u32 *code = base + be32_to_cpu(ucode->code_offset); 316 unsigned int i; 317 318 if (ucode->major || ucode->minor || ucode->revision) 319 printf("QE: uploading microcode '%s' version %u.%u.%u\n", 320 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor, 321 (u16)ucode->revision); 322 else 323 printf("QE: uploading microcode '%s'\n", (char *)ucode->id); 324 325 /* Use auto-increment */ 326 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) | 327 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR); 328 329 for (i = 0; i < be32_to_cpu(ucode->count); i++) 330 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i])); 331 } 332 333 /* 334 * Upload a microcode to the I-RAM at a specific address. 335 * 336 * See docs/README.qe_firmware for information on QE microcode uploading. 337 * 338 * Currently, only version 1 is supported, so the 'version' field must be 339 * set to 1. 340 * 341 * The SOC model and revision are not validated, they are only displayed for 342 * informational purposes. 343 * 344 * 'calc_size' is the calculated size, in bytes, of the firmware structure and 345 * all of the microcode structures, minus the CRC. 346 * 347 * 'length' is the size that the structure says it is, including the CRC. 348 */ 349 int qe_upload_firmware(const struct qe_firmware *firmware) 350 { 351 unsigned int i; 352 unsigned int j; 353 u32 crc; 354 size_t calc_size = sizeof(struct qe_firmware); 355 size_t length; 356 const struct qe_header *hdr; 357 #ifdef CONFIG_DEEP_SLEEP 358 #ifdef CONFIG_LS102XA 359 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; 360 #else 361 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 362 #endif 363 #endif 364 if (!firmware) { 365 printf("Invalid address\n"); 366 return -EINVAL; 367 } 368 369 hdr = &firmware->header; 370 length = be32_to_cpu(hdr->length); 371 372 /* Check the magic */ 373 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || 374 (hdr->magic[2] != 'F')) { 375 printf("QE microcode not found\n"); 376 #ifdef CONFIG_DEEP_SLEEP 377 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); 378 #endif 379 return -EPERM; 380 } 381 382 /* Check the version */ 383 if (hdr->version != 1) { 384 printf("Unsupported version\n"); 385 return -EPERM; 386 } 387 388 /* Validate some of the fields */ 389 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) { 390 printf("Invalid data\n"); 391 return -EINVAL; 392 } 393 394 /* Validate the length and check if there's a CRC */ 395 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode); 396 397 for (i = 0; i < firmware->count; i++) 398 /* 399 * For situations where the second RISC uses the same microcode 400 * as the first, the 'code_offset' and 'count' fields will be 401 * zero, so it's okay to add those. 402 */ 403 calc_size += sizeof(u32) * 404 be32_to_cpu(firmware->microcode[i].count); 405 406 /* Validate the length */ 407 if (length != calc_size + sizeof(u32)) { 408 printf("Invalid length\n"); 409 return -EPERM; 410 } 411 412 /* 413 * Validate the CRC. We would normally call crc32_no_comp(), but that 414 * function isn't available unless you turn on JFFS support. 415 */ 416 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size)); 417 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) { 418 printf("Firmware CRC is invalid\n"); 419 return -EIO; 420 } 421 422 /* 423 * If the microcode calls for it, split the I-RAM. 424 */ 425 if (!firmware->split) { 426 out_be16(&qe_immr->cp.cercr, 427 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR); 428 } 429 430 if (firmware->soc.model) 431 printf("Firmware '%s' for %u V%u.%u\n", 432 firmware->id, be16_to_cpu(firmware->soc.model), 433 firmware->soc.major, firmware->soc.minor); 434 else 435 printf("Firmware '%s'\n", firmware->id); 436 437 /* 438 * The QE only supports one microcode per RISC, so clear out all the 439 * saved microcode information and put in the new. 440 */ 441 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info)); 442 strncpy(qe_firmware_info.id, (char *)firmware->id, 62); 443 qe_firmware_info.extended_modes = firmware->extended_modes; 444 memcpy(qe_firmware_info.vtraps, firmware->vtraps, 445 sizeof(firmware->vtraps)); 446 qe_firmware_uploaded = 1; 447 448 /* Loop through each microcode. */ 449 for (i = 0; i < firmware->count; i++) { 450 const struct qe_microcode *ucode = &firmware->microcode[i]; 451 452 /* Upload a microcode if it's present */ 453 if (ucode->code_offset) 454 qe_upload_microcode(firmware, ucode); 455 456 /* Program the traps for this processor */ 457 for (j = 0; j < 16; j++) { 458 u32 trap = be32_to_cpu(ucode->traps[j]); 459 460 if (trap) 461 out_be32(&qe_immr->rsp[i].tibcr[j], trap); 462 } 463 464 /* Enable traps */ 465 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); 466 } 467 468 return 0; 469 } 470 471 #ifdef CONFIG_U_QE 472 /* 473 * Upload a microcode to the I-RAM at a specific address. 474 * 475 * See docs/README.qe_firmware for information on QE microcode uploading. 476 * 477 * Currently, only version 1 is supported, so the 'version' field must be 478 * set to 1. 479 * 480 * The SOC model and revision are not validated, they are only displayed for 481 * informational purposes. 482 * 483 * 'calc_size' is the calculated size, in bytes, of the firmware structure and 484 * all of the microcode structures, minus the CRC. 485 * 486 * 'length' is the size that the structure says it is, including the CRC. 487 */ 488 int u_qe_upload_firmware(const struct qe_firmware *firmware) 489 { 490 unsigned int i; 491 unsigned int j; 492 u32 crc; 493 size_t calc_size = sizeof(struct qe_firmware); 494 size_t length; 495 const struct qe_header *hdr; 496 #ifdef CONFIG_DEEP_SLEEP 497 #ifdef CONFIG_LS102XA 498 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; 499 #else 500 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 501 #endif 502 #endif 503 if (!firmware) { 504 printf("Invalid address\n"); 505 return -EINVAL; 506 } 507 508 hdr = &firmware->header; 509 length = be32_to_cpu(hdr->length); 510 511 /* Check the magic */ 512 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || 513 (hdr->magic[2] != 'F')) { 514 printf("Not a microcode\n"); 515 #ifdef CONFIG_DEEP_SLEEP 516 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); 517 #endif 518 return -EPERM; 519 } 520 521 /* Check the version */ 522 if (hdr->version != 1) { 523 printf("Unsupported version\n"); 524 return -EPERM; 525 } 526 527 /* Validate some of the fields */ 528 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) { 529 printf("Invalid data\n"); 530 return -EINVAL; 531 } 532 533 /* Validate the length and check if there's a CRC */ 534 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode); 535 536 for (i = 0; i < firmware->count; i++) 537 /* 538 * For situations where the second RISC uses the same microcode 539 * as the first, the 'code_offset' and 'count' fields will be 540 * zero, so it's okay to add those. 541 */ 542 calc_size += sizeof(u32) * 543 be32_to_cpu(firmware->microcode[i].count); 544 545 /* Validate the length */ 546 if (length != calc_size + sizeof(u32)) { 547 printf("Invalid length\n"); 548 return -EPERM; 549 } 550 551 /* 552 * Validate the CRC. We would normally call crc32_no_comp(), but that 553 * function isn't available unless you turn on JFFS support. 554 */ 555 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size)); 556 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) { 557 printf("Firmware CRC is invalid\n"); 558 return -EIO; 559 } 560 561 /* 562 * If the microcode calls for it, split the I-RAM. 563 */ 564 if (!firmware->split) { 565 out_be16(&qe_immr->cp.cercr, 566 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR); 567 } 568 569 if (firmware->soc.model) 570 printf("Firmware '%s' for %u V%u.%u\n", 571 firmware->id, be16_to_cpu(firmware->soc.model), 572 firmware->soc.major, firmware->soc.minor); 573 else 574 printf("Firmware '%s'\n", firmware->id); 575 576 /* Loop through each microcode. */ 577 for (i = 0; i < firmware->count; i++) { 578 const struct qe_microcode *ucode = &firmware->microcode[i]; 579 580 /* Upload a microcode if it's present */ 581 if (ucode->code_offset) 582 qe_upload_microcode(firmware, ucode); 583 584 /* Program the traps for this processor */ 585 for (j = 0; j < 16; j++) { 586 u32 trap = be32_to_cpu(ucode->traps[j]); 587 588 if (trap) 589 out_be32(&qe_immr->rsp[i].tibcr[j], trap); 590 } 591 592 /* Enable traps */ 593 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); 594 } 595 596 return 0; 597 } 598 #endif 599 600 #ifdef CONFIG_U_QE 601 int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr) 602 { 603 unsigned int i; 604 unsigned int j; 605 const struct qe_header *hdr; 606 const u32 *code; 607 #ifdef CONFIG_DEEP_SLEEP 608 #ifdef CONFIG_PPC 609 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 610 #else 611 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; 612 #endif 613 #endif 614 615 if (!firmware) 616 return -EINVAL; 617 618 hdr = &firmware->header; 619 620 /* Check the magic */ 621 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || 622 (hdr->magic[2] != 'F')) { 623 #ifdef CONFIG_DEEP_SLEEP 624 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); 625 #endif 626 return -EPERM; 627 } 628 629 /* 630 * If the microcode calls for it, split the I-RAM. 631 */ 632 if (!firmware->split) { 633 out_be16(&qe_immrr->cp.cercr, 634 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR); 635 } 636 637 /* Loop through each microcode. */ 638 for (i = 0; i < firmware->count; i++) { 639 const struct qe_microcode *ucode = &firmware->microcode[i]; 640 641 /* Upload a microcode if it's present */ 642 if (!ucode->code_offset) 643 return 0; 644 645 code = (const void *)firmware + be32_to_cpu(ucode->code_offset); 646 647 /* Use auto-increment */ 648 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) | 649 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR); 650 651 for (i = 0; i < be32_to_cpu(ucode->count); i++) 652 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i])); 653 654 /* Program the traps for this processor */ 655 for (j = 0; j < 16; j++) { 656 u32 trap = be32_to_cpu(ucode->traps[j]); 657 658 if (trap) 659 out_be32(&qe_immrr->rsp[i].tibcr[j], trap); 660 } 661 662 /* Enable traps */ 663 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); 664 } 665 666 return 0; 667 } 668 #endif 669 670 struct qe_firmware_info *qe_get_firmware_info(void) 671 { 672 return qe_firmware_uploaded ? &qe_firmware_info : NULL; 673 } 674 675 static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 676 { 677 ulong addr; 678 679 if (argc < 3) 680 return cmd_usage(cmdtp); 681 682 if (strcmp(argv[1], "fw") == 0) { 683 addr = simple_strtoul(argv[2], NULL, 16); 684 685 if (!addr) { 686 printf("Invalid address\n"); 687 return -EINVAL; 688 } 689 690 /* 691 * If a length was supplied, compare that with the 'length' 692 * field. 693 */ 694 695 if (argc > 3) { 696 ulong length = simple_strtoul(argv[3], NULL, 16); 697 struct qe_firmware *firmware = (void *) addr; 698 699 if (length != be32_to_cpu(firmware->header.length)) { 700 printf("Length mismatch\n"); 701 return -EINVAL; 702 } 703 } 704 705 return qe_upload_firmware((const struct qe_firmware *) addr); 706 } 707 708 return cmd_usage(cmdtp); 709 } 710 711 U_BOOT_CMD( 712 qe, 4, 0, qe_cmd, 713 "QUICC Engine commands", 714 "fw <addr> [<length>] - Upload firmware binary at address <addr> to " 715 "the QE,\n" 716 "\twith optional length <length> verification." 717 ); 718