blob: 7010bbc2308bbd87873360cb8244e9376045bf99 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dave Liue732e9c2006-11-03 12:11:15 -06002/*
Haiying Wang0eea38e2009-05-20 12:30:35 -04003 * Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
Dave Liue732e9c2006-11-03 12:11:15 -06004 *
5 * Dave Liu <daveliu@freescale.com>
6 * based on source code of Shlomi Gridish
Dave Liue732e9c2006-11-03 12:11:15 -06007 */
8
Masahiro Yamadaadae2ec2016-09-21 11:28:53 +09009#include <common.h>
Zhao Qiang82cd8c62017-05-25 09:47:40 +080010#include <malloc.h>
Timur Tabi6d838da2008-01-07 13:31:19 -060011#include <command.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090012#include <linux/errno.h>
Masahiro Yamadaadae2ec2016-09-21 11:28:53 +090013#include <asm/io.h>
14#include <linux/immap_qe.h>
Qianyu Gongae6a7582016-02-18 13:01:59 +080015#include <fsl_qe.h>
York Sunc4f047c2017-03-27 11:41:03 -070016#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +080017#include <asm/arch/immap_ls102xa.h>
18#endif
Dave Liue732e9c2006-11-03 12:11:15 -060019
Zhao Qiang82cd8c62017-05-25 09:47:40 +080020#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
21#include <mmc.h>
22#endif
23
Zhao Qiangb59534d2014-04-30 16:45:31 +080024#define MPC85xx_DEVDISR_QE_DISABLE 0x1
25
Dave Liue732e9c2006-11-03 12:11:15 -060026qe_map_t *qe_immr = NULL;
Zhao Qiang3ae22202016-02-05 10:04:16 +080027#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060028static qe_snum_t snums[QE_NUM_OF_SNUM];
Zhao Qiang3ae22202016-02-05 10:04:16 +080029#endif
Dave Liue732e9c2006-11-03 12:11:15 -060030
Wolfgang Denkd112a2c2007-09-15 20:48:41 +020031DECLARE_GLOBAL_DATA_PTR;
32
Dave Liue732e9c2006-11-03 12:11:15 -060033void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
34{
Wolfgang Denk545b06a2008-01-10 00:55:14 +010035 u32 cecr;
Dave Liue732e9c2006-11-03 12:11:15 -060036
37 if (cmd == QE_RESET) {
38 out_be32(&qe_immr->cp.cecr,(u32) (cmd | QE_CR_FLG));
39 } else {
40 out_be32(&qe_immr->cp.cecdr, cmd_data);
41 out_be32(&qe_immr->cp.cecr, (sbc | QE_CR_FLG |
42 ((u32) mcn<<QE_CR_PROTOCOL_SHIFT) | cmd));
43 }
44 /* Wait for the QE_CR_FLG to clear */
45 do {
46 cecr = in_be32(&qe_immr->cp.cecr);
47 } while (cecr & QE_CR_FLG);
48
49 return;
50}
51
Zhao Qiang5ad93952014-09-25 13:52:25 +080052#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060053uint qe_muram_alloc(uint size, uint align)
54{
Dave Liue732e9c2006-11-03 12:11:15 -060055 uint retloc;
56 uint align_mask, off;
57 uint savebase;
58
59 align_mask = align - 1;
Simon Glass8518b172012-12-13 20:48:50 +000060 savebase = gd->arch.mp_alloc_base;
Dave Liue732e9c2006-11-03 12:11:15 -060061
Simon Glass8518b172012-12-13 20:48:50 +000062 off = gd->arch.mp_alloc_base & align_mask;
63 if (off != 0)
64 gd->arch.mp_alloc_base += (align - off);
Dave Liue732e9c2006-11-03 12:11:15 -060065
66 if ((off = size & align_mask) != 0)
67 size += (align - off);
68
Simon Glass8518b172012-12-13 20:48:50 +000069 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) {
70 gd->arch.mp_alloc_base = savebase;
Dave Liue732e9c2006-11-03 12:11:15 -060071 printf("%s: ran out of ram.\n", __FUNCTION__);
72 }
73
Simon Glass8518b172012-12-13 20:48:50 +000074 retloc = gd->arch.mp_alloc_base;
75 gd->arch.mp_alloc_base += size;
Dave Liue732e9c2006-11-03 12:11:15 -060076
77 memset((void *)&qe_immr->muram[retloc], 0, size);
78
79 __asm__ __volatile__("sync");
80
81 return retloc;
82}
Zhao Qiang5ad93952014-09-25 13:52:25 +080083#endif
Dave Liue732e9c2006-11-03 12:11:15 -060084
85void *qe_muram_addr(uint offset)
86{
87 return (void *)&qe_immr->muram[offset];
88}
89
Zhao Qiang3ae22202016-02-05 10:04:16 +080090#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060091static void qe_sdma_init(void)
92{
93 volatile sdma_t *p;
94 uint sdma_buffer_base;
95
96 p = (volatile sdma_t *)&qe_immr->sdma;
97
98 /* All of DMA transaction in bus 1 */
99 out_be32(&p->sdaqr, 0);
100 out_be32(&p->sdaqmr, 0);
101
102 /* Allocate 2KB temporary buffer for sdma */
Dave Liu11da1752007-06-25 10:41:04 +0800103 sdma_buffer_base = qe_muram_alloc(2048, 4096);
Dave Liue732e9c2006-11-03 12:11:15 -0600104 out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);
105
106 /* Clear sdma status */
107 out_be32(&p->sdsr, 0x03000000);
108
109 /* Enable global mode on bus 1, and 2KB buffer size */
110 out_be32(&p->sdmr, QE_SDMR_GLB_1_MSK | (0x3 << QE_SDMR_CEN_SHIFT));
111}
112
Haiying Wang0eea38e2009-05-20 12:30:35 -0400113/* This table is a list of the serial numbers of the Threads, taken from the
114 * "SNUM Table" chart in the QE Reference Manual. The order is not important,
115 * we just need to know what the SNUMs are for the threads.
116 */
117static u8 thread_snum[] = {
Gerlando Falautofe201cb2012-10-10 22:13:08 +0000118/* Evthreads 16-29 are not supported in MPC8309 */
119#if !defined(CONFIG_MPC8309)
Dave Liue732e9c2006-11-03 12:11:15 -0600120 0x04, 0x05, 0x0c, 0x0d,
121 0x14, 0x15, 0x1c, 0x1d,
122 0x24, 0x25, 0x2c, 0x2d,
Gerlando Falautofe201cb2012-10-10 22:13:08 +0000123 0x34, 0x35,
124#endif
125 0x88, 0x89, 0x98, 0x99,
126 0xa8, 0xa9, 0xb8, 0xb9,
127 0xc8, 0xc9, 0xd8, 0xd9,
128 0xe8, 0xe9, 0x08, 0x09,
129 0x18, 0x19, 0x28, 0x29,
130 0x38, 0x39, 0x48, 0x49,
131 0x58, 0x59, 0x68, 0x69,
132 0x78, 0x79, 0x80, 0x81
Dave Liue732e9c2006-11-03 12:11:15 -0600133};
134
135static void qe_snums_init(void)
136{
137 int i;
138
139 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
140 snums[i].state = QE_SNUM_STATE_FREE;
141 snums[i].num = thread_snum[i];
142 }
143}
144
145int qe_get_snum(void)
146{
147 int snum = -EBUSY;
148 int i;
149
150 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
151 if (snums[i].state == QE_SNUM_STATE_FREE) {
152 snums[i].state = QE_SNUM_STATE_USED;
153 snum = snums[i].num;
154 break;
155 }
156 }
157
158 return snum;
159}
160
161void qe_put_snum(u8 snum)
162{
163 int i;
164
165 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
166 if (snums[i].num == snum) {
167 snums[i].state = QE_SNUM_STATE_FREE;
168 break;
169 }
170 }
171}
172
173void qe_init(uint qe_base)
174{
Dave Liue732e9c2006-11-03 12:11:15 -0600175 /* Init the QE IMMR base */
176 qe_immr = (qe_map_t *)qe_base;
177
Timur Tabi275f4bb2011-11-22 09:21:25 -0600178#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
Wolfgang Denke366f152009-04-05 00:27:57 +0200179 /*
180 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
181 */
Zhao Qiang83a90842014-03-21 16:21:44 +0800182 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Haiying Wangec9d36c2009-03-26 17:01:49 -0400183
Wolfgang Denke366f152009-04-05 00:27:57 +0200184 /* enable the microcode in IRAM */
185 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
Haiying Wangec9d36c2009-03-26 17:01:49 -0400186#endif
187
Simon Glass8518b172012-12-13 20:48:50 +0000188 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
189 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
Dave Liue732e9c2006-11-03 12:11:15 -0600190
191 qe_sdma_init();
192 qe_snums_init();
193}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800194#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600195
Zhao Qiang5ad93952014-09-25 13:52:25 +0800196#ifdef CONFIG_U_QE
197void u_qe_init(void)
198{
Zhao Qiang0be9be82016-02-05 10:04:17 +0800199 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiang5ad93952014-09-25 13:52:25 +0800200
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800201 void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
202#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
203 int dev = CONFIG_SYS_MMC_ENV_DEV;
204 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
205 u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
206
207 if (mmc_initialize(gd->bd)) {
208 printf("%s: mmc_initialize() failed\n", __func__);
209 return;
210 }
211 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
212 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
213
214 if (!mmc) {
215 free(addr);
216 printf("\nMMC cannot find device for ucode\n");
217 } else {
218 printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
219 dev, blk, cnt);
220 mmc_init(mmc);
Yinbo Zhu45c20bd2018-09-25 14:47:06 +0800221 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800222 addr);
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800223 }
224#endif
Zhao Qiang10640212017-08-14 10:22:43 +0800225 if (!u_qe_upload_firmware(addr))
226 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800227#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
228 free(addr);
229#endif
Zhao Qiang5ad93952014-09-25 13:52:25 +0800230}
231#endif
232
Zhao Qiangcfd76712015-03-25 17:02:59 +0800233#ifdef CONFIG_U_QE
234void u_qe_resume(void)
235{
236 qe_map_t *qe_immrr;
Zhao Qiangcfd76712015-03-25 17:02:59 +0800237
Zhao Qiang0be9be82016-02-05 10:04:17 +0800238 qe_immrr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiangcfd76712015-03-25 17:02:59 +0800239 u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr);
240 out_be32(&qe_immrr->iram.iready, QE_IRAM_READY);
241}
242#endif
243
Dave Liue732e9c2006-11-03 12:11:15 -0600244void qe_reset(void)
245{
246 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
247 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
248}
249
Zhao Qiang3ae22202016-02-05 10:04:16 +0800250#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600251void qe_assign_page(uint snum, uint para_ram_base)
252{
253 u32 cecr;
254
255 out_be32(&qe_immr->cp.cecdr, para_ram_base);
256 out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
257 | QE_CR_FLG | QE_ASSIGN_PAGE);
258
259 /* Wait for the QE_CR_FLG to clear */
260 do {
261 cecr = in_be32(&qe_immr->cp.cecr);
262 } while (cecr & QE_CR_FLG );
263
264 return;
265}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800266#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600267
268/*
269 * brg: 0~15 as BRG1~BRG16
270 rate: baud rate
271 * BRG input clock comes from the BRGCLK (internal clock generated from
272 the QE clock, it is one-half of the QE clock), If need the clock source
273 from CLKn pin, we have te change the function.
274 */
275
Simon Glass34a194f2012-12-13 20:48:44 +0000276#define BRG_CLK (gd->arch.brg_clk)
Dave Liue732e9c2006-11-03 12:11:15 -0600277
Zhao Qiang5ad93952014-09-25 13:52:25 +0800278#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600279int qe_set_brg(uint brg, uint rate)
280{
Dave Liue732e9c2006-11-03 12:11:15 -0600281 volatile uint *bp;
282 u32 divisor;
283 int div16 = 0;
284
285 if (brg >= QE_NUM_OF_BRGS)
286 return -EINVAL;
287 bp = (uint *)&qe_immr->brg.brgc1;
288 bp += brg;
289
290 divisor = (BRG_CLK / rate);
291 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
292 div16 = 1;
293 divisor /= 16;
294 }
295
296 *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
297 __asm__ __volatile__("sync");
298
299 if (div16) {
300 *bp |= QE_BRGC_DIV16;
301 __asm__ __volatile__("sync");
302 }
303
304 return 0;
305}
Zhao Qiang5ad93952014-09-25 13:52:25 +0800306#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600307
308/* Set ethernet MII clock master
309*/
310int qe_set_mii_clk_src(int ucc_num)
311{
312 u32 cmxgcr;
313
314 /* check if the UCC number is in range. */
315 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) {
316 printf("%s: ucc num not in ranges\n", __FUNCTION__);
317 return -EINVAL;
318 }
319
320 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
321 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
322 cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT);
323 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
324
325 return 0;
326}
327
Timur Tabi6d838da2008-01-07 13:31:19 -0600328/* Firmware information stored here for qe_get_firmware_info() */
329static struct qe_firmware_info qe_firmware_info;
330
331/*
332 * Set to 1 if QE firmware has been uploaded, and therefore
333 * qe_firmware_info contains valid data.
334 */
335static int qe_firmware_uploaded;
336
337/*
338 * Upload a QE microcode
339 *
340 * This function is a worker function for qe_upload_firmware(). It does
341 * the actual uploading of the microcode.
342 */
343static void qe_upload_microcode(const void *base,
344 const struct qe_microcode *ucode)
345{
346 const u32 *code = base + be32_to_cpu(ucode->code_offset);
347 unsigned int i;
348
349 if (ucode->major || ucode->minor || ucode->revision)
350 printf("QE: uploading microcode '%s' version %u.%u.%u\n",
Zhao Qiang7879a492015-05-05 15:53:32 +0800351 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor,
352 (u16)ucode->revision);
Timur Tabi6d838da2008-01-07 13:31:19 -0600353 else
Zhao Qiang7879a492015-05-05 15:53:32 +0800354 printf("QE: uploading microcode '%s'\n", (char *)ucode->id);
Timur Tabi6d838da2008-01-07 13:31:19 -0600355
356 /* Use auto-increment */
357 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
358 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
359
360 for (i = 0; i < be32_to_cpu(ucode->count); i++)
361 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
362}
363
364/*
365 * Upload a microcode to the I-RAM at a specific address.
366 *
367 * See docs/README.qe_firmware for information on QE microcode uploading.
368 *
369 * Currently, only version 1 is supported, so the 'version' field must be
370 * set to 1.
371 *
372 * The SOC model and revision are not validated, they are only displayed for
373 * informational purposes.
374 *
375 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
376 * all of the microcode structures, minus the CRC.
377 *
378 * 'length' is the size that the structure says it is, including the CRC.
379 */
380int qe_upload_firmware(const struct qe_firmware *firmware)
381{
382 unsigned int i;
383 unsigned int j;
384 u32 crc;
385 size_t calc_size = sizeof(struct qe_firmware);
386 size_t length;
387 const struct qe_header *hdr;
Zhao Qiangb59534d2014-04-30 16:45:31 +0800388#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700389#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800390 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
391#else
Zhao Qiangb59534d2014-04-30 16:45:31 +0800392 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
393#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800394#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600395 if (!firmware) {
396 printf("Invalid address\n");
397 return -EINVAL;
398 }
399
400 hdr = &firmware->header;
401 length = be32_to_cpu(hdr->length);
402
403 /* Check the magic */
404 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
405 (hdr->magic[2] != 'F')) {
Vijay Raia4792292014-07-23 18:33:16 +0530406 printf("QE microcode not found\n");
Zhao Qiangb59534d2014-04-30 16:45:31 +0800407#ifdef CONFIG_DEEP_SLEEP
408 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
409#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600410 return -EPERM;
411 }
412
413 /* Check the version */
414 if (hdr->version != 1) {
415 printf("Unsupported version\n");
416 return -EPERM;
417 }
418
419 /* Validate some of the fields */
Timur Tabic6c0fd52008-03-03 09:58:52 -0600420 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabi6d838da2008-01-07 13:31:19 -0600421 printf("Invalid data\n");
422 return -EINVAL;
423 }
424
425 /* Validate the length and check if there's a CRC */
426 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
427
428 for (i = 0; i < firmware->count; i++)
429 /*
430 * For situations where the second RISC uses the same microcode
431 * as the first, the 'code_offset' and 'count' fields will be
432 * zero, so it's okay to add those.
433 */
434 calc_size += sizeof(u32) *
435 be32_to_cpu(firmware->microcode[i].count);
436
437 /* Validate the length */
438 if (length != calc_size + sizeof(u32)) {
439 printf("Invalid length\n");
440 return -EPERM;
441 }
442
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100443 /*
444 * Validate the CRC. We would normally call crc32_no_comp(), but that
445 * function isn't available unless you turn on JFFS support.
446 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600447 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
448 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
449 printf("Firmware CRC is invalid\n");
450 return -EIO;
451 }
452
453 /*
454 * If the microcode calls for it, split the I-RAM.
455 */
456 if (!firmware->split) {
457 out_be16(&qe_immr->cp.cercr,
458 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
459 }
460
461 if (firmware->soc.model)
462 printf("Firmware '%s' for %u V%u.%u\n",
463 firmware->id, be16_to_cpu(firmware->soc.model),
464 firmware->soc.major, firmware->soc.minor);
465 else
466 printf("Firmware '%s'\n", firmware->id);
467
468 /*
469 * The QE only supports one microcode per RISC, so clear out all the
470 * saved microcode information and put in the new.
471 */
472 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Zhao Qiangd64f1a42015-05-05 15:53:33 +0800473 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabi6d838da2008-01-07 13:31:19 -0600474 qe_firmware_info.extended_modes = firmware->extended_modes;
475 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
476 sizeof(firmware->vtraps));
477 qe_firmware_uploaded = 1;
478
479 /* Loop through each microcode. */
480 for (i = 0; i < firmware->count; i++) {
481 const struct qe_microcode *ucode = &firmware->microcode[i];
482
483 /* Upload a microcode if it's present */
484 if (ucode->code_offset)
485 qe_upload_microcode(firmware, ucode);
486
487 /* Program the traps for this processor */
488 for (j = 0; j < 16; j++) {
489 u32 trap = be32_to_cpu(ucode->traps[j]);
490
491 if (trap)
492 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
493 }
494
495 /* Enable traps */
496 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
497 }
498
499 return 0;
500}
501
Zhao Qianga985f822014-11-04 13:46:16 +0800502#ifdef CONFIG_U_QE
503/*
504 * Upload a microcode to the I-RAM at a specific address.
505 *
506 * See docs/README.qe_firmware for information on QE microcode uploading.
507 *
508 * Currently, only version 1 is supported, so the 'version' field must be
509 * set to 1.
510 *
511 * The SOC model and revision are not validated, they are only displayed for
512 * informational purposes.
513 *
514 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
515 * all of the microcode structures, minus the CRC.
516 *
517 * 'length' is the size that the structure says it is, including the CRC.
518 */
519int u_qe_upload_firmware(const struct qe_firmware *firmware)
520{
521 unsigned int i;
522 unsigned int j;
523 u32 crc;
524 size_t calc_size = sizeof(struct qe_firmware);
525 size_t length;
526 const struct qe_header *hdr;
527#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700528#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800529 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
530#else
Zhao Qianga985f822014-11-04 13:46:16 +0800531 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
532#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800533#endif
Zhao Qianga985f822014-11-04 13:46:16 +0800534 if (!firmware) {
535 printf("Invalid address\n");
536 return -EINVAL;
537 }
538
539 hdr = &firmware->header;
540 length = be32_to_cpu(hdr->length);
541
542 /* Check the magic */
543 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
544 (hdr->magic[2] != 'F')) {
545 printf("Not a microcode\n");
546#ifdef CONFIG_DEEP_SLEEP
547 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
548#endif
549 return -EPERM;
550 }
551
552 /* Check the version */
553 if (hdr->version != 1) {
554 printf("Unsupported version\n");
555 return -EPERM;
556 }
557
558 /* Validate some of the fields */
559 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
560 printf("Invalid data\n");
561 return -EINVAL;
562 }
563
564 /* Validate the length and check if there's a CRC */
565 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
566
567 for (i = 0; i < firmware->count; i++)
568 /*
569 * For situations where the second RISC uses the same microcode
570 * as the first, the 'code_offset' and 'count' fields will be
571 * zero, so it's okay to add those.
572 */
573 calc_size += sizeof(u32) *
574 be32_to_cpu(firmware->microcode[i].count);
575
576 /* Validate the length */
577 if (length != calc_size + sizeof(u32)) {
578 printf("Invalid length\n");
579 return -EPERM;
580 }
581
582 /*
583 * Validate the CRC. We would normally call crc32_no_comp(), but that
584 * function isn't available unless you turn on JFFS support.
585 */
586 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
587 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
588 printf("Firmware CRC is invalid\n");
589 return -EIO;
590 }
591
592 /*
593 * If the microcode calls for it, split the I-RAM.
594 */
595 if (!firmware->split) {
596 out_be16(&qe_immr->cp.cercr,
597 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
598 }
599
600 if (firmware->soc.model)
601 printf("Firmware '%s' for %u V%u.%u\n",
602 firmware->id, be16_to_cpu(firmware->soc.model),
603 firmware->soc.major, firmware->soc.minor);
604 else
605 printf("Firmware '%s'\n", firmware->id);
606
607 /* Loop through each microcode. */
608 for (i = 0; i < firmware->count; i++) {
609 const struct qe_microcode *ucode = &firmware->microcode[i];
610
611 /* Upload a microcode if it's present */
612 if (ucode->code_offset)
613 qe_upload_microcode(firmware, ucode);
614
615 /* Program the traps for this processor */
616 for (j = 0; j < 16; j++) {
617 u32 trap = be32_to_cpu(ucode->traps[j]);
618
619 if (trap)
620 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
621 }
622
623 /* Enable traps */
624 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
625 }
626
627 return 0;
628}
629#endif
630
Zhao Qiangcfd76712015-03-25 17:02:59 +0800631#ifdef CONFIG_U_QE
632int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
633{
634 unsigned int i;
635 unsigned int j;
636 const struct qe_header *hdr;
637 const u32 *code;
638#ifdef CONFIG_DEEP_SLEEP
639#ifdef CONFIG_PPC
640 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
641#else
642 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
643#endif
644#endif
645
646 if (!firmware)
647 return -EINVAL;
648
649 hdr = &firmware->header;
650
651 /* Check the magic */
652 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
653 (hdr->magic[2] != 'F')) {
654#ifdef CONFIG_DEEP_SLEEP
655 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
656#endif
657 return -EPERM;
658 }
659
660 /*
661 * If the microcode calls for it, split the I-RAM.
662 */
663 if (!firmware->split) {
664 out_be16(&qe_immrr->cp.cercr,
665 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
666 }
667
668 /* Loop through each microcode. */
669 for (i = 0; i < firmware->count; i++) {
670 const struct qe_microcode *ucode = &firmware->microcode[i];
671
672 /* Upload a microcode if it's present */
673 if (!ucode->code_offset)
674 return 0;
675
676 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
677
678 /* Use auto-increment */
679 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
680 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
681
682 for (i = 0; i < be32_to_cpu(ucode->count); i++)
683 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
684
685 /* Program the traps for this processor */
686 for (j = 0; j < 16; j++) {
687 u32 trap = be32_to_cpu(ucode->traps[j]);
688
689 if (trap)
690 out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
691 }
692
693 /* Enable traps */
694 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
695 }
696
697 return 0;
698}
699#endif
700
Timur Tabi6d838da2008-01-07 13:31:19 -0600701struct qe_firmware_info *qe_get_firmware_info(void)
702{
703 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
704}
705
Wolfgang Denk6262d0212010-06-28 22:00:46 +0200706static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Timur Tabi6d838da2008-01-07 13:31:19 -0600707{
708 ulong addr;
709
Wolfgang Denk3b683112010-07-17 01:06:04 +0200710 if (argc < 3)
711 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600712
713 if (strcmp(argv[1], "fw") == 0) {
714 addr = simple_strtoul(argv[2], NULL, 16);
715
716 if (!addr) {
717 printf("Invalid address\n");
718 return -EINVAL;
719 }
720
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100721 /*
722 * If a length was supplied, compare that with the 'length'
723 * field.
724 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600725
726 if (argc > 3) {
727 ulong length = simple_strtoul(argv[3], NULL, 16);
728 struct qe_firmware *firmware = (void *) addr;
729
730 if (length != be32_to_cpu(firmware->header.length)) {
731 printf("Length mismatch\n");
732 return -EINVAL;
733 }
734 }
735
736 return qe_upload_firmware((const struct qe_firmware *) addr);
737 }
738
Wolfgang Denk3b683112010-07-17 01:06:04 +0200739 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600740}
741
742U_BOOT_CMD(
743 qe, 4, 0, qe_cmd,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600744 "QUICC Engine commands",
Timur Tabi6d838da2008-01-07 13:31:19 -0600745 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200746 "the QE,\n"
747 "\twith optional length <length> verification."
748);