blob: 84e1433d9ee746e847fd11d2c283652364952f5b [file] [log] [blame]
Dave Liu7737d5c2006-11-03 12:11:15 -06001/*
Haiying Wang4e7b25e2009-05-20 12:30:35 -04002 * Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
Dave Liu7737d5c2006-11-03 12:11:15 -06003 *
4 * Dave Liu <daveliu@freescale.com>
5 * based on source code of Shlomi Gridish
6 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Dave Liu7737d5c2006-11-03 12:11:15 -06008 */
9
10#include "common.h"
Timur Tabib8ec2382008-01-07 13:31:19 -060011#include <command.h>
Dave Liu7737d5c2006-11-03 12:11:15 -060012#include "asm/errno.h"
13#include "asm/io.h"
Zhao Qiang38d67a4e2014-06-03 16:27:07 +080014#include "linux/immap_qe.h"
Dave Liu7737d5c2006-11-03 12:11:15 -060015#include "qe.h"
Zhao Qiang9c7c86f2014-12-15 15:50:49 +080016#ifdef CONFIG_LS102XA
17#include <asm/arch/immap_ls102xa.h>
18#endif
Dave Liu7737d5c2006-11-03 12:11:15 -060019
Zhao Qiangca721fb2014-04-30 16:45:31 +080020#define MPC85xx_DEVDISR_QE_DISABLE 0x1
21
Dave Liu7737d5c2006-11-03 12:11:15 -060022qe_map_t *qe_immr = NULL;
23static qe_snum_t snums[QE_NUM_OF_SNUM];
24
Wolfgang Denk1218abf2007-09-15 20:48:41 +020025DECLARE_GLOBAL_DATA_PTR;
26
Dave Liu7737d5c2006-11-03 12:11:15 -060027void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
28{
Wolfgang Denkd3a65322008-01-10 00:55:14 +010029 u32 cecr;
Dave Liu7737d5c2006-11-03 12:11:15 -060030
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
Zhao Qiang93d33202014-09-25 13:52:25 +080046#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -060047uint qe_muram_alloc(uint size, uint align)
48{
Dave Liu7737d5c2006-11-03 12:11:15 -060049 uint retloc;
50 uint align_mask, off;
51 uint savebase;
52
53 align_mask = align - 1;
Simon Glass45bae2e2012-12-13 20:48:50 +000054 savebase = gd->arch.mp_alloc_base;
Dave Liu7737d5c2006-11-03 12:11:15 -060055
Simon Glass45bae2e2012-12-13 20:48:50 +000056 off = gd->arch.mp_alloc_base & align_mask;
57 if (off != 0)
58 gd->arch.mp_alloc_base += (align - off);
Dave Liu7737d5c2006-11-03 12:11:15 -060059
60 if ((off = size & align_mask) != 0)
61 size += (align - off);
62
Simon Glass45bae2e2012-12-13 20:48:50 +000063 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) {
64 gd->arch.mp_alloc_base = savebase;
Dave Liu7737d5c2006-11-03 12:11:15 -060065 printf("%s: ran out of ram.\n", __FUNCTION__);
66 }
67
Simon Glass45bae2e2012-12-13 20:48:50 +000068 retloc = gd->arch.mp_alloc_base;
69 gd->arch.mp_alloc_base += size;
Dave Liu7737d5c2006-11-03 12:11:15 -060070
71 memset((void *)&qe_immr->muram[retloc], 0, size);
72
73 __asm__ __volatile__("sync");
74
75 return retloc;
76}
Zhao Qiang93d33202014-09-25 13:52:25 +080077#endif
Dave Liu7737d5c2006-11-03 12:11:15 -060078
79void *qe_muram_addr(uint offset)
80{
81 return (void *)&qe_immr->muram[offset];
82}
83
84static 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 */
Dave Liuff9658d2007-06-25 10:41:04 +080096 sdma_buffer_base = qe_muram_alloc(2048, 4096);
Dave Liu7737d5c2006-11-03 12:11:15 -060097 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
Haiying Wang4e7b25e2009-05-20 12:30:35 -0400106/* 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 */
110static u8 thread_snum[] = {
Gerlando Falautoa88731a2012-10-10 22:13:08 +0000111/* Evthreads 16-29 are not supported in MPC8309 */
112#if !defined(CONFIG_MPC8309)
Dave Liu7737d5c2006-11-03 12:11:15 -0600113 0x04, 0x05, 0x0c, 0x0d,
114 0x14, 0x15, 0x1c, 0x1d,
115 0x24, 0x25, 0x2c, 0x2d,
Gerlando Falautoa88731a2012-10-10 22:13:08 +0000116 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
Dave Liu7737d5c2006-11-03 12:11:15 -0600126};
127
128static 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
138int 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
154void 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
166void qe_init(uint qe_base)
167{
Dave Liu7737d5c2006-11-03 12:11:15 -0600168 /* Init the QE IMMR base */
169 qe_immr = (qe_map_t *)qe_base;
170
Timur Tabif2717b42011-11-22 09:21:25 -0600171#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
Wolfgang Denkc0a14ae2009-04-05 00:27:57 +0200172 /*
173 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
174 */
Zhao Qiangdcf1d772014-03-21 16:21:44 +0800175 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Haiying Wang2d4de6a2009-03-26 17:01:49 -0400176
Wolfgang Denkc0a14ae2009-04-05 00:27:57 +0200177 /* enable the microcode in IRAM */
178 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
Haiying Wang2d4de6a2009-03-26 17:01:49 -0400179#endif
180
Simon Glass45bae2e2012-12-13 20:48:50 +0000181 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
182 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
Dave Liu7737d5c2006-11-03 12:11:15 -0600183
184 qe_sdma_init();
185 qe_snums_init();
186}
187
Zhao Qiang93d33202014-09-25 13:52:25 +0800188#ifdef CONFIG_U_QE
189void 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
Zhao Qiang5632d152014-11-04 13:46:16 +0800194 u_qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Zhao Qiang93d33202014-09-25 13:52:25 +0800195 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
196}
197#endif
198
Zhao Qiangae42eb02015-03-25 17:02:59 +0800199#ifdef CONFIG_U_QE
200void 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
Dave Liu7737d5c2006-11-03 12:11:15 -0600211void qe_reset(void)
212{
213 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
214 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
215}
216
217void 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
Simon Glass1206c182012-12-13 20:48:44 +0000241#define BRG_CLK (gd->arch.brg_clk)
Dave Liu7737d5c2006-11-03 12:11:15 -0600242
Zhao Qiang93d33202014-09-25 13:52:25 +0800243#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -0600244int qe_set_brg(uint brg, uint rate)
245{
Dave Liu7737d5c2006-11-03 12:11:15 -0600246 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}
Zhao Qiang93d33202014-09-25 13:52:25 +0800271#endif
Dave Liu7737d5c2006-11-03 12:11:15 -0600272
273/* Set ethernet MII clock master
274*/
275int 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
Timur Tabib8ec2382008-01-07 13:31:19 -0600293/* Firmware information stored here for qe_get_firmware_info() */
294static 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 */
300static 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 */
308static 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 ucode->id, ucode->major, ucode->minor, ucode->revision);
317 else
318 printf("QE: uploading microcode '%s'\n", ucode->id);
319
320 /* Use auto-increment */
321 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
322 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
323
324 for (i = 0; i < be32_to_cpu(ucode->count); i++)
325 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
326}
327
328/*
329 * Upload a microcode to the I-RAM at a specific address.
330 *
331 * See docs/README.qe_firmware for information on QE microcode uploading.
332 *
333 * Currently, only version 1 is supported, so the 'version' field must be
334 * set to 1.
335 *
336 * The SOC model and revision are not validated, they are only displayed for
337 * informational purposes.
338 *
339 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
340 * all of the microcode structures, minus the CRC.
341 *
342 * 'length' is the size that the structure says it is, including the CRC.
343 */
344int qe_upload_firmware(const struct qe_firmware *firmware)
345{
346 unsigned int i;
347 unsigned int j;
348 u32 crc;
349 size_t calc_size = sizeof(struct qe_firmware);
350 size_t length;
351 const struct qe_header *hdr;
Zhao Qiangca721fb2014-04-30 16:45:31 +0800352#ifdef CONFIG_DEEP_SLEEP
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800353#ifdef CONFIG_LS102XA
354 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
355#else
Zhao Qiangca721fb2014-04-30 16:45:31 +0800356 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
357#endif
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800358#endif
Timur Tabib8ec2382008-01-07 13:31:19 -0600359 if (!firmware) {
360 printf("Invalid address\n");
361 return -EINVAL;
362 }
363
364 hdr = &firmware->header;
365 length = be32_to_cpu(hdr->length);
366
367 /* Check the magic */
368 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
369 (hdr->magic[2] != 'F')) {
Vijay Rai12eeb132014-07-23 18:33:16 +0530370 printf("QE microcode not found\n");
Zhao Qiangca721fb2014-04-30 16:45:31 +0800371#ifdef CONFIG_DEEP_SLEEP
372 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
373#endif
Timur Tabib8ec2382008-01-07 13:31:19 -0600374 return -EPERM;
375 }
376
377 /* Check the version */
378 if (hdr->version != 1) {
379 printf("Unsupported version\n");
380 return -EPERM;
381 }
382
383 /* Validate some of the fields */
Timur Tabi491fb6d2008-03-03 09:58:52 -0600384 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabib8ec2382008-01-07 13:31:19 -0600385 printf("Invalid data\n");
386 return -EINVAL;
387 }
388
389 /* Validate the length and check if there's a CRC */
390 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
391
392 for (i = 0; i < firmware->count; i++)
393 /*
394 * For situations where the second RISC uses the same microcode
395 * as the first, the 'code_offset' and 'count' fields will be
396 * zero, so it's okay to add those.
397 */
398 calc_size += sizeof(u32) *
399 be32_to_cpu(firmware->microcode[i].count);
400
401 /* Validate the length */
402 if (length != calc_size + sizeof(u32)) {
403 printf("Invalid length\n");
404 return -EPERM;
405 }
406
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100407 /*
408 * Validate the CRC. We would normally call crc32_no_comp(), but that
409 * function isn't available unless you turn on JFFS support.
410 */
Timur Tabib8ec2382008-01-07 13:31:19 -0600411 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
412 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
413 printf("Firmware CRC is invalid\n");
414 return -EIO;
415 }
416
417 /*
418 * If the microcode calls for it, split the I-RAM.
419 */
420 if (!firmware->split) {
421 out_be16(&qe_immr->cp.cercr,
422 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
423 }
424
425 if (firmware->soc.model)
426 printf("Firmware '%s' for %u V%u.%u\n",
427 firmware->id, be16_to_cpu(firmware->soc.model),
428 firmware->soc.major, firmware->soc.minor);
429 else
430 printf("Firmware '%s'\n", firmware->id);
431
432 /*
433 * The QE only supports one microcode per RISC, so clear out all the
434 * saved microcode information and put in the new.
435 */
436 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Dave Liu06c428b2008-01-14 11:12:01 +0800437 strcpy(qe_firmware_info.id, (char *)firmware->id);
Timur Tabib8ec2382008-01-07 13:31:19 -0600438 qe_firmware_info.extended_modes = firmware->extended_modes;
439 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
440 sizeof(firmware->vtraps));
441 qe_firmware_uploaded = 1;
442
443 /* Loop through each microcode. */
444 for (i = 0; i < firmware->count; i++) {
445 const struct qe_microcode *ucode = &firmware->microcode[i];
446
447 /* Upload a microcode if it's present */
448 if (ucode->code_offset)
449 qe_upload_microcode(firmware, ucode);
450
451 /* Program the traps for this processor */
452 for (j = 0; j < 16; j++) {
453 u32 trap = be32_to_cpu(ucode->traps[j]);
454
455 if (trap)
456 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
457 }
458
459 /* Enable traps */
460 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
461 }
462
463 return 0;
464}
465
Zhao Qiang5632d152014-11-04 13:46:16 +0800466#ifdef CONFIG_U_QE
467/*
468 * Upload a microcode to the I-RAM at a specific address.
469 *
470 * See docs/README.qe_firmware for information on QE microcode uploading.
471 *
472 * Currently, only version 1 is supported, so the 'version' field must be
473 * set to 1.
474 *
475 * The SOC model and revision are not validated, they are only displayed for
476 * informational purposes.
477 *
478 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
479 * all of the microcode structures, minus the CRC.
480 *
481 * 'length' is the size that the structure says it is, including the CRC.
482 */
483int u_qe_upload_firmware(const struct qe_firmware *firmware)
484{
485 unsigned int i;
486 unsigned int j;
487 u32 crc;
488 size_t calc_size = sizeof(struct qe_firmware);
489 size_t length;
490 const struct qe_header *hdr;
491#ifdef CONFIG_DEEP_SLEEP
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800492#ifdef CONFIG_LS102XA
493 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
494#else
Zhao Qiang5632d152014-11-04 13:46:16 +0800495 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
496#endif
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800497#endif
Zhao Qiang5632d152014-11-04 13:46:16 +0800498 if (!firmware) {
499 printf("Invalid address\n");
500 return -EINVAL;
501 }
502
503 hdr = &firmware->header;
504 length = be32_to_cpu(hdr->length);
505
506 /* Check the magic */
507 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
508 (hdr->magic[2] != 'F')) {
509 printf("Not a microcode\n");
510#ifdef CONFIG_DEEP_SLEEP
511 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
512#endif
513 return -EPERM;
514 }
515
516 /* Check the version */
517 if (hdr->version != 1) {
518 printf("Unsupported version\n");
519 return -EPERM;
520 }
521
522 /* Validate some of the fields */
523 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
524 printf("Invalid data\n");
525 return -EINVAL;
526 }
527
528 /* Validate the length and check if there's a CRC */
529 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
530
531 for (i = 0; i < firmware->count; i++)
532 /*
533 * For situations where the second RISC uses the same microcode
534 * as the first, the 'code_offset' and 'count' fields will be
535 * zero, so it's okay to add those.
536 */
537 calc_size += sizeof(u32) *
538 be32_to_cpu(firmware->microcode[i].count);
539
540 /* Validate the length */
541 if (length != calc_size + sizeof(u32)) {
542 printf("Invalid length\n");
543 return -EPERM;
544 }
545
546 /*
547 * Validate the CRC. We would normally call crc32_no_comp(), but that
548 * function isn't available unless you turn on JFFS support.
549 */
550 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
551 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
552 printf("Firmware CRC is invalid\n");
553 return -EIO;
554 }
555
556 /*
557 * If the microcode calls for it, split the I-RAM.
558 */
559 if (!firmware->split) {
560 out_be16(&qe_immr->cp.cercr,
561 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
562 }
563
564 if (firmware->soc.model)
565 printf("Firmware '%s' for %u V%u.%u\n",
566 firmware->id, be16_to_cpu(firmware->soc.model),
567 firmware->soc.major, firmware->soc.minor);
568 else
569 printf("Firmware '%s'\n", firmware->id);
570
571 /* Loop through each microcode. */
572 for (i = 0; i < firmware->count; i++) {
573 const struct qe_microcode *ucode = &firmware->microcode[i];
574
575 /* Upload a microcode if it's present */
576 if (ucode->code_offset)
577 qe_upload_microcode(firmware, ucode);
578
579 /* Program the traps for this processor */
580 for (j = 0; j < 16; j++) {
581 u32 trap = be32_to_cpu(ucode->traps[j]);
582
583 if (trap)
584 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
585 }
586
587 /* Enable traps */
588 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
589 }
590
591 return 0;
592}
593#endif
594
Zhao Qiangae42eb02015-03-25 17:02:59 +0800595#ifdef CONFIG_U_QE
596int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
597{
598 unsigned int i;
599 unsigned int j;
600 const struct qe_header *hdr;
601 const u32 *code;
602#ifdef CONFIG_DEEP_SLEEP
603#ifdef CONFIG_PPC
604 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
605#else
606 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
607#endif
608#endif
609
610 if (!firmware)
611 return -EINVAL;
612
613 hdr = &firmware->header;
614
615 /* Check the magic */
616 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
617 (hdr->magic[2] != 'F')) {
618#ifdef CONFIG_DEEP_SLEEP
619 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
620#endif
621 return -EPERM;
622 }
623
624 /*
625 * If the microcode calls for it, split the I-RAM.
626 */
627 if (!firmware->split) {
628 out_be16(&qe_immrr->cp.cercr,
629 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
630 }
631
632 /* Loop through each microcode. */
633 for (i = 0; i < firmware->count; i++) {
634 const struct qe_microcode *ucode = &firmware->microcode[i];
635
636 /* Upload a microcode if it's present */
637 if (!ucode->code_offset)
638 return 0;
639
640 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
641
642 /* Use auto-increment */
643 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
644 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
645
646 for (i = 0; i < be32_to_cpu(ucode->count); i++)
647 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
648
649 /* Program the traps for this processor */
650 for (j = 0; j < 16; j++) {
651 u32 trap = be32_to_cpu(ucode->traps[j]);
652
653 if (trap)
654 out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
655 }
656
657 /* Enable traps */
658 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
659 }
660
661 return 0;
662}
663#endif
664
Timur Tabib8ec2382008-01-07 13:31:19 -0600665struct qe_firmware_info *qe_get_firmware_info(void)
666{
667 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
668}
669
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200670static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Timur Tabib8ec2382008-01-07 13:31:19 -0600671{
672 ulong addr;
673
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200674 if (argc < 3)
675 return cmd_usage(cmdtp);
Timur Tabib8ec2382008-01-07 13:31:19 -0600676
677 if (strcmp(argv[1], "fw") == 0) {
678 addr = simple_strtoul(argv[2], NULL, 16);
679
680 if (!addr) {
681 printf("Invalid address\n");
682 return -EINVAL;
683 }
684
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100685 /*
686 * If a length was supplied, compare that with the 'length'
687 * field.
688 */
Timur Tabib8ec2382008-01-07 13:31:19 -0600689
690 if (argc > 3) {
691 ulong length = simple_strtoul(argv[3], NULL, 16);
692 struct qe_firmware *firmware = (void *) addr;
693
694 if (length != be32_to_cpu(firmware->header.length)) {
695 printf("Length mismatch\n");
696 return -EINVAL;
697 }
698 }
699
700 return qe_upload_firmware((const struct qe_firmware *) addr);
701 }
702
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200703 return cmd_usage(cmdtp);
Timur Tabib8ec2382008-01-07 13:31:19 -0600704}
705
706U_BOOT_CMD(
707 qe, 4, 0, qe_cmd,
Peter Tyser2fb26042009-01-27 18:03:12 -0600708 "QUICC Engine commands",
Timur Tabib8ec2382008-01-07 13:31:19 -0600709 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200710 "the QE,\n"
711 "\twith optional length <length> verification."
712);