blob: 61ca4760c85203606c067efed17fcf537457874b [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 *
Heinrich Schuchardtb0289282020-04-19 09:19:04 +0200443 * See Documentation/powerpc/qe_firmware.rst in the Linux kernel tree for
444 * information on QE microcode uploading.
Timur Tabi6d838da2008-01-07 13:31:19 -0600445 *
446 * Currently, only version 1 is supported, so the 'version' field must be
447 * set to 1.
448 *
449 * The SOC model and revision are not validated, they are only displayed for
450 * informational purposes.
451 *
452 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
453 * all of the microcode structures, minus the CRC.
454 *
455 * 'length' is the size that the structure says it is, including the CRC.
456 */
457int qe_upload_firmware(const struct qe_firmware *firmware)
458{
459 unsigned int i;
460 unsigned int j;
461 u32 crc;
462 size_t calc_size = sizeof(struct qe_firmware);
463 size_t length;
464 const struct qe_header *hdr;
Zhao Qiangb59534d2014-04-30 16:45:31 +0800465#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700466#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800467 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
468#else
Zhao Qiangb59534d2014-04-30 16:45:31 +0800469 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
470#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800471#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600472 if (!firmware) {
473 printf("Invalid address\n");
474 return -EINVAL;
475 }
476
477 hdr = &firmware->header;
478 length = be32_to_cpu(hdr->length);
479
480 /* Check the magic */
481 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
482 (hdr->magic[2] != 'F')) {
Vijay Raia4792292014-07-23 18:33:16 +0530483 printf("QE microcode not found\n");
Zhao Qiangb59534d2014-04-30 16:45:31 +0800484#ifdef CONFIG_DEEP_SLEEP
485 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
486#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600487 return -EPERM;
488 }
489
490 /* Check the version */
491 if (hdr->version != 1) {
492 printf("Unsupported version\n");
493 return -EPERM;
494 }
495
496 /* Validate some of the fields */
Timur Tabic6c0fd52008-03-03 09:58:52 -0600497 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabi6d838da2008-01-07 13:31:19 -0600498 printf("Invalid data\n");
499 return -EINVAL;
500 }
501
502 /* Validate the length and check if there's a CRC */
503 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
504
505 for (i = 0; i < firmware->count; i++)
506 /*
507 * For situations where the second RISC uses the same microcode
508 * as the first, the 'code_offset' and 'count' fields will be
509 * zero, so it's okay to add those.
510 */
511 calc_size += sizeof(u32) *
512 be32_to_cpu(firmware->microcode[i].count);
513
514 /* Validate the length */
515 if (length != calc_size + sizeof(u32)) {
516 printf("Invalid length\n");
517 return -EPERM;
518 }
519
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100520 /*
521 * Validate the CRC. We would normally call crc32_no_comp(), but that
522 * function isn't available unless you turn on JFFS support.
523 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600524 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
525 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
526 printf("Firmware CRC is invalid\n");
527 return -EIO;
528 }
529
530 /*
531 * If the microcode calls for it, split the I-RAM.
532 */
533 if (!firmware->split) {
534 out_be16(&qe_immr->cp.cercr,
535 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
536 }
537
538 if (firmware->soc.model)
539 printf("Firmware '%s' for %u V%u.%u\n",
540 firmware->id, be16_to_cpu(firmware->soc.model),
541 firmware->soc.major, firmware->soc.minor);
542 else
543 printf("Firmware '%s'\n", firmware->id);
544
545 /*
546 * The QE only supports one microcode per RISC, so clear out all the
547 * saved microcode information and put in the new.
548 */
549 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Zhao Qiangd64f1a42015-05-05 15:53:33 +0800550 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabi6d838da2008-01-07 13:31:19 -0600551 qe_firmware_info.extended_modes = firmware->extended_modes;
552 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
553 sizeof(firmware->vtraps));
554 qe_firmware_uploaded = 1;
555
556 /* Loop through each microcode. */
557 for (i = 0; i < firmware->count; i++) {
558 const struct qe_microcode *ucode = &firmware->microcode[i];
559
560 /* Upload a microcode if it's present */
561 if (ucode->code_offset)
562 qe_upload_microcode(firmware, ucode);
563
564 /* Program the traps for this processor */
565 for (j = 0; j < 16; j++) {
566 u32 trap = be32_to_cpu(ucode->traps[j]);
567
568 if (trap)
569 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
570 }
571
572 /* Enable traps */
573 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
574 }
575
576 return 0;
577}
578
Zhao Qianga985f822014-11-04 13:46:16 +0800579#ifdef CONFIG_U_QE
580/*
581 * Upload a microcode to the I-RAM at a specific address.
582 *
Heinrich Schuchardtb0289282020-04-19 09:19:04 +0200583 * See Documentation/powerpc/qe_firmware.rst in the Linux kernel tree for
584 * information on QE microcode uploading.
Zhao Qianga985f822014-11-04 13:46:16 +0800585 *
586 * Currently, only version 1 is supported, so the 'version' field must be
587 * set to 1.
588 *
589 * The SOC model and revision are not validated, they are only displayed for
590 * informational purposes.
591 *
592 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
593 * all of the microcode structures, minus the CRC.
594 *
595 * 'length' is the size that the structure says it is, including the CRC.
596 */
597int u_qe_upload_firmware(const struct qe_firmware *firmware)
598{
599 unsigned int i;
600 unsigned int j;
601 u32 crc;
602 size_t calc_size = sizeof(struct qe_firmware);
603 size_t length;
604 const struct qe_header *hdr;
605#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700606#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800607 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
608#else
Zhao Qianga985f822014-11-04 13:46:16 +0800609 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
610#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800611#endif
Zhao Qianga985f822014-11-04 13:46:16 +0800612 if (!firmware) {
613 printf("Invalid address\n");
614 return -EINVAL;
615 }
616
617 hdr = &firmware->header;
618 length = be32_to_cpu(hdr->length);
619
620 /* Check the magic */
621 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
622 (hdr->magic[2] != 'F')) {
623 printf("Not a microcode\n");
624#ifdef CONFIG_DEEP_SLEEP
625 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
626#endif
627 return -EPERM;
628 }
629
630 /* Check the version */
631 if (hdr->version != 1) {
632 printf("Unsupported version\n");
633 return -EPERM;
634 }
635
636 /* Validate some of the fields */
637 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
638 printf("Invalid data\n");
639 return -EINVAL;
640 }
641
642 /* Validate the length and check if there's a CRC */
643 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
644
645 for (i = 0; i < firmware->count; i++)
646 /*
647 * For situations where the second RISC uses the same microcode
648 * as the first, the 'code_offset' and 'count' fields will be
649 * zero, so it's okay to add those.
650 */
651 calc_size += sizeof(u32) *
652 be32_to_cpu(firmware->microcode[i].count);
653
654 /* Validate the length */
655 if (length != calc_size + sizeof(u32)) {
656 printf("Invalid length\n");
657 return -EPERM;
658 }
659
660 /*
661 * Validate the CRC. We would normally call crc32_no_comp(), but that
662 * function isn't available unless you turn on JFFS support.
663 */
664 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
665 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
666 printf("Firmware CRC is invalid\n");
667 return -EIO;
668 }
669
670 /*
671 * If the microcode calls for it, split the I-RAM.
672 */
673 if (!firmware->split) {
674 out_be16(&qe_immr->cp.cercr,
675 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
676 }
677
678 if (firmware->soc.model)
679 printf("Firmware '%s' for %u V%u.%u\n",
680 firmware->id, be16_to_cpu(firmware->soc.model),
681 firmware->soc.major, firmware->soc.minor);
682 else
683 printf("Firmware '%s'\n", firmware->id);
684
685 /* Loop through each microcode. */
686 for (i = 0; i < firmware->count; i++) {
687 const struct qe_microcode *ucode = &firmware->microcode[i];
688
689 /* Upload a microcode if it's present */
690 if (ucode->code_offset)
691 qe_upload_microcode(firmware, ucode);
692
693 /* Program the traps for this processor */
694 for (j = 0; j < 16; j++) {
695 u32 trap = be32_to_cpu(ucode->traps[j]);
696
697 if (trap)
698 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
699 }
700
701 /* Enable traps */
702 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
703 }
704
705 return 0;
706}
707#endif
708
Zhao Qiangcfd76712015-03-25 17:02:59 +0800709#ifdef CONFIG_U_QE
710int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
711{
712 unsigned int i;
713 unsigned int j;
714 const struct qe_header *hdr;
715 const u32 *code;
716#ifdef CONFIG_DEEP_SLEEP
717#ifdef CONFIG_PPC
718 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
719#else
720 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
721#endif
722#endif
723
724 if (!firmware)
725 return -EINVAL;
726
727 hdr = &firmware->header;
728
729 /* Check the magic */
730 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
731 (hdr->magic[2] != 'F')) {
732#ifdef CONFIG_DEEP_SLEEP
733 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
734#endif
735 return -EPERM;
736 }
737
738 /*
739 * If the microcode calls for it, split the I-RAM.
740 */
741 if (!firmware->split) {
742 out_be16(&qe_immrr->cp.cercr,
743 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
744 }
745
746 /* Loop through each microcode. */
747 for (i = 0; i < firmware->count; i++) {
748 const struct qe_microcode *ucode = &firmware->microcode[i];
749
750 /* Upload a microcode if it's present */
751 if (!ucode->code_offset)
752 return 0;
753
754 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
755
756 /* Use auto-increment */
757 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
758 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
759
760 for (i = 0; i < be32_to_cpu(ucode->count); i++)
761 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
762
763 /* Program the traps for this processor */
764 for (j = 0; j < 16; j++) {
765 u32 trap = be32_to_cpu(ucode->traps[j]);
766
767 if (trap)
768 out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
769 }
770
771 /* Enable traps */
772 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
773 }
774
775 return 0;
776}
777#endif
778
Timur Tabi6d838da2008-01-07 13:31:19 -0600779struct qe_firmware_info *qe_get_firmware_info(void)
780{
781 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
782}
783
Simon Glassed38aef2020-05-10 11:40:03 -0600784static int qe_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Timur Tabi6d838da2008-01-07 13:31:19 -0600785{
786 ulong addr;
787
Wolfgang Denk3b683112010-07-17 01:06:04 +0200788 if (argc < 3)
789 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600790
791 if (strcmp(argv[1], "fw") == 0) {
792 addr = simple_strtoul(argv[2], NULL, 16);
793
794 if (!addr) {
795 printf("Invalid address\n");
796 return -EINVAL;
797 }
798
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100799 /*
800 * If a length was supplied, compare that with the 'length'
801 * field.
802 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600803
804 if (argc > 3) {
805 ulong length = simple_strtoul(argv[3], NULL, 16);
806 struct qe_firmware *firmware = (void *) addr;
807
808 if (length != be32_to_cpu(firmware->header.length)) {
809 printf("Length mismatch\n");
810 return -EINVAL;
811 }
812 }
813
814 return qe_upload_firmware((const struct qe_firmware *) addr);
815 }
816
Wolfgang Denk3b683112010-07-17 01:06:04 +0200817 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600818}
819
820U_BOOT_CMD(
821 qe, 4, 0, qe_cmd,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600822 "QUICC Engine commands",
Timur Tabi6d838da2008-01-07 13:31:19 -0600823 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200824 "the QE,\n"
825 "\twith optional length <length> verification."
826);