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 "asm/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 uint qe_base = CONFIG_SYS_IMMR + 0x01400000; /* QE immr base */ 196 qe_immr = (qe_map_t *)qe_base; 197 198 u_qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR); 199 out_be32(&qe_immr->iram.iready, QE_IRAM_READY); 200 } 201 #endif 202 203 #ifdef CONFIG_U_QE 204 void u_qe_resume(void) 205 { 206 qe_map_t *qe_immrr; 207 uint qe_base = CONFIG_SYS_IMMR + QE_IMMR_OFFSET; /* QE immr base */ 208 qe_immrr = (qe_map_t *)qe_base; 209 210 u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr); 211 out_be32(&qe_immrr->iram.iready, QE_IRAM_READY); 212 } 213 #endif 214 215 void qe_reset(void) 216 { 217 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID, 218 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0); 219 } 220 221 #ifdef CONFIG_QE 222 void qe_assign_page(uint snum, uint para_ram_base) 223 { 224 u32 cecr; 225 226 out_be32(&qe_immr->cp.cecdr, para_ram_base); 227 out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT) 228 | QE_CR_FLG | QE_ASSIGN_PAGE); 229 230 /* Wait for the QE_CR_FLG to clear */ 231 do { 232 cecr = in_be32(&qe_immr->cp.cecr); 233 } while (cecr & QE_CR_FLG ); 234 235 return; 236 } 237 #endif 238 239 /* 240 * brg: 0~15 as BRG1~BRG16 241 rate: baud rate 242 * BRG input clock comes from the BRGCLK (internal clock generated from 243 the QE clock, it is one-half of the QE clock), If need the clock source 244 from CLKn pin, we have te change the function. 245 */ 246 247 #define BRG_CLK (gd->arch.brg_clk) 248 249 #ifdef CONFIG_QE 250 int qe_set_brg(uint brg, uint rate) 251 { 252 volatile uint *bp; 253 u32 divisor; 254 int div16 = 0; 255 256 if (brg >= QE_NUM_OF_BRGS) 257 return -EINVAL; 258 bp = (uint *)&qe_immr->brg.brgc1; 259 bp += brg; 260 261 divisor = (BRG_CLK / rate); 262 if (divisor > QE_BRGC_DIVISOR_MAX + 1) { 263 div16 = 1; 264 divisor /= 16; 265 } 266 267 *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE; 268 __asm__ __volatile__("sync"); 269 270 if (div16) { 271 *bp |= QE_BRGC_DIV16; 272 __asm__ __volatile__("sync"); 273 } 274 275 return 0; 276 } 277 #endif 278 279 /* Set ethernet MII clock master 280 */ 281 int qe_set_mii_clk_src(int ucc_num) 282 { 283 u32 cmxgcr; 284 285 /* check if the UCC number is in range. */ 286 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) { 287 printf("%s: ucc num not in ranges\n", __FUNCTION__); 288 return -EINVAL; 289 } 290 291 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr); 292 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK; 293 cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT); 294 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr); 295 296 return 0; 297 } 298 299 /* Firmware information stored here for qe_get_firmware_info() */ 300 static struct qe_firmware_info qe_firmware_info; 301 302 /* 303 * Set to 1 if QE firmware has been uploaded, and therefore 304 * qe_firmware_info contains valid data. 305 */ 306 static int qe_firmware_uploaded; 307 308 /* 309 * Upload a QE microcode 310 * 311 * This function is a worker function for qe_upload_firmware(). It does 312 * the actual uploading of the microcode. 313 */ 314 static void qe_upload_microcode(const void *base, 315 const struct qe_microcode *ucode) 316 { 317 const u32 *code = base + be32_to_cpu(ucode->code_offset); 318 unsigned int i; 319 320 if (ucode->major || ucode->minor || ucode->revision) 321 printf("QE: uploading microcode '%s' version %u.%u.%u\n", 322 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor, 323 (u16)ucode->revision); 324 else 325 printf("QE: uploading microcode '%s'\n", (char *)ucode->id); 326 327 /* Use auto-increment */ 328 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) | 329 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR); 330 331 for (i = 0; i < be32_to_cpu(ucode->count); i++) 332 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i])); 333 } 334 335 /* 336 * Upload a microcode to the I-RAM at a specific address. 337 * 338 * See docs/README.qe_firmware for information on QE microcode uploading. 339 * 340 * Currently, only version 1 is supported, so the 'version' field must be 341 * set to 1. 342 * 343 * The SOC model and revision are not validated, they are only displayed for 344 * informational purposes. 345 * 346 * 'calc_size' is the calculated size, in bytes, of the firmware structure and 347 * all of the microcode structures, minus the CRC. 348 * 349 * 'length' is the size that the structure says it is, including the CRC. 350 */ 351 int qe_upload_firmware(const struct qe_firmware *firmware) 352 { 353 unsigned int i; 354 unsigned int j; 355 u32 crc; 356 size_t calc_size = sizeof(struct qe_firmware); 357 size_t length; 358 const struct qe_header *hdr; 359 #ifdef CONFIG_DEEP_SLEEP 360 #ifdef CONFIG_LS102XA 361 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; 362 #else 363 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 364 #endif 365 #endif 366 if (!firmware) { 367 printf("Invalid address\n"); 368 return -EINVAL; 369 } 370 371 hdr = &firmware->header; 372 length = be32_to_cpu(hdr->length); 373 374 /* Check the magic */ 375 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || 376 (hdr->magic[2] != 'F')) { 377 printf("QE microcode not found\n"); 378 #ifdef CONFIG_DEEP_SLEEP 379 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); 380 #endif 381 return -EPERM; 382 } 383 384 /* Check the version */ 385 if (hdr->version != 1) { 386 printf("Unsupported version\n"); 387 return -EPERM; 388 } 389 390 /* Validate some of the fields */ 391 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) { 392 printf("Invalid data\n"); 393 return -EINVAL; 394 } 395 396 /* Validate the length and check if there's a CRC */ 397 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode); 398 399 for (i = 0; i < firmware->count; i++) 400 /* 401 * For situations where the second RISC uses the same microcode 402 * as the first, the 'code_offset' and 'count' fields will be 403 * zero, so it's okay to add those. 404 */ 405 calc_size += sizeof(u32) * 406 be32_to_cpu(firmware->microcode[i].count); 407 408 /* Validate the length */ 409 if (length != calc_size + sizeof(u32)) { 410 printf("Invalid length\n"); 411 return -EPERM; 412 } 413 414 /* 415 * Validate the CRC. We would normally call crc32_no_comp(), but that 416 * function isn't available unless you turn on JFFS support. 417 */ 418 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size)); 419 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) { 420 printf("Firmware CRC is invalid\n"); 421 return -EIO; 422 } 423 424 /* 425 * If the microcode calls for it, split the I-RAM. 426 */ 427 if (!firmware->split) { 428 out_be16(&qe_immr->cp.cercr, 429 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR); 430 } 431 432 if (firmware->soc.model) 433 printf("Firmware '%s' for %u V%u.%u\n", 434 firmware->id, be16_to_cpu(firmware->soc.model), 435 firmware->soc.major, firmware->soc.minor); 436 else 437 printf("Firmware '%s'\n", firmware->id); 438 439 /* 440 * The QE only supports one microcode per RISC, so clear out all the 441 * saved microcode information and put in the new. 442 */ 443 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info)); 444 strncpy(qe_firmware_info.id, (char *)firmware->id, 62); 445 qe_firmware_info.extended_modes = firmware->extended_modes; 446 memcpy(qe_firmware_info.vtraps, firmware->vtraps, 447 sizeof(firmware->vtraps)); 448 qe_firmware_uploaded = 1; 449 450 /* Loop through each microcode. */ 451 for (i = 0; i < firmware->count; i++) { 452 const struct qe_microcode *ucode = &firmware->microcode[i]; 453 454 /* Upload a microcode if it's present */ 455 if (ucode->code_offset) 456 qe_upload_microcode(firmware, ucode); 457 458 /* Program the traps for this processor */ 459 for (j = 0; j < 16; j++) { 460 u32 trap = be32_to_cpu(ucode->traps[j]); 461 462 if (trap) 463 out_be32(&qe_immr->rsp[i].tibcr[j], trap); 464 } 465 466 /* Enable traps */ 467 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); 468 } 469 470 return 0; 471 } 472 473 #ifdef CONFIG_U_QE 474 /* 475 * Upload a microcode to the I-RAM at a specific address. 476 * 477 * See docs/README.qe_firmware for information on QE microcode uploading. 478 * 479 * Currently, only version 1 is supported, so the 'version' field must be 480 * set to 1. 481 * 482 * The SOC model and revision are not validated, they are only displayed for 483 * informational purposes. 484 * 485 * 'calc_size' is the calculated size, in bytes, of the firmware structure and 486 * all of the microcode structures, minus the CRC. 487 * 488 * 'length' is the size that the structure says it is, including the CRC. 489 */ 490 int u_qe_upload_firmware(const struct qe_firmware *firmware) 491 { 492 unsigned int i; 493 unsigned int j; 494 u32 crc; 495 size_t calc_size = sizeof(struct qe_firmware); 496 size_t length; 497 const struct qe_header *hdr; 498 #ifdef CONFIG_DEEP_SLEEP 499 #ifdef CONFIG_LS102XA 500 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; 501 #else 502 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 503 #endif 504 #endif 505 if (!firmware) { 506 printf("Invalid address\n"); 507 return -EINVAL; 508 } 509 510 hdr = &firmware->header; 511 length = be32_to_cpu(hdr->length); 512 513 /* Check the magic */ 514 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || 515 (hdr->magic[2] != 'F')) { 516 printf("Not a microcode\n"); 517 #ifdef CONFIG_DEEP_SLEEP 518 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); 519 #endif 520 return -EPERM; 521 } 522 523 /* Check the version */ 524 if (hdr->version != 1) { 525 printf("Unsupported version\n"); 526 return -EPERM; 527 } 528 529 /* Validate some of the fields */ 530 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) { 531 printf("Invalid data\n"); 532 return -EINVAL; 533 } 534 535 /* Validate the length and check if there's a CRC */ 536 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode); 537 538 for (i = 0; i < firmware->count; i++) 539 /* 540 * For situations where the second RISC uses the same microcode 541 * as the first, the 'code_offset' and 'count' fields will be 542 * zero, so it's okay to add those. 543 */ 544 calc_size += sizeof(u32) * 545 be32_to_cpu(firmware->microcode[i].count); 546 547 /* Validate the length */ 548 if (length != calc_size + sizeof(u32)) { 549 printf("Invalid length\n"); 550 return -EPERM; 551 } 552 553 /* 554 * Validate the CRC. We would normally call crc32_no_comp(), but that 555 * function isn't available unless you turn on JFFS support. 556 */ 557 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size)); 558 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) { 559 printf("Firmware CRC is invalid\n"); 560 return -EIO; 561 } 562 563 /* 564 * If the microcode calls for it, split the I-RAM. 565 */ 566 if (!firmware->split) { 567 out_be16(&qe_immr->cp.cercr, 568 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR); 569 } 570 571 if (firmware->soc.model) 572 printf("Firmware '%s' for %u V%u.%u\n", 573 firmware->id, be16_to_cpu(firmware->soc.model), 574 firmware->soc.major, firmware->soc.minor); 575 else 576 printf("Firmware '%s'\n", firmware->id); 577 578 /* Loop through each microcode. */ 579 for (i = 0; i < firmware->count; i++) { 580 const struct qe_microcode *ucode = &firmware->microcode[i]; 581 582 /* Upload a microcode if it's present */ 583 if (ucode->code_offset) 584 qe_upload_microcode(firmware, ucode); 585 586 /* Program the traps for this processor */ 587 for (j = 0; j < 16; j++) { 588 u32 trap = be32_to_cpu(ucode->traps[j]); 589 590 if (trap) 591 out_be32(&qe_immr->rsp[i].tibcr[j], trap); 592 } 593 594 /* Enable traps */ 595 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); 596 } 597 598 return 0; 599 } 600 #endif 601 602 #ifdef CONFIG_U_QE 603 int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr) 604 { 605 unsigned int i; 606 unsigned int j; 607 const struct qe_header *hdr; 608 const u32 *code; 609 #ifdef CONFIG_DEEP_SLEEP 610 #ifdef CONFIG_PPC 611 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 612 #else 613 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; 614 #endif 615 #endif 616 617 if (!firmware) 618 return -EINVAL; 619 620 hdr = &firmware->header; 621 622 /* Check the magic */ 623 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || 624 (hdr->magic[2] != 'F')) { 625 #ifdef CONFIG_DEEP_SLEEP 626 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); 627 #endif 628 return -EPERM; 629 } 630 631 /* 632 * If the microcode calls for it, split the I-RAM. 633 */ 634 if (!firmware->split) { 635 out_be16(&qe_immrr->cp.cercr, 636 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR); 637 } 638 639 /* Loop through each microcode. */ 640 for (i = 0; i < firmware->count; i++) { 641 const struct qe_microcode *ucode = &firmware->microcode[i]; 642 643 /* Upload a microcode if it's present */ 644 if (!ucode->code_offset) 645 return 0; 646 647 code = (const void *)firmware + be32_to_cpu(ucode->code_offset); 648 649 /* Use auto-increment */ 650 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) | 651 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR); 652 653 for (i = 0; i < be32_to_cpu(ucode->count); i++) 654 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i])); 655 656 /* Program the traps for this processor */ 657 for (j = 0; j < 16; j++) { 658 u32 trap = be32_to_cpu(ucode->traps[j]); 659 660 if (trap) 661 out_be32(&qe_immrr->rsp[i].tibcr[j], trap); 662 } 663 664 /* Enable traps */ 665 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); 666 } 667 668 return 0; 669 } 670 #endif 671 672 struct qe_firmware_info *qe_get_firmware_info(void) 673 { 674 return qe_firmware_uploaded ? &qe_firmware_info : NULL; 675 } 676 677 static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 678 { 679 ulong addr; 680 681 if (argc < 3) 682 return cmd_usage(cmdtp); 683 684 if (strcmp(argv[1], "fw") == 0) { 685 addr = simple_strtoul(argv[2], NULL, 16); 686 687 if (!addr) { 688 printf("Invalid address\n"); 689 return -EINVAL; 690 } 691 692 /* 693 * If a length was supplied, compare that with the 'length' 694 * field. 695 */ 696 697 if (argc > 3) { 698 ulong length = simple_strtoul(argv[3], NULL, 16); 699 struct qe_firmware *firmware = (void *) addr; 700 701 if (length != be32_to_cpu(firmware->header.length)) { 702 printf("Length mismatch\n"); 703 return -EINVAL; 704 } 705 } 706 707 return qe_upload_firmware((const struct qe_firmware *) addr); 708 } 709 710 return cmd_usage(cmdtp); 711 } 712 713 U_BOOT_CMD( 714 qe, 4, 0, qe_cmd, 715 "QUICC Engine commands", 716 "fw <addr> [<length>] - Upload firmware binary at address <addr> to " 717 "the QE,\n" 718 "\twith optional length <length> verification." 719 ); 720