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