blob: 08620b23a7180fba914626b471a9de5ed099b90a [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",
Zhao Qiange94a8fd2015-05-05 15:53:32 +0800316 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor,
317 (u16)ucode->revision);
Timur Tabib8ec2382008-01-07 13:31:19 -0600318 else
Zhao Qiange94a8fd2015-05-05 15:53:32 +0800319 printf("QE: uploading microcode '%s'\n", (char *)ucode->id);
Timur Tabib8ec2382008-01-07 13:31:19 -0600320
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 */
345int 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;
Zhao Qiangca721fb2014-04-30 16:45:31 +0800353#ifdef CONFIG_DEEP_SLEEP
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800354#ifdef CONFIG_LS102XA
355 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
356#else
Zhao Qiangca721fb2014-04-30 16:45:31 +0800357 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
358#endif
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800359#endif
Timur Tabib8ec2382008-01-07 13:31:19 -0600360 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')) {
Vijay Rai12eeb132014-07-23 18:33:16 +0530371 printf("QE microcode not found\n");
Zhao Qiangca721fb2014-04-30 16:45:31 +0800372#ifdef CONFIG_DEEP_SLEEP
373 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
374#endif
Timur Tabib8ec2382008-01-07 13:31:19 -0600375 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 */
Timur Tabi491fb6d2008-03-03 09:58:52 -0600385 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabib8ec2382008-01-07 13:31:19 -0600386 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
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100408 /*
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 */
Timur Tabib8ec2382008-01-07 13:31:19 -0600412 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));
Zhao Qiang0e0224e2015-05-05 15:53:33 +0800438 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabib8ec2382008-01-07 13:31:19 -0600439 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
Zhao Qiang5632d152014-11-04 13:46:16 +0800467#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 */
484int 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
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800493#ifdef CONFIG_LS102XA
494 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
495#else
Zhao Qiang5632d152014-11-04 13:46:16 +0800496 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
497#endif
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800498#endif
Zhao Qiang5632d152014-11-04 13:46:16 +0800499 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
Zhao Qiangae42eb02015-03-25 17:02:59 +0800596#ifdef CONFIG_U_QE
597int 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
Timur Tabib8ec2382008-01-07 13:31:19 -0600666struct qe_firmware_info *qe_get_firmware_info(void)
667{
668 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
669}
670
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200671static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Timur Tabib8ec2382008-01-07 13:31:19 -0600672{
673 ulong addr;
674
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200675 if (argc < 3)
676 return cmd_usage(cmdtp);
Timur Tabib8ec2382008-01-07 13:31:19 -0600677
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
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100686 /*
687 * If a length was supplied, compare that with the 'length'
688 * field.
689 */
Timur Tabib8ec2382008-01-07 13:31:19 -0600690
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
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200704 return cmd_usage(cmdtp);
Timur Tabib8ec2382008-01-07 13:31:19 -0600705}
706
707U_BOOT_CMD(
708 qe, 4, 0, qe_cmd,
Peter Tyser2fb26042009-01-27 18:03:12 -0600709 "QUICC Engine commands",
Timur Tabib8ec2382008-01-07 13:31:19 -0600710 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200711 "the QE,\n"
712 "\twith optional length <length> verification."
713);