blob: 31e0e3b4d50d759e6d2d87fa74c3e527766ce0f0 [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"
Qianyu Gong2459afb2016-02-18 13:01:59 +080015#include <fsl_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;
Zhao Qiang3bf46e62016-02-05 10:04:16 +080023#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -060024static qe_snum_t snums[QE_NUM_OF_SNUM];
Zhao Qiang3bf46e62016-02-05 10:04:16 +080025#endif
Dave Liu7737d5c2006-11-03 12:11:15 -060026
Wolfgang Denk1218abf2007-09-15 20:48:41 +020027DECLARE_GLOBAL_DATA_PTR;
28
Dave Liu7737d5c2006-11-03 12:11:15 -060029void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
30{
Wolfgang Denkd3a65322008-01-10 00:55:14 +010031 u32 cecr;
Dave Liu7737d5c2006-11-03 12:11:15 -060032
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 /* Wait for the QE_CR_FLG to clear */
41 do {
42 cecr = in_be32(&qe_immr->cp.cecr);
43 } while (cecr & QE_CR_FLG);
44
45 return;
46}
47
Zhao Qiang93d33202014-09-25 13:52:25 +080048#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -060049uint qe_muram_alloc(uint size, uint align)
50{
Dave Liu7737d5c2006-11-03 12:11:15 -060051 uint retloc;
52 uint align_mask, off;
53 uint savebase;
54
55 align_mask = align - 1;
Simon Glass45bae2e2012-12-13 20:48:50 +000056 savebase = gd->arch.mp_alloc_base;
Dave Liu7737d5c2006-11-03 12:11:15 -060057
Simon Glass45bae2e2012-12-13 20:48:50 +000058 off = gd->arch.mp_alloc_base & align_mask;
59 if (off != 0)
60 gd->arch.mp_alloc_base += (align - off);
Dave Liu7737d5c2006-11-03 12:11:15 -060061
62 if ((off = size & align_mask) != 0)
63 size += (align - off);
64
Simon Glass45bae2e2012-12-13 20:48:50 +000065 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) {
66 gd->arch.mp_alloc_base = savebase;
Dave Liu7737d5c2006-11-03 12:11:15 -060067 printf("%s: ran out of ram.\n", __FUNCTION__);
68 }
69
Simon Glass45bae2e2012-12-13 20:48:50 +000070 retloc = gd->arch.mp_alloc_base;
71 gd->arch.mp_alloc_base += size;
Dave Liu7737d5c2006-11-03 12:11:15 -060072
73 memset((void *)&qe_immr->muram[retloc], 0, size);
74
75 __asm__ __volatile__("sync");
76
77 return retloc;
78}
Zhao Qiang93d33202014-09-25 13:52:25 +080079#endif
Dave Liu7737d5c2006-11-03 12:11:15 -060080
81void *qe_muram_addr(uint offset)
82{
83 return (void *)&qe_immr->muram[offset];
84}
85
Zhao Qiang3bf46e62016-02-05 10:04:16 +080086#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -060087static 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 /* All of DMA transaction in bus 1 */
95 out_be32(&p->sdaqr, 0);
96 out_be32(&p->sdaqmr, 0);
97
98 /* Allocate 2KB temporary buffer for sdma */
Dave Liuff9658d2007-06-25 10:41:04 +080099 sdma_buffer_base = qe_muram_alloc(2048, 4096);
Dave Liu7737d5c2006-11-03 12:11:15 -0600100 out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);
101
102 /* Clear sdma status */
103 out_be32(&p->sdsr, 0x03000000);
104
105 /* Enable global mode on bus 1, and 2KB buffer size */
106 out_be32(&p->sdmr, QE_SDMR_GLB_1_MSK | (0x3 << QE_SDMR_CEN_SHIFT));
107}
108
Haiying Wang4e7b25e2009-05-20 12:30:35 -0400109/* This table is a list of the serial numbers of the Threads, taken from the
110 * "SNUM Table" chart in the QE Reference Manual. The order is not important,
111 * we just need to know what the SNUMs are for the threads.
112 */
113static u8 thread_snum[] = {
Gerlando Falautoa88731a2012-10-10 22:13:08 +0000114/* Evthreads 16-29 are not supported in MPC8309 */
115#if !defined(CONFIG_MPC8309)
Dave Liu7737d5c2006-11-03 12:11:15 -0600116 0x04, 0x05, 0x0c, 0x0d,
117 0x14, 0x15, 0x1c, 0x1d,
118 0x24, 0x25, 0x2c, 0x2d,
Gerlando Falautoa88731a2012-10-10 22:13:08 +0000119 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
Dave Liu7737d5c2006-11-03 12:11:15 -0600129};
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{
Dave Liu7737d5c2006-11-03 12:11:15 -0600171 /* Init the QE IMMR base */
172 qe_immr = (qe_map_t *)qe_base;
173
Timur Tabif2717b42011-11-22 09:21:25 -0600174#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
Wolfgang Denkc0a14ae2009-04-05 00:27:57 +0200175 /*
176 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
177 */
Zhao Qiangdcf1d772014-03-21 16:21:44 +0800178 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Haiying Wang2d4de6a2009-03-26 17:01:49 -0400179
Wolfgang Denkc0a14ae2009-04-05 00:27:57 +0200180 /* enable the microcode in IRAM */
181 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
Haiying Wang2d4de6a2009-03-26 17:01:49 -0400182#endif
183
Simon Glass45bae2e2012-12-13 20:48:50 +0000184 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
185 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
Dave Liu7737d5c2006-11-03 12:11:15 -0600186
187 qe_sdma_init();
188 qe_snums_init();
189}
Zhao Qiang3bf46e62016-02-05 10:04:16 +0800190#endif
Dave Liu7737d5c2006-11-03 12:11:15 -0600191
Zhao Qiang93d33202014-09-25 13:52:25 +0800192#ifdef CONFIG_U_QE
193void u_qe_init(void)
194{
195 uint qe_base = CONFIG_SYS_IMMR + 0x01400000; /* QE immr base */
196 qe_immr = (qe_map_t *)qe_base;
197
Zhao Qiang5632d152014-11-04 13:46:16 +0800198 u_qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Zhao Qiang93d33202014-09-25 13:52:25 +0800199 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
200}
201#endif
202
Zhao Qiangae42eb02015-03-25 17:02:59 +0800203#ifdef CONFIG_U_QE
204void u_qe_resume(void)
205{
206 qe_map_t *qe_immrr;
207 uint qe_base = CONFIG_SYS_IMMR + QE_IMMR_OFFSET; /* QE immr base */
208 qe_immrr = (qe_map_t *)qe_base;
209
210 u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr);
211 out_be32(&qe_immrr->iram.iready, QE_IRAM_READY);
212}
213#endif
214
Dave Liu7737d5c2006-11-03 12:11:15 -0600215void qe_reset(void)
216{
217 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
218 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
219}
220
Zhao Qiang3bf46e62016-02-05 10:04:16 +0800221#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -0600222void qe_assign_page(uint snum, uint para_ram_base)
223{
224 u32 cecr;
225
226 out_be32(&qe_immr->cp.cecdr, para_ram_base);
227 out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
228 | QE_CR_FLG | QE_ASSIGN_PAGE);
229
230 /* Wait for the QE_CR_FLG to clear */
231 do {
232 cecr = in_be32(&qe_immr->cp.cecr);
233 } while (cecr & QE_CR_FLG );
234
235 return;
236}
Zhao Qiang3bf46e62016-02-05 10:04:16 +0800237#endif
Dave Liu7737d5c2006-11-03 12:11:15 -0600238
239/*
240 * brg: 0~15 as BRG1~BRG16
241 rate: baud rate
242 * BRG input clock comes from the BRGCLK (internal clock generated from
243 the QE clock, it is one-half of the QE clock), If need the clock source
244 from CLKn pin, we have te change the function.
245 */
246
Simon Glass1206c182012-12-13 20:48:44 +0000247#define BRG_CLK (gd->arch.brg_clk)
Dave Liu7737d5c2006-11-03 12:11:15 -0600248
Zhao Qiang93d33202014-09-25 13:52:25 +0800249#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -0600250int qe_set_brg(uint brg, uint rate)
251{
Dave Liu7737d5c2006-11-03 12:11:15 -0600252 volatile uint *bp;
253 u32 divisor;
254 int div16 = 0;
255
256 if (brg >= QE_NUM_OF_BRGS)
257 return -EINVAL;
258 bp = (uint *)&qe_immr->brg.brgc1;
259 bp += brg;
260
261 divisor = (BRG_CLK / rate);
262 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
263 div16 = 1;
264 divisor /= 16;
265 }
266
267 *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
268 __asm__ __volatile__("sync");
269
270 if (div16) {
271 *bp |= QE_BRGC_DIV16;
272 __asm__ __volatile__("sync");
273 }
274
275 return 0;
276}
Zhao Qiang93d33202014-09-25 13:52:25 +0800277#endif
Dave Liu7737d5c2006-11-03 12:11:15 -0600278
279/* Set ethernet MII clock master
280*/
281int qe_set_mii_clk_src(int ucc_num)
282{
283 u32 cmxgcr;
284
285 /* check if the UCC number is in range. */
286 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) {
287 printf("%s: ucc num not in ranges\n", __FUNCTION__);
288 return -EINVAL;
289 }
290
291 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
292 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
293 cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT);
294 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
295
296 return 0;
297}
298
Timur Tabib8ec2382008-01-07 13:31:19 -0600299/* Firmware information stored here for qe_get_firmware_info() */
300static struct qe_firmware_info qe_firmware_info;
301
302/*
303 * Set to 1 if QE firmware has been uploaded, and therefore
304 * qe_firmware_info contains valid data.
305 */
306static int qe_firmware_uploaded;
307
308/*
309 * Upload a QE microcode
310 *
311 * This function is a worker function for qe_upload_firmware(). It does
312 * the actual uploading of the microcode.
313 */
314static void qe_upload_microcode(const void *base,
315 const struct qe_microcode *ucode)
316{
317 const u32 *code = base + be32_to_cpu(ucode->code_offset);
318 unsigned int i;
319
320 if (ucode->major || ucode->minor || ucode->revision)
321 printf("QE: uploading microcode '%s' version %u.%u.%u\n",
Zhao Qiange94a8fd2015-05-05 15:53:32 +0800322 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor,
323 (u16)ucode->revision);
Timur Tabib8ec2382008-01-07 13:31:19 -0600324 else
Zhao Qiange94a8fd2015-05-05 15:53:32 +0800325 printf("QE: uploading microcode '%s'\n", (char *)ucode->id);
Timur Tabib8ec2382008-01-07 13:31:19 -0600326
327 /* Use auto-increment */
328 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
329 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
330
331 for (i = 0; i < be32_to_cpu(ucode->count); i++)
332 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
333}
334
335/*
336 * Upload a microcode to the I-RAM at a specific address.
337 *
338 * See docs/README.qe_firmware for information on QE microcode uploading.
339 *
340 * Currently, only version 1 is supported, so the 'version' field must be
341 * set to 1.
342 *
343 * The SOC model and revision are not validated, they are only displayed for
344 * informational purposes.
345 *
346 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
347 * all of the microcode structures, minus the CRC.
348 *
349 * 'length' is the size that the structure says it is, including the CRC.
350 */
351int qe_upload_firmware(const struct qe_firmware *firmware)
352{
353 unsigned int i;
354 unsigned int j;
355 u32 crc;
356 size_t calc_size = sizeof(struct qe_firmware);
357 size_t length;
358 const struct qe_header *hdr;
Zhao Qiangca721fb2014-04-30 16:45:31 +0800359#ifdef CONFIG_DEEP_SLEEP
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800360#ifdef CONFIG_LS102XA
361 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
362#else
Zhao Qiangca721fb2014-04-30 16:45:31 +0800363 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
364#endif
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800365#endif
Timur Tabib8ec2382008-01-07 13:31:19 -0600366 if (!firmware) {
367 printf("Invalid address\n");
368 return -EINVAL;
369 }
370
371 hdr = &firmware->header;
372 length = be32_to_cpu(hdr->length);
373
374 /* Check the magic */
375 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
376 (hdr->magic[2] != 'F')) {
Vijay Rai12eeb132014-07-23 18:33:16 +0530377 printf("QE microcode not found\n");
Zhao Qiangca721fb2014-04-30 16:45:31 +0800378#ifdef CONFIG_DEEP_SLEEP
379 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
380#endif
Timur Tabib8ec2382008-01-07 13:31:19 -0600381 return -EPERM;
382 }
383
384 /* Check the version */
385 if (hdr->version != 1) {
386 printf("Unsupported version\n");
387 return -EPERM;
388 }
389
390 /* Validate some of the fields */
Timur Tabi491fb6d2008-03-03 09:58:52 -0600391 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabib8ec2382008-01-07 13:31:19 -0600392 printf("Invalid data\n");
393 return -EINVAL;
394 }
395
396 /* Validate the length and check if there's a CRC */
397 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
398
399 for (i = 0; i < firmware->count; i++)
400 /*
401 * For situations where the second RISC uses the same microcode
402 * as the first, the 'code_offset' and 'count' fields will be
403 * zero, so it's okay to add those.
404 */
405 calc_size += sizeof(u32) *
406 be32_to_cpu(firmware->microcode[i].count);
407
408 /* Validate the length */
409 if (length != calc_size + sizeof(u32)) {
410 printf("Invalid length\n");
411 return -EPERM;
412 }
413
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100414 /*
415 * Validate the CRC. We would normally call crc32_no_comp(), but that
416 * function isn't available unless you turn on JFFS support.
417 */
Timur Tabib8ec2382008-01-07 13:31:19 -0600418 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
419 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
420 printf("Firmware CRC is invalid\n");
421 return -EIO;
422 }
423
424 /*
425 * If the microcode calls for it, split the I-RAM.
426 */
427 if (!firmware->split) {
428 out_be16(&qe_immr->cp.cercr,
429 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
430 }
431
432 if (firmware->soc.model)
433 printf("Firmware '%s' for %u V%u.%u\n",
434 firmware->id, be16_to_cpu(firmware->soc.model),
435 firmware->soc.major, firmware->soc.minor);
436 else
437 printf("Firmware '%s'\n", firmware->id);
438
439 /*
440 * The QE only supports one microcode per RISC, so clear out all the
441 * saved microcode information and put in the new.
442 */
443 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Zhao Qiang0e0224e2015-05-05 15:53:33 +0800444 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabib8ec2382008-01-07 13:31:19 -0600445 qe_firmware_info.extended_modes = firmware->extended_modes;
446 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
447 sizeof(firmware->vtraps));
448 qe_firmware_uploaded = 1;
449
450 /* Loop through each microcode. */
451 for (i = 0; i < firmware->count; i++) {
452 const struct qe_microcode *ucode = &firmware->microcode[i];
453
454 /* Upload a microcode if it's present */
455 if (ucode->code_offset)
456 qe_upload_microcode(firmware, ucode);
457
458 /* Program the traps for this processor */
459 for (j = 0; j < 16; j++) {
460 u32 trap = be32_to_cpu(ucode->traps[j]);
461
462 if (trap)
463 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
464 }
465
466 /* Enable traps */
467 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
468 }
469
470 return 0;
471}
472
Zhao Qiang5632d152014-11-04 13:46:16 +0800473#ifdef CONFIG_U_QE
474/*
475 * Upload a microcode to the I-RAM at a specific address.
476 *
477 * See docs/README.qe_firmware for information on QE microcode uploading.
478 *
479 * Currently, only version 1 is supported, so the 'version' field must be
480 * set to 1.
481 *
482 * The SOC model and revision are not validated, they are only displayed for
483 * informational purposes.
484 *
485 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
486 * all of the microcode structures, minus the CRC.
487 *
488 * 'length' is the size that the structure says it is, including the CRC.
489 */
490int u_qe_upload_firmware(const struct qe_firmware *firmware)
491{
492 unsigned int i;
493 unsigned int j;
494 u32 crc;
495 size_t calc_size = sizeof(struct qe_firmware);
496 size_t length;
497 const struct qe_header *hdr;
498#ifdef CONFIG_DEEP_SLEEP
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800499#ifdef CONFIG_LS102XA
500 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
501#else
Zhao Qiang5632d152014-11-04 13:46:16 +0800502 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
503#endif
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800504#endif
Zhao Qiang5632d152014-11-04 13:46:16 +0800505 if (!firmware) {
506 printf("Invalid address\n");
507 return -EINVAL;
508 }
509
510 hdr = &firmware->header;
511 length = be32_to_cpu(hdr->length);
512
513 /* Check the magic */
514 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
515 (hdr->magic[2] != 'F')) {
516 printf("Not a microcode\n");
517#ifdef CONFIG_DEEP_SLEEP
518 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
519#endif
520 return -EPERM;
521 }
522
523 /* Check the version */
524 if (hdr->version != 1) {
525 printf("Unsupported version\n");
526 return -EPERM;
527 }
528
529 /* Validate some of the fields */
530 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
531 printf("Invalid data\n");
532 return -EINVAL;
533 }
534
535 /* Validate the length and check if there's a CRC */
536 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
537
538 for (i = 0; i < firmware->count; i++)
539 /*
540 * For situations where the second RISC uses the same microcode
541 * as the first, the 'code_offset' and 'count' fields will be
542 * zero, so it's okay to add those.
543 */
544 calc_size += sizeof(u32) *
545 be32_to_cpu(firmware->microcode[i].count);
546
547 /* Validate the length */
548 if (length != calc_size + sizeof(u32)) {
549 printf("Invalid length\n");
550 return -EPERM;
551 }
552
553 /*
554 * Validate the CRC. We would normally call crc32_no_comp(), but that
555 * function isn't available unless you turn on JFFS support.
556 */
557 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
558 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
559 printf("Firmware CRC is invalid\n");
560 return -EIO;
561 }
562
563 /*
564 * If the microcode calls for it, split the I-RAM.
565 */
566 if (!firmware->split) {
567 out_be16(&qe_immr->cp.cercr,
568 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
569 }
570
571 if (firmware->soc.model)
572 printf("Firmware '%s' for %u V%u.%u\n",
573 firmware->id, be16_to_cpu(firmware->soc.model),
574 firmware->soc.major, firmware->soc.minor);
575 else
576 printf("Firmware '%s'\n", firmware->id);
577
578 /* Loop through each microcode. */
579 for (i = 0; i < firmware->count; i++) {
580 const struct qe_microcode *ucode = &firmware->microcode[i];
581
582 /* Upload a microcode if it's present */
583 if (ucode->code_offset)
584 qe_upload_microcode(firmware, ucode);
585
586 /* Program the traps for this processor */
587 for (j = 0; j < 16; j++) {
588 u32 trap = be32_to_cpu(ucode->traps[j]);
589
590 if (trap)
591 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
592 }
593
594 /* Enable traps */
595 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
596 }
597
598 return 0;
599}
600#endif
601
Zhao Qiangae42eb02015-03-25 17:02:59 +0800602#ifdef CONFIG_U_QE
603int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
604{
605 unsigned int i;
606 unsigned int j;
607 const struct qe_header *hdr;
608 const u32 *code;
609#ifdef CONFIG_DEEP_SLEEP
610#ifdef CONFIG_PPC
611 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
612#else
613 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
614#endif
615#endif
616
617 if (!firmware)
618 return -EINVAL;
619
620 hdr = &firmware->header;
621
622 /* Check the magic */
623 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
624 (hdr->magic[2] != 'F')) {
625#ifdef CONFIG_DEEP_SLEEP
626 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
627#endif
628 return -EPERM;
629 }
630
631 /*
632 * If the microcode calls for it, split the I-RAM.
633 */
634 if (!firmware->split) {
635 out_be16(&qe_immrr->cp.cercr,
636 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
637 }
638
639 /* Loop through each microcode. */
640 for (i = 0; i < firmware->count; i++) {
641 const struct qe_microcode *ucode = &firmware->microcode[i];
642
643 /* Upload a microcode if it's present */
644 if (!ucode->code_offset)
645 return 0;
646
647 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
648
649 /* Use auto-increment */
650 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
651 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
652
653 for (i = 0; i < be32_to_cpu(ucode->count); i++)
654 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
655
656 /* Program the traps for this processor */
657 for (j = 0; j < 16; j++) {
658 u32 trap = be32_to_cpu(ucode->traps[j]);
659
660 if (trap)
661 out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
662 }
663
664 /* Enable traps */
665 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
666 }
667
668 return 0;
669}
670#endif
671
Timur Tabib8ec2382008-01-07 13:31:19 -0600672struct qe_firmware_info *qe_get_firmware_info(void)
673{
674 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
675}
676
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200677static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Timur Tabib8ec2382008-01-07 13:31:19 -0600678{
679 ulong addr;
680
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200681 if (argc < 3)
682 return cmd_usage(cmdtp);
Timur Tabib8ec2382008-01-07 13:31:19 -0600683
684 if (strcmp(argv[1], "fw") == 0) {
685 addr = simple_strtoul(argv[2], NULL, 16);
686
687 if (!addr) {
688 printf("Invalid address\n");
689 return -EINVAL;
690 }
691
Wolfgang Denkd3a65322008-01-10 00:55:14 +0100692 /*
693 * If a length was supplied, compare that with the 'length'
694 * field.
695 */
Timur Tabib8ec2382008-01-07 13:31:19 -0600696
697 if (argc > 3) {
698 ulong length = simple_strtoul(argv[3], NULL, 16);
699 struct qe_firmware *firmware = (void *) addr;
700
701 if (length != be32_to_cpu(firmware->header.length)) {
702 printf("Length mismatch\n");
703 return -EINVAL;
704 }
705 }
706
707 return qe_upload_firmware((const struct qe_firmware *) addr);
708 }
709
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200710 return cmd_usage(cmdtp);
Timur Tabib8ec2382008-01-07 13:31:19 -0600711}
712
713U_BOOT_CMD(
714 qe, 4, 0, qe_cmd,
Peter Tyser2fb26042009-01-27 18:03:12 -0600715 "QUICC Engine commands",
Timur Tabib8ec2382008-01-07 13:31:19 -0600716 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200717 "the QE,\n"
718 "\twith optional length <length> verification."
719);