blob: 61ca4760c85203606c067efed17fcf537457874b [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dave Liu7737d5c2006-11-03 12:11:15 -06002/*
Haiying Wang4e7b25e2009-05-20 12:30:35 -04003 * Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
Dave Liu7737d5c2006-11-03 12:11:15 -06004 *
5 * Dave Liu <daveliu@freescale.com>
6 * based on source code of Shlomi Gridish
Dave Liu7737d5c2006-11-03 12:11:15 -06007 */
8
Masahiro Yamadab5bf5cb2016-09-21 11:28:53 +09009#include <common.h>
Zhao Qiang5aa03dd2017-05-25 09:47:40 +080010#include <malloc.h>
Timur Tabib8ec2382008-01-07 13:31:19 -060011#include <command.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +090012#include <linux/errno.h>
Masahiro Yamadab5bf5cb2016-09-21 11:28:53 +090013#include <asm/io.h>
14#include <linux/immap_qe.h>
Qianyu Gong2459afb2016-02-18 13:01:59 +080015#include <fsl_qe.h>
Rajesh Bhagatc5e66372018-11-05 18:02:28 +000016#include <mmc.h>
Simon Glass3db71102019-11-14 12:57:16 -070017#include <u-boot/crc.h>
Rajesh Bhagatc5e66372018-11-05 18:02:28 +000018
York Sun73fb5832017-03-27 11:41:03 -070019#ifdef CONFIG_ARCH_LS1021A
Zhao Qiang9c7c86f2014-12-15 15:50:49 +080020#include <asm/arch/immap_ls102xa.h>
21#endif
Rajesh Bhagatc5e66372018-11-05 18:02:28 +000022#ifdef CONFIG_ARM64
23#include <asm/armv8/mmu.h>
24#include <asm/arch/cpu.h>
Zhao Qiang5aa03dd2017-05-25 09:47:40 +080025#endif
26
Zhao Qiangca721fb2014-04-30 16:45:31 +080027#define MPC85xx_DEVDISR_QE_DISABLE 0x1
28
Dave Liu7737d5c2006-11-03 12:11:15 -060029qe_map_t *qe_immr = NULL;
Zhao Qiang3bf46e62016-02-05 10:04:16 +080030#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -060031static qe_snum_t snums[QE_NUM_OF_SNUM];
Zhao Qiang3bf46e62016-02-05 10:04:16 +080032#endif
Dave Liu7737d5c2006-11-03 12:11:15 -060033
Wolfgang Denk1218abf2007-09-15 20:48:41 +020034DECLARE_GLOBAL_DATA_PTR;
35
Dave Liu7737d5c2006-11-03 12:11:15 -060036void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
37{
Wolfgang Denkd3a65322008-01-10 00:55:14 +010038 u32 cecr;
Dave Liu7737d5c2006-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 Qiang93d33202014-09-25 13:52:25 +080055#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -060056uint qe_muram_alloc(uint size, uint align)
57{
Dave Liu7737d5c2006-11-03 12:11:15 -060058 uint retloc;
59 uint align_mask, off;
60 uint savebase;
61
62 align_mask = align - 1;
Simon Glass45bae2e2012-12-13 20:48:50 +000063 savebase = gd->arch.mp_alloc_base;
Dave Liu7737d5c2006-11-03 12:11:15 -060064
Simon Glass45bae2e2012-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 Liu7737d5c2006-11-03 12:11:15 -060068
69 if ((off = size & align_mask) != 0)
70 size += (align - off);
71
Simon Glass45bae2e2012-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 Liu7737d5c2006-11-03 12:11:15 -060074 printf("%s: ran out of ram.\n", __FUNCTION__);
75 }
76
Simon Glass45bae2e2012-12-13 20:48:50 +000077 retloc = gd->arch.mp_alloc_base;
78 gd->arch.mp_alloc_base += size;
Dave Liu7737d5c2006-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 Qiang93d33202014-09-25 13:52:25 +080086#endif
Dave Liu7737d5c2006-11-03 12:11:15 -060087
88void *qe_muram_addr(uint offset)
89{
90 return (void *)&qe_immr->muram[offset];
91}
92
Zhao Qiang3bf46e62016-02-05 10:04:16 +080093#ifdef CONFIG_QE
Dave Liu7737d5c2006-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 Liuff9658d2007-06-25 10:41:04 +0800106 sdma_buffer_base = qe_muram_alloc(2048, 4096);
Dave Liu7737d5c2006-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 Wang4e7b25e2009-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 Falautoa88731a2012-10-10 22:13:08 +0000121/* Evthreads 16-29 are not supported in MPC8309 */
Mario Six4bc97a32019-01-21 09:17:24 +0100122#if !defined(CONFIG_ARCH_MPC8309)
Dave Liu7737d5c2006-11-03 12:11:15 -0600123 0x04, 0x05, 0x0c, 0x0d,
124 0x14, 0x15, 0x1c, 0x1d,
125 0x24, 0x25, 0x2c, 0x2d,
Gerlando Falautoa88731a2012-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 Liu7737d5c2006-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 Bhagatc5e66372018-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 Liu7737d5c2006-11-03 12:11:15 -0600203void qe_init(uint qe_base)
204{
Dave Liu7737d5c2006-11-03 12:11:15 -0600205 /* Init the QE IMMR base */
206 qe_immr = (qe_map_t *)qe_base;
207
Timur Tabif2717b42011-11-22 09:21:25 -0600208#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
Wolfgang Denkc0a14ae2009-04-05 00:27:57 +0200209 /*
210 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
211 */
Zhao Qiangdcf1d772014-03-21 16:21:44 +0800212 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Haiying Wang2d4de6a2009-03-26 17:01:49 -0400213
Wolfgang Denkc0a14ae2009-04-05 00:27:57 +0200214 /* enable the microcode in IRAM */
215 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
Haiying Wang2d4de6a2009-03-26 17:01:49 -0400216#endif
217
Simon Glass45bae2e2012-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 Liu7737d5c2006-11-03 12:11:15 -0600220
221 qe_sdma_init();
222 qe_snums_init();
223}
Zhao Qiang3bf46e62016-02-05 10:04:16 +0800224#endif
Rajesh Bhagatc5e66372018-11-05 18:02:28 +0000225#endif
Dave Liu7737d5c2006-11-03 12:11:15 -0600226
Zhao Qiang93d33202014-09-25 13:52:25 +0800227#ifdef CONFIG_U_QE
Rajesh Bhagatc5e66372018-11-05 18:02:28 +0000228#ifdef CONFIG_TFABOOT
229void u_qe_init(void)
230{
231 enum boot_src src = get_boot_src();
232
233 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
234
235 void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
236
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
Zhao Qiang93d33202014-09-25 13:52:25 +0800272void u_qe_init(void)
273{
Zhao Qiangd3e6d302016-02-05 10:04:17 +0800274 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiang93d33202014-09-25 13:52:25 +0800275
Zhao Qiang5aa03dd2017-05-25 09:47:40 +0800276 void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
277#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 Zhuc3ced8a2018-09-25 14:47:06 +0800296 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
Zhao Qiang5aa03dd2017-05-25 09:47:40 +0800297 addr);
Zhao Qiang5aa03dd2017-05-25 09:47:40 +0800298 }
299#endif
Zhao Qianga7a81752017-08-14 10:22:43 +0800300 if (!u_qe_upload_firmware(addr))
301 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
Zhao Qiang5aa03dd2017-05-25 09:47:40 +0800302#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
303 free(addr);
304#endif
Zhao Qiang93d33202014-09-25 13:52:25 +0800305}
306#endif
Rajesh Bhagatc5e66372018-11-05 18:02:28 +0000307#endif
Zhao Qiang93d33202014-09-25 13:52:25 +0800308
Zhao Qiangae42eb02015-03-25 17:02:59 +0800309#ifdef CONFIG_U_QE
310void u_qe_resume(void)
311{
312 qe_map_t *qe_immrr;
Zhao Qiangae42eb02015-03-25 17:02:59 +0800313
Zhao Qiangd3e6d302016-02-05 10:04:17 +0800314 qe_immrr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiangae42eb02015-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 Liu7737d5c2006-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 Qiang3bf46e62016-02-05 10:04:16 +0800326#ifdef CONFIG_QE
Dave Liu7737d5c2006-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 Qiang3bf46e62016-02-05 10:04:16 +0800342#endif
Dave Liu7737d5c2006-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 Glass1206c182012-12-13 20:48:44 +0000352#define BRG_CLK (gd->arch.brg_clk)
Dave Liu7737d5c2006-11-03 12:11:15 -0600353
Zhao Qiang93d33202014-09-25 13:52:25 +0800354#ifdef CONFIG_QE
Dave Liu7737d5c2006-11-03 12:11:15 -0600355int qe_set_brg(uint brg, uint rate)
356{
Dave Liu7737d5c2006-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 Qiang93d33202014-09-25 13:52:25 +0800382#endif
Dave Liu7737d5c2006-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 Tabib8ec2382008-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 Qiange94a8fd2015-05-05 15:53:32 +0800427 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor,
428 (u16)ucode->revision);
Timur Tabib8ec2382008-01-07 13:31:19 -0600429 else
Zhao Qiange94a8fd2015-05-05 15:53:32 +0800430 printf("QE: uploading microcode '%s'\n", (char *)ucode->id);
Timur Tabib8ec2382008-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 Schuchardtd76485b2020-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 Tabib8ec2382008-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 Qiangca721fb2014-04-30 16:45:31 +0800465#ifdef CONFIG_DEEP_SLEEP
York Sun73fb5832017-03-27 11:41:03 -0700466#ifdef CONFIG_ARCH_LS1021A
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800467 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
468#else
Zhao Qiangca721fb2014-04-30 16:45:31 +0800469 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
470#endif
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800471#endif
Timur Tabib8ec2382008-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 Rai12eeb132014-07-23 18:33:16 +0530483 printf("QE microcode not found\n");
Zhao Qiangca721fb2014-04-30 16:45:31 +0800484#ifdef CONFIG_DEEP_SLEEP
485 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
486#endif
Timur Tabib8ec2382008-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 Tabi491fb6d2008-03-03 09:58:52 -0600497 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabib8ec2382008-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 Denkd3a65322008-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 Tabib8ec2382008-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 Qiang0e0224e2015-05-05 15:53:33 +0800550 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabib8ec2382008-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 Qiang5632d152014-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 Schuchardtd76485b2020-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 Qiang5632d152014-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 Sun73fb5832017-03-27 11:41:03 -0700606#ifdef CONFIG_ARCH_LS1021A
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800607 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
608#else
Zhao Qiang5632d152014-11-04 13:46:16 +0800609 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
610#endif
Zhao Qiang9c7c86f2014-12-15 15:50:49 +0800611#endif
Zhao Qiang5632d152014-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 Qiangae42eb02015-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 Tabib8ec2382008-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 Glass09140112020-05-10 11:40:03 -0600784static int qe_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Timur Tabib8ec2382008-01-07 13:31:19 -0600785{
786 ulong addr;
787
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200788 if (argc < 3)
789 return cmd_usage(cmdtp);
Timur Tabib8ec2382008-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 Denkd3a65322008-01-10 00:55:14 +0100799 /*
800 * If a length was supplied, compare that with the 'length'
801 * field.
802 */
Timur Tabib8ec2382008-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 Denk47e26b12010-07-17 01:06:04 +0200817 return cmd_usage(cmdtp);
Timur Tabib8ec2382008-01-07 13:31:19 -0600818}
819
820U_BOOT_CMD(
821 qe, 4, 0, qe_cmd,
Peter Tyser2fb26042009-01-27 18:03:12 -0600822 "QUICC Engine commands",
Timur Tabib8ec2382008-01-07 13:31:19 -0600823 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200824 "the QE,\n"
825 "\twith optional length <length> verification."
826);