1
2
3
4
5
6
7
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
22qe_map_t *qe_immr = NULL;
23#ifdef CONFIG_QE
24static qe_snum_t snums[QE_NUM_OF_SNUM];
25#endif
26
27DECLARE_GLOBAL_DATA_PTR;
28
29void 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
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
49uint 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
81void *qe_muram_addr(uint offset)
82{
83 return (void *)&qe_immr->muram[offset];
84}
85
86#ifdef CONFIG_QE
87static 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
95 out_be32(&p->sdaqr, 0);
96 out_be32(&p->sdaqmr, 0);
97
98
99 sdma_buffer_base = qe_muram_alloc(2048, 4096);
100 out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);
101
102
103 out_be32(&p->sdsr, 0x03000000);
104
105
106 out_be32(&p->sdmr, QE_SDMR_GLB_1_MSK | (0x3 << QE_SDMR_CEN_SHIFT));
107}
108
109
110
111
112
113static u8 thread_snum[] = {
114
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
131static 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
141int 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
157void 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
169void qe_init(uint qe_base)
170{
171
172 qe_immr = (qe_map_t *)qe_base;
173
174#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
175
176
177
178 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
179
180
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
193void 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
203void 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
213void 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
220void 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
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
239
240
241
242
243
244
245#define BRG_CLK (gd->arch.brg_clk)
246
247#ifdef CONFIG_QE
248int 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
278
279int qe_set_mii_clk_src(int ucc_num)
280{
281 u32 cmxgcr;
282
283
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
298static struct qe_firmware_info qe_firmware_info;
299
300
301
302
303
304static int qe_firmware_uploaded;
305
306
307
308
309
310
311
312static 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
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
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349int 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
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
383 if (hdr->version != 1) {
384 printf("Unsupported version\n");
385 return -EPERM;
386 }
387
388
389 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
390 printf("Invalid data\n");
391 return -EINVAL;
392 }
393
394
395 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
396
397 for (i = 0; i < firmware->count; i++)
398
399
400
401
402
403 calc_size += sizeof(u32) *
404 be32_to_cpu(firmware->microcode[i].count);
405
406
407 if (length != calc_size + sizeof(u32)) {
408 printf("Invalid length\n");
409 return -EPERM;
410 }
411
412
413
414
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
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
439
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
449 for (i = 0; i < firmware->count; i++) {
450 const struct qe_microcode *ucode = &firmware->microcode[i];
451
452
453 if (ucode->code_offset)
454 qe_upload_microcode(firmware, ucode);
455
456
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
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
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488int 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
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
522 if (hdr->version != 1) {
523 printf("Unsupported version\n");
524 return -EPERM;
525 }
526
527
528 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
529 printf("Invalid data\n");
530 return -EINVAL;
531 }
532
533
534 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
535
536 for (i = 0; i < firmware->count; i++)
537
538
539
540
541
542 calc_size += sizeof(u32) *
543 be32_to_cpu(firmware->microcode[i].count);
544
545
546 if (length != calc_size + sizeof(u32)) {
547 printf("Invalid length\n");
548 return -EPERM;
549 }
550
551
552
553
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
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
577 for (i = 0; i < firmware->count; i++) {
578 const struct qe_microcode *ucode = &firmware->microcode[i];
579
580
581 if (ucode->code_offset)
582 qe_upload_microcode(firmware, ucode);
583
584
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
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
601int 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
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
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
638 for (i = 0; i < firmware->count; i++) {
639 const struct qe_microcode *ucode = &firmware->microcode[i];
640
641
642 if (!ucode->code_offset)
643 return 0;
644
645 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
646
647
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
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
663 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
664 }
665
666 return 0;
667}
668#endif
669
670struct qe_firmware_info *qe_get_firmware_info(void)
671{
672 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
673}
674
675static 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
692
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
711U_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