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