blob: 5366a1eb712a7d7a8f07e1fb36be4597a01295e9 [file] [log] [blame]
Dave Liue732e9c2006-11-03 12:11:15 -06001/*
Haiying Wang0eea38e2009-05-20 12:30:35 -04002 * Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
Dave Liue732e9c2006-11-03 12:11:15 -06003 *
4 * Dave Liu <daveliu@freescale.com>
5 * based on source code of Shlomi Gridish
6 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Dave Liue732e9c2006-11-03 12:11:15 -06008 */
9
Masahiro Yamadaadae2ec2016-09-21 11:28:53 +090010#include <common.h>
Zhao Qiang82cd8c62017-05-25 09:47:40 +080011#include <malloc.h>
Timur Tabi6d838da2008-01-07 13:31:19 -060012#include <command.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090013#include <linux/errno.h>
Masahiro Yamadaadae2ec2016-09-21 11:28:53 +090014#include <asm/io.h>
15#include <linux/immap_qe.h>
Qianyu Gongae6a7582016-02-18 13:01:59 +080016#include <fsl_qe.h>
York Sunc4f047c2017-03-27 11:41:03 -070017#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +080018#include <asm/arch/immap_ls102xa.h>
19#endif
Dave Liue732e9c2006-11-03 12:11:15 -060020
Zhao Qiang82cd8c62017-05-25 09:47:40 +080021#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
22#include <mmc.h>
23#endif
24
Zhao Qiangb59534d2014-04-30 16:45:31 +080025#define MPC85xx_DEVDISR_QE_DISABLE 0x1
26
Dave Liue732e9c2006-11-03 12:11:15 -060027qe_map_t *qe_immr = NULL;
Zhao Qiang3ae22202016-02-05 10:04:16 +080028#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060029static qe_snum_t snums[QE_NUM_OF_SNUM];
Zhao Qiang3ae22202016-02-05 10:04:16 +080030#endif
Dave Liue732e9c2006-11-03 12:11:15 -060031
Wolfgang Denkd112a2c2007-09-15 20:48:41 +020032DECLARE_GLOBAL_DATA_PTR;
33
Dave Liue732e9c2006-11-03 12:11:15 -060034void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
35{
Wolfgang Denk545b06a2008-01-10 00:55:14 +010036 u32 cecr;
Dave Liue732e9c2006-11-03 12:11:15 -060037
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
Zhao Qiang5ad93952014-09-25 13:52:25 +080053#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060054uint qe_muram_alloc(uint size, uint align)
55{
Dave Liue732e9c2006-11-03 12:11:15 -060056 uint retloc;
57 uint align_mask, off;
58 uint savebase;
59
60 align_mask = align - 1;
Simon Glass8518b172012-12-13 20:48:50 +000061 savebase = gd->arch.mp_alloc_base;
Dave Liue732e9c2006-11-03 12:11:15 -060062
Simon Glass8518b172012-12-13 20:48:50 +000063 off = gd->arch.mp_alloc_base & align_mask;
64 if (off != 0)
65 gd->arch.mp_alloc_base += (align - off);
Dave Liue732e9c2006-11-03 12:11:15 -060066
67 if ((off = size & align_mask) != 0)
68 size += (align - off);
69
Simon Glass8518b172012-12-13 20:48:50 +000070 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) {
71 gd->arch.mp_alloc_base = savebase;
Dave Liue732e9c2006-11-03 12:11:15 -060072 printf("%s: ran out of ram.\n", __FUNCTION__);
73 }
74
Simon Glass8518b172012-12-13 20:48:50 +000075 retloc = gd->arch.mp_alloc_base;
76 gd->arch.mp_alloc_base += size;
Dave Liue732e9c2006-11-03 12:11:15 -060077
78 memset((void *)&qe_immr->muram[retloc], 0, size);
79
80 __asm__ __volatile__("sync");
81
82 return retloc;
83}
Zhao Qiang5ad93952014-09-25 13:52:25 +080084#endif
Dave Liue732e9c2006-11-03 12:11:15 -060085
86void *qe_muram_addr(uint offset)
87{
88 return (void *)&qe_immr->muram[offset];
89}
90
Zhao Qiang3ae22202016-02-05 10:04:16 +080091#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060092static 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 */
Dave Liu11da1752007-06-25 10:41:04 +0800104 sdma_buffer_base = qe_muram_alloc(2048, 4096);
Dave Liue732e9c2006-11-03 12:11:15 -0600105 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
Haiying Wang0eea38e2009-05-20 12:30:35 -0400114/* 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[] = {
Gerlando Falautofe201cb2012-10-10 22:13:08 +0000119/* Evthreads 16-29 are not supported in MPC8309 */
120#if !defined(CONFIG_MPC8309)
Dave Liue732e9c2006-11-03 12:11:15 -0600121 0x04, 0x05, 0x0c, 0x0d,
122 0x14, 0x15, 0x1c, 0x1d,
123 0x24, 0x25, 0x2c, 0x2d,
Gerlando Falautofe201cb2012-10-10 22:13:08 +0000124 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
Dave Liue732e9c2006-11-03 12:11:15 -0600134};
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{
Dave Liue732e9c2006-11-03 12:11:15 -0600176 /* Init the QE IMMR base */
177 qe_immr = (qe_map_t *)qe_base;
178
Timur Tabi275f4bb2011-11-22 09:21:25 -0600179#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
Wolfgang Denke366f152009-04-05 00:27:57 +0200180 /*
181 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
182 */
Zhao Qiang83a90842014-03-21 16:21:44 +0800183 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Haiying Wangec9d36c2009-03-26 17:01:49 -0400184
Wolfgang Denke366f152009-04-05 00:27:57 +0200185 /* enable the microcode in IRAM */
186 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
Haiying Wangec9d36c2009-03-26 17:01:49 -0400187#endif
188
Simon Glass8518b172012-12-13 20:48:50 +0000189 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
190 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
Dave Liue732e9c2006-11-03 12:11:15 -0600191
192 qe_sdma_init();
193 qe_snums_init();
194}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800195#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600196
Zhao Qiang5ad93952014-09-25 13:52:25 +0800197#ifdef CONFIG_U_QE
198void u_qe_init(void)
199{
Zhao Qiang0be9be82016-02-05 10:04:17 +0800200 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiang5ad93952014-09-25 13:52:25 +0800201
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800202 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);
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800224 }
225#endif
Zhao Qiang10640212017-08-14 10:22:43 +0800226 if (!u_qe_upload_firmware(addr))
227 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800228#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
229 free(addr);
230#endif
Zhao Qiang5ad93952014-09-25 13:52:25 +0800231}
232#endif
233
Zhao Qiangcfd76712015-03-25 17:02:59 +0800234#ifdef CONFIG_U_QE
235void u_qe_resume(void)
236{
237 qe_map_t *qe_immrr;
Zhao Qiangcfd76712015-03-25 17:02:59 +0800238
Zhao Qiang0be9be82016-02-05 10:04:17 +0800239 qe_immrr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiangcfd76712015-03-25 17:02:59 +0800240 u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr);
241 out_be32(&qe_immrr->iram.iready, QE_IRAM_READY);
242}
243#endif
244
Dave Liue732e9c2006-11-03 12:11:15 -0600245void qe_reset(void)
246{
247 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
248 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
249}
250
Zhao Qiang3ae22202016-02-05 10:04:16 +0800251#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600252void qe_assign_page(uint snum, uint para_ram_base)
253{
254 u32 cecr;
255
256 out_be32(&qe_immr->cp.cecdr, para_ram_base);
257 out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
258 | QE_CR_FLG | QE_ASSIGN_PAGE);
259
260 /* Wait for the QE_CR_FLG to clear */
261 do {
262 cecr = in_be32(&qe_immr->cp.cecr);
263 } while (cecr & QE_CR_FLG );
264
265 return;
266}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800267#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600268
269/*
270 * brg: 0~15 as BRG1~BRG16
271 rate: baud rate
272 * BRG input clock comes from the BRGCLK (internal clock generated from
273 the QE clock, it is one-half of the QE clock), If need the clock source
274 from CLKn pin, we have te change the function.
275 */
276
Simon Glass34a194f2012-12-13 20:48:44 +0000277#define BRG_CLK (gd->arch.brg_clk)
Dave Liue732e9c2006-11-03 12:11:15 -0600278
Zhao Qiang5ad93952014-09-25 13:52:25 +0800279#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600280int qe_set_brg(uint brg, uint rate)
281{
Dave Liue732e9c2006-11-03 12:11:15 -0600282 volatile uint *bp;
283 u32 divisor;
284 int div16 = 0;
285
286 if (brg >= QE_NUM_OF_BRGS)
287 return -EINVAL;
288 bp = (uint *)&qe_immr->brg.brgc1;
289 bp += brg;
290
291 divisor = (BRG_CLK / rate);
292 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
293 div16 = 1;
294 divisor /= 16;
295 }
296
297 *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
298 __asm__ __volatile__("sync");
299
300 if (div16) {
301 *bp |= QE_BRGC_DIV16;
302 __asm__ __volatile__("sync");
303 }
304
305 return 0;
306}
Zhao Qiang5ad93952014-09-25 13:52:25 +0800307#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600308
309/* Set ethernet MII clock master
310*/
311int qe_set_mii_clk_src(int ucc_num)
312{
313 u32 cmxgcr;
314
315 /* check if the UCC number is in range. */
316 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) {
317 printf("%s: ucc num not in ranges\n", __FUNCTION__);
318 return -EINVAL;
319 }
320
321 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
322 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
323 cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT);
324 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
325
326 return 0;
327}
328
Timur Tabi6d838da2008-01-07 13:31:19 -0600329/* Firmware information stored here for qe_get_firmware_info() */
330static struct qe_firmware_info qe_firmware_info;
331
332/*
333 * Set to 1 if QE firmware has been uploaded, and therefore
334 * qe_firmware_info contains valid data.
335 */
336static int qe_firmware_uploaded;
337
338/*
339 * Upload a QE microcode
340 *
341 * This function is a worker function for qe_upload_firmware(). It does
342 * the actual uploading of the microcode.
343 */
344static void qe_upload_microcode(const void *base,
345 const struct qe_microcode *ucode)
346{
347 const u32 *code = base + be32_to_cpu(ucode->code_offset);
348 unsigned int i;
349
350 if (ucode->major || ucode->minor || ucode->revision)
351 printf("QE: uploading microcode '%s' version %u.%u.%u\n",
Zhao Qiang7879a492015-05-05 15:53:32 +0800352 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor,
353 (u16)ucode->revision);
Timur Tabi6d838da2008-01-07 13:31:19 -0600354 else
Zhao Qiang7879a492015-05-05 15:53:32 +0800355 printf("QE: uploading microcode '%s'\n", (char *)ucode->id);
Timur Tabi6d838da2008-01-07 13:31:19 -0600356
357 /* Use auto-increment */
358 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
359 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
360
361 for (i = 0; i < be32_to_cpu(ucode->count); i++)
362 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
363}
364
365/*
366 * Upload a microcode to the I-RAM at a specific address.
367 *
368 * See docs/README.qe_firmware for information on QE microcode uploading.
369 *
370 * Currently, only version 1 is supported, so the 'version' field must be
371 * set to 1.
372 *
373 * The SOC model and revision are not validated, they are only displayed for
374 * informational purposes.
375 *
376 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
377 * all of the microcode structures, minus the CRC.
378 *
379 * 'length' is the size that the structure says it is, including the CRC.
380 */
381int qe_upload_firmware(const struct qe_firmware *firmware)
382{
383 unsigned int i;
384 unsigned int j;
385 u32 crc;
386 size_t calc_size = sizeof(struct qe_firmware);
387 size_t length;
388 const struct qe_header *hdr;
Zhao Qiangb59534d2014-04-30 16:45:31 +0800389#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700390#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800391 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
392#else
Zhao Qiangb59534d2014-04-30 16:45:31 +0800393 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
394#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800395#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600396 if (!firmware) {
397 printf("Invalid address\n");
398 return -EINVAL;
399 }
400
401 hdr = &firmware->header;
402 length = be32_to_cpu(hdr->length);
403
404 /* Check the magic */
405 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
406 (hdr->magic[2] != 'F')) {
Vijay Raia4792292014-07-23 18:33:16 +0530407 printf("QE microcode not found\n");
Zhao Qiangb59534d2014-04-30 16:45:31 +0800408#ifdef CONFIG_DEEP_SLEEP
409 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
410#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600411 return -EPERM;
412 }
413
414 /* Check the version */
415 if (hdr->version != 1) {
416 printf("Unsupported version\n");
417 return -EPERM;
418 }
419
420 /* Validate some of the fields */
Timur Tabic6c0fd52008-03-03 09:58:52 -0600421 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabi6d838da2008-01-07 13:31:19 -0600422 printf("Invalid data\n");
423 return -EINVAL;
424 }
425
426 /* Validate the length and check if there's a CRC */
427 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
428
429 for (i = 0; i < firmware->count; i++)
430 /*
431 * For situations where the second RISC uses the same microcode
432 * as the first, the 'code_offset' and 'count' fields will be
433 * zero, so it's okay to add those.
434 */
435 calc_size += sizeof(u32) *
436 be32_to_cpu(firmware->microcode[i].count);
437
438 /* Validate the length */
439 if (length != calc_size + sizeof(u32)) {
440 printf("Invalid length\n");
441 return -EPERM;
442 }
443
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100444 /*
445 * Validate the CRC. We would normally call crc32_no_comp(), but that
446 * function isn't available unless you turn on JFFS support.
447 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600448 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
449 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
450 printf("Firmware CRC is invalid\n");
451 return -EIO;
452 }
453
454 /*
455 * If the microcode calls for it, split the I-RAM.
456 */
457 if (!firmware->split) {
458 out_be16(&qe_immr->cp.cercr,
459 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
460 }
461
462 if (firmware->soc.model)
463 printf("Firmware '%s' for %u V%u.%u\n",
464 firmware->id, be16_to_cpu(firmware->soc.model),
465 firmware->soc.major, firmware->soc.minor);
466 else
467 printf("Firmware '%s'\n", firmware->id);
468
469 /*
470 * The QE only supports one microcode per RISC, so clear out all the
471 * saved microcode information and put in the new.
472 */
473 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Zhao Qiangd64f1a42015-05-05 15:53:33 +0800474 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabi6d838da2008-01-07 13:31:19 -0600475 qe_firmware_info.extended_modes = firmware->extended_modes;
476 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
477 sizeof(firmware->vtraps));
478 qe_firmware_uploaded = 1;
479
480 /* Loop through each microcode. */
481 for (i = 0; i < firmware->count; i++) {
482 const struct qe_microcode *ucode = &firmware->microcode[i];
483
484 /* Upload a microcode if it's present */
485 if (ucode->code_offset)
486 qe_upload_microcode(firmware, ucode);
487
488 /* Program the traps for this processor */
489 for (j = 0; j < 16; j++) {
490 u32 trap = be32_to_cpu(ucode->traps[j]);
491
492 if (trap)
493 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
494 }
495
496 /* Enable traps */
497 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
498 }
499
500 return 0;
501}
502
Zhao Qianga985f822014-11-04 13:46:16 +0800503#ifdef CONFIG_U_QE
504/*
505 * Upload a microcode to the I-RAM at a specific address.
506 *
507 * See docs/README.qe_firmware for information on QE microcode uploading.
508 *
509 * Currently, only version 1 is supported, so the 'version' field must be
510 * set to 1.
511 *
512 * The SOC model and revision are not validated, they are only displayed for
513 * informational purposes.
514 *
515 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
516 * all of the microcode structures, minus the CRC.
517 *
518 * 'length' is the size that the structure says it is, including the CRC.
519 */
520int u_qe_upload_firmware(const struct qe_firmware *firmware)
521{
522 unsigned int i;
523 unsigned int j;
524 u32 crc;
525 size_t calc_size = sizeof(struct qe_firmware);
526 size_t length;
527 const struct qe_header *hdr;
528#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700529#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800530 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
531#else
Zhao Qianga985f822014-11-04 13:46:16 +0800532 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
533#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800534#endif
Zhao Qianga985f822014-11-04 13:46:16 +0800535 if (!firmware) {
536 printf("Invalid address\n");
537 return -EINVAL;
538 }
539
540 hdr = &firmware->header;
541 length = be32_to_cpu(hdr->length);
542
543 /* Check the magic */
544 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
545 (hdr->magic[2] != 'F')) {
546 printf("Not a microcode\n");
547#ifdef CONFIG_DEEP_SLEEP
548 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
549#endif
550 return -EPERM;
551 }
552
553 /* Check the version */
554 if (hdr->version != 1) {
555 printf("Unsupported version\n");
556 return -EPERM;
557 }
558
559 /* Validate some of the fields */
560 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
561 printf("Invalid data\n");
562 return -EINVAL;
563 }
564
565 /* Validate the length and check if there's a CRC */
566 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
567
568 for (i = 0; i < firmware->count; i++)
569 /*
570 * For situations where the second RISC uses the same microcode
571 * as the first, the 'code_offset' and 'count' fields will be
572 * zero, so it's okay to add those.
573 */
574 calc_size += sizeof(u32) *
575 be32_to_cpu(firmware->microcode[i].count);
576
577 /* Validate the length */
578 if (length != calc_size + sizeof(u32)) {
579 printf("Invalid length\n");
580 return -EPERM;
581 }
582
583 /*
584 * Validate the CRC. We would normally call crc32_no_comp(), but that
585 * function isn't available unless you turn on JFFS support.
586 */
587 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
588 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
589 printf("Firmware CRC is invalid\n");
590 return -EIO;
591 }
592
593 /*
594 * If the microcode calls for it, split the I-RAM.
595 */
596 if (!firmware->split) {
597 out_be16(&qe_immr->cp.cercr,
598 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
599 }
600
601 if (firmware->soc.model)
602 printf("Firmware '%s' for %u V%u.%u\n",
603 firmware->id, be16_to_cpu(firmware->soc.model),
604 firmware->soc.major, firmware->soc.minor);
605 else
606 printf("Firmware '%s'\n", firmware->id);
607
608 /* Loop through each microcode. */
609 for (i = 0; i < firmware->count; i++) {
610 const struct qe_microcode *ucode = &firmware->microcode[i];
611
612 /* Upload a microcode if it's present */
613 if (ucode->code_offset)
614 qe_upload_microcode(firmware, ucode);
615
616 /* Program the traps for this processor */
617 for (j = 0; j < 16; j++) {
618 u32 trap = be32_to_cpu(ucode->traps[j]);
619
620 if (trap)
621 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
622 }
623
624 /* Enable traps */
625 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
626 }
627
628 return 0;
629}
630#endif
631
Zhao Qiangcfd76712015-03-25 17:02:59 +0800632#ifdef CONFIG_U_QE
633int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
634{
635 unsigned int i;
636 unsigned int j;
637 const struct qe_header *hdr;
638 const u32 *code;
639#ifdef CONFIG_DEEP_SLEEP
640#ifdef CONFIG_PPC
641 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
642#else
643 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
644#endif
645#endif
646
647 if (!firmware)
648 return -EINVAL;
649
650 hdr = &firmware->header;
651
652 /* Check the magic */
653 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
654 (hdr->magic[2] != 'F')) {
655#ifdef CONFIG_DEEP_SLEEP
656 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
657#endif
658 return -EPERM;
659 }
660
661 /*
662 * If the microcode calls for it, split the I-RAM.
663 */
664 if (!firmware->split) {
665 out_be16(&qe_immrr->cp.cercr,
666 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
667 }
668
669 /* Loop through each microcode. */
670 for (i = 0; i < firmware->count; i++) {
671 const struct qe_microcode *ucode = &firmware->microcode[i];
672
673 /* Upload a microcode if it's present */
674 if (!ucode->code_offset)
675 return 0;
676
677 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
678
679 /* Use auto-increment */
680 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
681 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
682
683 for (i = 0; i < be32_to_cpu(ucode->count); i++)
684 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
685
686 /* Program the traps for this processor */
687 for (j = 0; j < 16; j++) {
688 u32 trap = be32_to_cpu(ucode->traps[j]);
689
690 if (trap)
691 out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
692 }
693
694 /* Enable traps */
695 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
696 }
697
698 return 0;
699}
700#endif
701
Timur Tabi6d838da2008-01-07 13:31:19 -0600702struct qe_firmware_info *qe_get_firmware_info(void)
703{
704 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
705}
706
Wolfgang Denk6262d0212010-06-28 22:00:46 +0200707static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Timur Tabi6d838da2008-01-07 13:31:19 -0600708{
709 ulong addr;
710
Wolfgang Denk3b683112010-07-17 01:06:04 +0200711 if (argc < 3)
712 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600713
714 if (strcmp(argv[1], "fw") == 0) {
715 addr = simple_strtoul(argv[2], NULL, 16);
716
717 if (!addr) {
718 printf("Invalid address\n");
719 return -EINVAL;
720 }
721
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100722 /*
723 * If a length was supplied, compare that with the 'length'
724 * field.
725 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600726
727 if (argc > 3) {
728 ulong length = simple_strtoul(argv[3], NULL, 16);
729 struct qe_firmware *firmware = (void *) addr;
730
731 if (length != be32_to_cpu(firmware->header.length)) {
732 printf("Length mismatch\n");
733 return -EINVAL;
734 }
735 }
736
737 return qe_upload_firmware((const struct qe_firmware *) addr);
738 }
739
Wolfgang Denk3b683112010-07-17 01:06:04 +0200740 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600741}
742
743U_BOOT_CMD(
744 qe, 4, 0, qe_cmd,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600745 "QUICC Engine commands",
Timur Tabi6d838da2008-01-07 13:31:19 -0600746 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200747 "the QE,\n"
748 "\twith optional length <length> verification."
749);