blob: 24549ece653cf4a20d64e2daae236323cfc4a032 [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>
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +000016#include <mmc.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070017#include <u-boot/crc.h>
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +000018
York Sunc4f047c2017-03-27 11:41:03 -070019#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +080020#include <asm/arch/immap_ls102xa.h>
21#endif
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +000022#ifdef CONFIG_ARM64
23#include <asm/armv8/mmu.h>
24#include <asm/arch/cpu.h>
Zhao Qiang82cd8c62017-05-25 09:47:40 +080025#endif
26
Zhao Qiangb59534d2014-04-30 16:45:31 +080027#define MPC85xx_DEVDISR_QE_DISABLE 0x1
28
Dave Liue732e9c2006-11-03 12:11:15 -060029qe_map_t *qe_immr = NULL;
Zhao Qiang3ae22202016-02-05 10:04:16 +080030#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060031static qe_snum_t snums[QE_NUM_OF_SNUM];
Zhao Qiang3ae22202016-02-05 10:04:16 +080032#endif
Dave Liue732e9c2006-11-03 12:11:15 -060033
Wolfgang Denkd112a2c2007-09-15 20:48:41 +020034DECLARE_GLOBAL_DATA_PTR;
35
Dave Liue732e9c2006-11-03 12:11:15 -060036void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
37{
Wolfgang Denk545b06a2008-01-10 00:55:14 +010038 u32 cecr;
Dave Liue732e9c2006-11-03 12:11:15 -060039
40 if (cmd == QE_RESET) {
41 out_be32(&qe_immr->cp.cecr,(u32) (cmd | QE_CR_FLG));
42 } else {
43 out_be32(&qe_immr->cp.cecdr, cmd_data);
44 out_be32(&qe_immr->cp.cecr, (sbc | QE_CR_FLG |
45 ((u32) mcn<<QE_CR_PROTOCOL_SHIFT) | cmd));
46 }
47 /* Wait for the QE_CR_FLG to clear */
48 do {
49 cecr = in_be32(&qe_immr->cp.cecr);
50 } while (cecr & QE_CR_FLG);
51
52 return;
53}
54
Zhao Qiang5ad93952014-09-25 13:52:25 +080055#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060056uint qe_muram_alloc(uint size, uint align)
57{
Dave Liue732e9c2006-11-03 12:11:15 -060058 uint retloc;
59 uint align_mask, off;
60 uint savebase;
61
62 align_mask = align - 1;
Simon Glass8518b172012-12-13 20:48:50 +000063 savebase = gd->arch.mp_alloc_base;
Dave Liue732e9c2006-11-03 12:11:15 -060064
Simon Glass8518b172012-12-13 20:48:50 +000065 off = gd->arch.mp_alloc_base & align_mask;
66 if (off != 0)
67 gd->arch.mp_alloc_base += (align - off);
Dave Liue732e9c2006-11-03 12:11:15 -060068
69 if ((off = size & align_mask) != 0)
70 size += (align - off);
71
Simon Glass8518b172012-12-13 20:48:50 +000072 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) {
73 gd->arch.mp_alloc_base = savebase;
Dave Liue732e9c2006-11-03 12:11:15 -060074 printf("%s: ran out of ram.\n", __FUNCTION__);
75 }
76
Simon Glass8518b172012-12-13 20:48:50 +000077 retloc = gd->arch.mp_alloc_base;
78 gd->arch.mp_alloc_base += size;
Dave Liue732e9c2006-11-03 12:11:15 -060079
80 memset((void *)&qe_immr->muram[retloc], 0, size);
81
82 __asm__ __volatile__("sync");
83
84 return retloc;
85}
Zhao Qiang5ad93952014-09-25 13:52:25 +080086#endif
Dave Liue732e9c2006-11-03 12:11:15 -060087
88void *qe_muram_addr(uint offset)
89{
90 return (void *)&qe_immr->muram[offset];
91}
92
Zhao Qiang3ae22202016-02-05 10:04:16 +080093#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060094static void qe_sdma_init(void)
95{
96 volatile sdma_t *p;
97 uint sdma_buffer_base;
98
99 p = (volatile sdma_t *)&qe_immr->sdma;
100
101 /* All of DMA transaction in bus 1 */
102 out_be32(&p->sdaqr, 0);
103 out_be32(&p->sdaqmr, 0);
104
105 /* Allocate 2KB temporary buffer for sdma */
Dave Liu11da1752007-06-25 10:41:04 +0800106 sdma_buffer_base = qe_muram_alloc(2048, 4096);
Dave Liue732e9c2006-11-03 12:11:15 -0600107 out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);
108
109 /* Clear sdma status */
110 out_be32(&p->sdsr, 0x03000000);
111
112 /* Enable global mode on bus 1, and 2KB buffer size */
113 out_be32(&p->sdmr, QE_SDMR_GLB_1_MSK | (0x3 << QE_SDMR_CEN_SHIFT));
114}
115
Haiying Wang0eea38e2009-05-20 12:30:35 -0400116/* This table is a list of the serial numbers of the Threads, taken from the
117 * "SNUM Table" chart in the QE Reference Manual. The order is not important,
118 * we just need to know what the SNUMs are for the threads.
119 */
120static u8 thread_snum[] = {
Gerlando Falautofe201cb2012-10-10 22:13:08 +0000121/* Evthreads 16-29 are not supported in MPC8309 */
Mario Sixb2e701c2019-01-21 09:17:24 +0100122#if !defined(CONFIG_ARCH_MPC8309)
Dave Liue732e9c2006-11-03 12:11:15 -0600123 0x04, 0x05, 0x0c, 0x0d,
124 0x14, 0x15, 0x1c, 0x1d,
125 0x24, 0x25, 0x2c, 0x2d,
Gerlando Falautofe201cb2012-10-10 22:13:08 +0000126 0x34, 0x35,
127#endif
128 0x88, 0x89, 0x98, 0x99,
129 0xa8, 0xa9, 0xb8, 0xb9,
130 0xc8, 0xc9, 0xd8, 0xd9,
131 0xe8, 0xe9, 0x08, 0x09,
132 0x18, 0x19, 0x28, 0x29,
133 0x38, 0x39, 0x48, 0x49,
134 0x58, 0x59, 0x68, 0x69,
135 0x78, 0x79, 0x80, 0x81
Dave Liue732e9c2006-11-03 12:11:15 -0600136};
137
138static void qe_snums_init(void)
139{
140 int i;
141
142 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
143 snums[i].state = QE_SNUM_STATE_FREE;
144 snums[i].num = thread_snum[i];
145 }
146}
147
148int qe_get_snum(void)
149{
150 int snum = -EBUSY;
151 int i;
152
153 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
154 if (snums[i].state == QE_SNUM_STATE_FREE) {
155 snums[i].state = QE_SNUM_STATE_USED;
156 snum = snums[i].num;
157 break;
158 }
159 }
160
161 return snum;
162}
163
164void qe_put_snum(u8 snum)
165{
166 int i;
167
168 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
169 if (snums[i].num == snum) {
170 snums[i].state = QE_SNUM_STATE_FREE;
171 break;
172 }
173 }
174}
175
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000176#ifdef CONFIG_TFABOOT
177void qe_init(uint qe_base)
178{
179 enum boot_src src = get_boot_src();
180
181 /* Init the QE IMMR base */
182 qe_immr = (qe_map_t *)qe_base;
183
184 if (src == BOOT_SOURCE_IFC_NOR) {
185 /*
186 * Upload microcode to IRAM for those SOCs
187 * which do not have ROM in QE.
188 */
189 qe_upload_firmware((const void *)(CONFIG_SYS_QE_FW_ADDR +
190 CONFIG_SYS_FSL_IFC_BASE));
191
192 /* enable the microcode in IRAM */
193 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
194 }
195
196 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
197 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
198
199 qe_sdma_init();
200 qe_snums_init();
201}
202#else
Dave Liue732e9c2006-11-03 12:11:15 -0600203void qe_init(uint qe_base)
204{
Dave Liue732e9c2006-11-03 12:11:15 -0600205 /* Init the QE IMMR base */
206 qe_immr = (qe_map_t *)qe_base;
207
Timur Tabi275f4bb2011-11-22 09:21:25 -0600208#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
Wolfgang Denke366f152009-04-05 00:27:57 +0200209 /*
210 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
211 */
Zhao Qiang83a90842014-03-21 16:21:44 +0800212 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Haiying Wangec9d36c2009-03-26 17:01:49 -0400213
Wolfgang Denke366f152009-04-05 00:27:57 +0200214 /* enable the microcode in IRAM */
215 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
Haiying Wangec9d36c2009-03-26 17:01:49 -0400216#endif
217
Simon Glass8518b172012-12-13 20:48:50 +0000218 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
219 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
Dave Liue732e9c2006-11-03 12:11:15 -0600220
221 qe_sdma_init();
222 qe_snums_init();
223}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800224#endif
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000225#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600226
Zhao Qiang5ad93952014-09-25 13:52:25 +0800227#ifdef CONFIG_U_QE
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000228#ifdef CONFIG_TFABOOT
Zhao Qiang5ad93952014-09-25 13:52:25 +0800229void u_qe_init(void)
230{
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000231 enum boot_src src = get_boot_src();
232
Zhao Qiang0be9be82016-02-05 10:04:17 +0800233 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiang5ad93952014-09-25 13:52:25 +0800234
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800235 void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000236
237 if (src == BOOT_SOURCE_IFC_NOR)
238 addr = (void *)(CONFIG_SYS_QE_FW_ADDR + CONFIG_SYS_FSL_IFC_BASE);
239
240 if (src == BOOT_SOURCE_QSPI_NOR)
241 addr = (void *)(CONFIG_SYS_QE_FW_ADDR + CONFIG_SYS_FSL_QSPI_BASE);
242
243 if (src == BOOT_SOURCE_SD_MMC) {
244 int dev = CONFIG_SYS_MMC_ENV_DEV;
245 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
246 u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
247
248 if (mmc_initialize(gd->bd)) {
249 printf("%s: mmc_initialize() failed\n", __func__);
250 return;
251 }
252 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
253 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
254
255 if (!mmc) {
256 free(addr);
257 printf("\nMMC cannot find device for ucode\n");
258 } else {
259 printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
260 dev, blk, cnt);
261 mmc_init(mmc);
262 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
263 addr);
264 }
265 }
266 if (!u_qe_upload_firmware(addr))
267 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
268 if (src == BOOT_SOURCE_SD_MMC)
269 free(addr);
270}
271#else
272void u_qe_init(void)
273{
274 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
275
276 void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800277#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
278 int dev = CONFIG_SYS_MMC_ENV_DEV;
279 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
280 u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
281
282 if (mmc_initialize(gd->bd)) {
283 printf("%s: mmc_initialize() failed\n", __func__);
284 return;
285 }
286 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
287 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
288
289 if (!mmc) {
290 free(addr);
291 printf("\nMMC cannot find device for ucode\n");
292 } else {
293 printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
294 dev, blk, cnt);
295 mmc_init(mmc);
Yinbo Zhu45c20bd2018-09-25 14:47:06 +0800296 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800297 addr);
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800298 }
299#endif
Zhao Qiang10640212017-08-14 10:22:43 +0800300 if (!u_qe_upload_firmware(addr))
301 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800302#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
303 free(addr);
304#endif
Zhao Qiang5ad93952014-09-25 13:52:25 +0800305}
306#endif
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000307#endif
Zhao Qiang5ad93952014-09-25 13:52:25 +0800308
Zhao Qiangcfd76712015-03-25 17:02:59 +0800309#ifdef CONFIG_U_QE
310void u_qe_resume(void)
311{
312 qe_map_t *qe_immrr;
Zhao Qiangcfd76712015-03-25 17:02:59 +0800313
Zhao Qiang0be9be82016-02-05 10:04:17 +0800314 qe_immrr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiangcfd76712015-03-25 17:02:59 +0800315 u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr);
316 out_be32(&qe_immrr->iram.iready, QE_IRAM_READY);
317}
318#endif
319
Dave Liue732e9c2006-11-03 12:11:15 -0600320void qe_reset(void)
321{
322 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
323 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
324}
325
Zhao Qiang3ae22202016-02-05 10:04:16 +0800326#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600327void qe_assign_page(uint snum, uint para_ram_base)
328{
329 u32 cecr;
330
331 out_be32(&qe_immr->cp.cecdr, para_ram_base);
332 out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
333 | QE_CR_FLG | QE_ASSIGN_PAGE);
334
335 /* Wait for the QE_CR_FLG to clear */
336 do {
337 cecr = in_be32(&qe_immr->cp.cecr);
338 } while (cecr & QE_CR_FLG );
339
340 return;
341}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800342#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600343
344/*
345 * brg: 0~15 as BRG1~BRG16
346 rate: baud rate
347 * BRG input clock comes from the BRGCLK (internal clock generated from
348 the QE clock, it is one-half of the QE clock), If need the clock source
349 from CLKn pin, we have te change the function.
350 */
351
Simon Glass34a194f2012-12-13 20:48:44 +0000352#define BRG_CLK (gd->arch.brg_clk)
Dave Liue732e9c2006-11-03 12:11:15 -0600353
Zhao Qiang5ad93952014-09-25 13:52:25 +0800354#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600355int qe_set_brg(uint brg, uint rate)
356{
Dave Liue732e9c2006-11-03 12:11:15 -0600357 volatile uint *bp;
358 u32 divisor;
359 int div16 = 0;
360
361 if (brg >= QE_NUM_OF_BRGS)
362 return -EINVAL;
363 bp = (uint *)&qe_immr->brg.brgc1;
364 bp += brg;
365
366 divisor = (BRG_CLK / rate);
367 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
368 div16 = 1;
369 divisor /= 16;
370 }
371
372 *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
373 __asm__ __volatile__("sync");
374
375 if (div16) {
376 *bp |= QE_BRGC_DIV16;
377 __asm__ __volatile__("sync");
378 }
379
380 return 0;
381}
Zhao Qiang5ad93952014-09-25 13:52:25 +0800382#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600383
384/* Set ethernet MII clock master
385*/
386int qe_set_mii_clk_src(int ucc_num)
387{
388 u32 cmxgcr;
389
390 /* check if the UCC number is in range. */
391 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) {
392 printf("%s: ucc num not in ranges\n", __FUNCTION__);
393 return -EINVAL;
394 }
395
396 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
397 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
398 cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT);
399 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
400
401 return 0;
402}
403
Timur Tabi6d838da2008-01-07 13:31:19 -0600404/* Firmware information stored here for qe_get_firmware_info() */
405static struct qe_firmware_info qe_firmware_info;
406
407/*
408 * Set to 1 if QE firmware has been uploaded, and therefore
409 * qe_firmware_info contains valid data.
410 */
411static int qe_firmware_uploaded;
412
413/*
414 * Upload a QE microcode
415 *
416 * This function is a worker function for qe_upload_firmware(). It does
417 * the actual uploading of the microcode.
418 */
419static void qe_upload_microcode(const void *base,
420 const struct qe_microcode *ucode)
421{
422 const u32 *code = base + be32_to_cpu(ucode->code_offset);
423 unsigned int i;
424
425 if (ucode->major || ucode->minor || ucode->revision)
426 printf("QE: uploading microcode '%s' version %u.%u.%u\n",
Zhao Qiang7879a492015-05-05 15:53:32 +0800427 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor,
428 (u16)ucode->revision);
Timur Tabi6d838da2008-01-07 13:31:19 -0600429 else
Zhao Qiang7879a492015-05-05 15:53:32 +0800430 printf("QE: uploading microcode '%s'\n", (char *)ucode->id);
Timur Tabi6d838da2008-01-07 13:31:19 -0600431
432 /* Use auto-increment */
433 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
434 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
435
436 for (i = 0; i < be32_to_cpu(ucode->count); i++)
437 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
438}
439
440/*
441 * Upload a microcode to the I-RAM at a specific address.
442 *
443 * See docs/README.qe_firmware for information on QE microcode uploading.
444 *
445 * Currently, only version 1 is supported, so the 'version' field must be
446 * set to 1.
447 *
448 * The SOC model and revision are not validated, they are only displayed for
449 * informational purposes.
450 *
451 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
452 * all of the microcode structures, minus the CRC.
453 *
454 * 'length' is the size that the structure says it is, including the CRC.
455 */
456int qe_upload_firmware(const struct qe_firmware *firmware)
457{
458 unsigned int i;
459 unsigned int j;
460 u32 crc;
461 size_t calc_size = sizeof(struct qe_firmware);
462 size_t length;
463 const struct qe_header *hdr;
Zhao Qiangb59534d2014-04-30 16:45:31 +0800464#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700465#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800466 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
467#else
Zhao Qiangb59534d2014-04-30 16:45:31 +0800468 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
469#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800470#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600471 if (!firmware) {
472 printf("Invalid address\n");
473 return -EINVAL;
474 }
475
476 hdr = &firmware->header;
477 length = be32_to_cpu(hdr->length);
478
479 /* Check the magic */
480 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
481 (hdr->magic[2] != 'F')) {
Vijay Raia4792292014-07-23 18:33:16 +0530482 printf("QE microcode not found\n");
Zhao Qiangb59534d2014-04-30 16:45:31 +0800483#ifdef CONFIG_DEEP_SLEEP
484 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
485#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600486 return -EPERM;
487 }
488
489 /* Check the version */
490 if (hdr->version != 1) {
491 printf("Unsupported version\n");
492 return -EPERM;
493 }
494
495 /* Validate some of the fields */
Timur Tabic6c0fd52008-03-03 09:58:52 -0600496 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabi6d838da2008-01-07 13:31:19 -0600497 printf("Invalid data\n");
498 return -EINVAL;
499 }
500
501 /* Validate the length and check if there's a CRC */
502 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
503
504 for (i = 0; i < firmware->count; i++)
505 /*
506 * For situations where the second RISC uses the same microcode
507 * as the first, the 'code_offset' and 'count' fields will be
508 * zero, so it's okay to add those.
509 */
510 calc_size += sizeof(u32) *
511 be32_to_cpu(firmware->microcode[i].count);
512
513 /* Validate the length */
514 if (length != calc_size + sizeof(u32)) {
515 printf("Invalid length\n");
516 return -EPERM;
517 }
518
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100519 /*
520 * Validate the CRC. We would normally call crc32_no_comp(), but that
521 * function isn't available unless you turn on JFFS support.
522 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600523 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
524 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
525 printf("Firmware CRC is invalid\n");
526 return -EIO;
527 }
528
529 /*
530 * If the microcode calls for it, split the I-RAM.
531 */
532 if (!firmware->split) {
533 out_be16(&qe_immr->cp.cercr,
534 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
535 }
536
537 if (firmware->soc.model)
538 printf("Firmware '%s' for %u V%u.%u\n",
539 firmware->id, be16_to_cpu(firmware->soc.model),
540 firmware->soc.major, firmware->soc.minor);
541 else
542 printf("Firmware '%s'\n", firmware->id);
543
544 /*
545 * The QE only supports one microcode per RISC, so clear out all the
546 * saved microcode information and put in the new.
547 */
548 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Zhao Qiangd64f1a42015-05-05 15:53:33 +0800549 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabi6d838da2008-01-07 13:31:19 -0600550 qe_firmware_info.extended_modes = firmware->extended_modes;
551 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
552 sizeof(firmware->vtraps));
553 qe_firmware_uploaded = 1;
554
555 /* Loop through each microcode. */
556 for (i = 0; i < firmware->count; i++) {
557 const struct qe_microcode *ucode = &firmware->microcode[i];
558
559 /* Upload a microcode if it's present */
560 if (ucode->code_offset)
561 qe_upload_microcode(firmware, ucode);
562
563 /* Program the traps for this processor */
564 for (j = 0; j < 16; j++) {
565 u32 trap = be32_to_cpu(ucode->traps[j]);
566
567 if (trap)
568 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
569 }
570
571 /* Enable traps */
572 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
573 }
574
575 return 0;
576}
577
Zhao Qianga985f822014-11-04 13:46:16 +0800578#ifdef CONFIG_U_QE
579/*
580 * Upload a microcode to the I-RAM at a specific address.
581 *
582 * See docs/README.qe_firmware for information on QE microcode uploading.
583 *
584 * Currently, only version 1 is supported, so the 'version' field must be
585 * set to 1.
586 *
587 * The SOC model and revision are not validated, they are only displayed for
588 * informational purposes.
589 *
590 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
591 * all of the microcode structures, minus the CRC.
592 *
593 * 'length' is the size that the structure says it is, including the CRC.
594 */
595int u_qe_upload_firmware(const struct qe_firmware *firmware)
596{
597 unsigned int i;
598 unsigned int j;
599 u32 crc;
600 size_t calc_size = sizeof(struct qe_firmware);
601 size_t length;
602 const struct qe_header *hdr;
603#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700604#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800605 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
606#else
Zhao Qianga985f822014-11-04 13:46:16 +0800607 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
608#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800609#endif
Zhao Qianga985f822014-11-04 13:46:16 +0800610 if (!firmware) {
611 printf("Invalid address\n");
612 return -EINVAL;
613 }
614
615 hdr = &firmware->header;
616 length = be32_to_cpu(hdr->length);
617
618 /* Check the magic */
619 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
620 (hdr->magic[2] != 'F')) {
621 printf("Not a microcode\n");
622#ifdef CONFIG_DEEP_SLEEP
623 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
624#endif
625 return -EPERM;
626 }
627
628 /* Check the version */
629 if (hdr->version != 1) {
630 printf("Unsupported version\n");
631 return -EPERM;
632 }
633
634 /* Validate some of the fields */
635 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
636 printf("Invalid data\n");
637 return -EINVAL;
638 }
639
640 /* Validate the length and check if there's a CRC */
641 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
642
643 for (i = 0; i < firmware->count; i++)
644 /*
645 * For situations where the second RISC uses the same microcode
646 * as the first, the 'code_offset' and 'count' fields will be
647 * zero, so it's okay to add those.
648 */
649 calc_size += sizeof(u32) *
650 be32_to_cpu(firmware->microcode[i].count);
651
652 /* Validate the length */
653 if (length != calc_size + sizeof(u32)) {
654 printf("Invalid length\n");
655 return -EPERM;
656 }
657
658 /*
659 * Validate the CRC. We would normally call crc32_no_comp(), but that
660 * function isn't available unless you turn on JFFS support.
661 */
662 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
663 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
664 printf("Firmware CRC is invalid\n");
665 return -EIO;
666 }
667
668 /*
669 * If the microcode calls for it, split the I-RAM.
670 */
671 if (!firmware->split) {
672 out_be16(&qe_immr->cp.cercr,
673 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
674 }
675
676 if (firmware->soc.model)
677 printf("Firmware '%s' for %u V%u.%u\n",
678 firmware->id, be16_to_cpu(firmware->soc.model),
679 firmware->soc.major, firmware->soc.minor);
680 else
681 printf("Firmware '%s'\n", firmware->id);
682
683 /* Loop through each microcode. */
684 for (i = 0; i < firmware->count; i++) {
685 const struct qe_microcode *ucode = &firmware->microcode[i];
686
687 /* Upload a microcode if it's present */
688 if (ucode->code_offset)
689 qe_upload_microcode(firmware, ucode);
690
691 /* Program the traps for this processor */
692 for (j = 0; j < 16; j++) {
693 u32 trap = be32_to_cpu(ucode->traps[j]);
694
695 if (trap)
696 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
697 }
698
699 /* Enable traps */
700 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
701 }
702
703 return 0;
704}
705#endif
706
Zhao Qiangcfd76712015-03-25 17:02:59 +0800707#ifdef CONFIG_U_QE
708int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
709{
710 unsigned int i;
711 unsigned int j;
712 const struct qe_header *hdr;
713 const u32 *code;
714#ifdef CONFIG_DEEP_SLEEP
715#ifdef CONFIG_PPC
716 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
717#else
718 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
719#endif
720#endif
721
722 if (!firmware)
723 return -EINVAL;
724
725 hdr = &firmware->header;
726
727 /* Check the magic */
728 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
729 (hdr->magic[2] != 'F')) {
730#ifdef CONFIG_DEEP_SLEEP
731 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
732#endif
733 return -EPERM;
734 }
735
736 /*
737 * If the microcode calls for it, split the I-RAM.
738 */
739 if (!firmware->split) {
740 out_be16(&qe_immrr->cp.cercr,
741 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
742 }
743
744 /* Loop through each microcode. */
745 for (i = 0; i < firmware->count; i++) {
746 const struct qe_microcode *ucode = &firmware->microcode[i];
747
748 /* Upload a microcode if it's present */
749 if (!ucode->code_offset)
750 return 0;
751
752 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
753
754 /* Use auto-increment */
755 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
756 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
757
758 for (i = 0; i < be32_to_cpu(ucode->count); i++)
759 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
760
761 /* Program the traps for this processor */
762 for (j = 0; j < 16; j++) {
763 u32 trap = be32_to_cpu(ucode->traps[j]);
764
765 if (trap)
766 out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
767 }
768
769 /* Enable traps */
770 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
771 }
772
773 return 0;
774}
775#endif
776
Timur Tabi6d838da2008-01-07 13:31:19 -0600777struct qe_firmware_info *qe_get_firmware_info(void)
778{
779 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
780}
781
Wolfgang Denk6262d0212010-06-28 22:00:46 +0200782static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Timur Tabi6d838da2008-01-07 13:31:19 -0600783{
784 ulong addr;
785
Wolfgang Denk3b683112010-07-17 01:06:04 +0200786 if (argc < 3)
787 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600788
789 if (strcmp(argv[1], "fw") == 0) {
790 addr = simple_strtoul(argv[2], NULL, 16);
791
792 if (!addr) {
793 printf("Invalid address\n");
794 return -EINVAL;
795 }
796
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100797 /*
798 * If a length was supplied, compare that with the 'length'
799 * field.
800 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600801
802 if (argc > 3) {
803 ulong length = simple_strtoul(argv[3], NULL, 16);
804 struct qe_firmware *firmware = (void *) addr;
805
806 if (length != be32_to_cpu(firmware->header.length)) {
807 printf("Length mismatch\n");
808 return -EINVAL;
809 }
810 }
811
812 return qe_upload_firmware((const struct qe_firmware *) addr);
813 }
814
Wolfgang Denk3b683112010-07-17 01:06:04 +0200815 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600816}
817
818U_BOOT_CMD(
819 qe, 4, 0, qe_cmd,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600820 "QUICC Engine commands",
Timur Tabi6d838da2008-01-07 13:31:19 -0600821 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200822 "the QE,\n"
823 "\twith optional length <length> verification."
824);