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