blob: 6e4d732a07a4f6e990f9e175925fd5ec4fdc04e3 [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>
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +000017
York Sunc4f047c2017-03-27 11:41:03 -070018#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +080019#include <asm/arch/immap_ls102xa.h>
20#endif
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +000021#ifdef CONFIG_ARM64
22#include <asm/armv8/mmu.h>
23#include <asm/arch/cpu.h>
Zhao Qiang82cd8c62017-05-25 09:47:40 +080024#endif
25
Zhao Qiangb59534d2014-04-30 16:45:31 +080026#define MPC85xx_DEVDISR_QE_DISABLE 0x1
27
Dave Liue732e9c2006-11-03 12:11:15 -060028qe_map_t *qe_immr = NULL;
Zhao Qiang3ae22202016-02-05 10:04:16 +080029#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060030static qe_snum_t snums[QE_NUM_OF_SNUM];
Zhao Qiang3ae22202016-02-05 10:04:16 +080031#endif
Dave Liue732e9c2006-11-03 12:11:15 -060032
Wolfgang Denkd112a2c2007-09-15 20:48:41 +020033DECLARE_GLOBAL_DATA_PTR;
34
Dave Liue732e9c2006-11-03 12:11:15 -060035void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
36{
Wolfgang Denk545b06a2008-01-10 00:55:14 +010037 u32 cecr;
Dave Liue732e9c2006-11-03 12:11:15 -060038
39 if (cmd == QE_RESET) {
40 out_be32(&qe_immr->cp.cecr,(u32) (cmd | QE_CR_FLG));
41 } else {
42 out_be32(&qe_immr->cp.cecdr, cmd_data);
43 out_be32(&qe_immr->cp.cecr, (sbc | QE_CR_FLG |
44 ((u32) mcn<<QE_CR_PROTOCOL_SHIFT) | cmd));
45 }
46 /* Wait for the QE_CR_FLG to clear */
47 do {
48 cecr = in_be32(&qe_immr->cp.cecr);
49 } while (cecr & QE_CR_FLG);
50
51 return;
52}
53
Zhao Qiang5ad93952014-09-25 13:52:25 +080054#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060055uint qe_muram_alloc(uint size, uint align)
56{
Dave Liue732e9c2006-11-03 12:11:15 -060057 uint retloc;
58 uint align_mask, off;
59 uint savebase;
60
61 align_mask = align - 1;
Simon Glass8518b172012-12-13 20:48:50 +000062 savebase = gd->arch.mp_alloc_base;
Dave Liue732e9c2006-11-03 12:11:15 -060063
Simon Glass8518b172012-12-13 20:48:50 +000064 off = gd->arch.mp_alloc_base & align_mask;
65 if (off != 0)
66 gd->arch.mp_alloc_base += (align - off);
Dave Liue732e9c2006-11-03 12:11:15 -060067
68 if ((off = size & align_mask) != 0)
69 size += (align - off);
70
Simon Glass8518b172012-12-13 20:48:50 +000071 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) {
72 gd->arch.mp_alloc_base = savebase;
Dave Liue732e9c2006-11-03 12:11:15 -060073 printf("%s: ran out of ram.\n", __FUNCTION__);
74 }
75
Simon Glass8518b172012-12-13 20:48:50 +000076 retloc = gd->arch.mp_alloc_base;
77 gd->arch.mp_alloc_base += size;
Dave Liue732e9c2006-11-03 12:11:15 -060078
79 memset((void *)&qe_immr->muram[retloc], 0, size);
80
81 __asm__ __volatile__("sync");
82
83 return retloc;
84}
Zhao Qiang5ad93952014-09-25 13:52:25 +080085#endif
Dave Liue732e9c2006-11-03 12:11:15 -060086
87void *qe_muram_addr(uint offset)
88{
89 return (void *)&qe_immr->muram[offset];
90}
91
Zhao Qiang3ae22202016-02-05 10:04:16 +080092#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060093static void qe_sdma_init(void)
94{
95 volatile sdma_t *p;
96 uint sdma_buffer_base;
97
98 p = (volatile sdma_t *)&qe_immr->sdma;
99
100 /* All of DMA transaction in bus 1 */
101 out_be32(&p->sdaqr, 0);
102 out_be32(&p->sdaqmr, 0);
103
104 /* Allocate 2KB temporary buffer for sdma */
Dave Liu11da1752007-06-25 10:41:04 +0800105 sdma_buffer_base = qe_muram_alloc(2048, 4096);
Dave Liue732e9c2006-11-03 12:11:15 -0600106 out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);
107
108 /* Clear sdma status */
109 out_be32(&p->sdsr, 0x03000000);
110
111 /* Enable global mode on bus 1, and 2KB buffer size */
112 out_be32(&p->sdmr, QE_SDMR_GLB_1_MSK | (0x3 << QE_SDMR_CEN_SHIFT));
113}
114
Haiying Wang0eea38e2009-05-20 12:30:35 -0400115/* This table is a list of the serial numbers of the Threads, taken from the
116 * "SNUM Table" chart in the QE Reference Manual. The order is not important,
117 * we just need to know what the SNUMs are for the threads.
118 */
119static u8 thread_snum[] = {
Gerlando Falautofe201cb2012-10-10 22:13:08 +0000120/* Evthreads 16-29 are not supported in MPC8309 */
Mario Sixb2e701c2019-01-21 09:17:24 +0100121#if !defined(CONFIG_ARCH_MPC8309)
Dave Liue732e9c2006-11-03 12:11:15 -0600122 0x04, 0x05, 0x0c, 0x0d,
123 0x14, 0x15, 0x1c, 0x1d,
124 0x24, 0x25, 0x2c, 0x2d,
Gerlando Falautofe201cb2012-10-10 22:13:08 +0000125 0x34, 0x35,
126#endif
127 0x88, 0x89, 0x98, 0x99,
128 0xa8, 0xa9, 0xb8, 0xb9,
129 0xc8, 0xc9, 0xd8, 0xd9,
130 0xe8, 0xe9, 0x08, 0x09,
131 0x18, 0x19, 0x28, 0x29,
132 0x38, 0x39, 0x48, 0x49,
133 0x58, 0x59, 0x68, 0x69,
134 0x78, 0x79, 0x80, 0x81
Dave Liue732e9c2006-11-03 12:11:15 -0600135};
136
137static void qe_snums_init(void)
138{
139 int i;
140
141 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
142 snums[i].state = QE_SNUM_STATE_FREE;
143 snums[i].num = thread_snum[i];
144 }
145}
146
147int qe_get_snum(void)
148{
149 int snum = -EBUSY;
150 int i;
151
152 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
153 if (snums[i].state == QE_SNUM_STATE_FREE) {
154 snums[i].state = QE_SNUM_STATE_USED;
155 snum = snums[i].num;
156 break;
157 }
158 }
159
160 return snum;
161}
162
163void qe_put_snum(u8 snum)
164{
165 int i;
166
167 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
168 if (snums[i].num == snum) {
169 snums[i].state = QE_SNUM_STATE_FREE;
170 break;
171 }
172 }
173}
174
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000175#ifdef CONFIG_TFABOOT
176void qe_init(uint qe_base)
177{
178 enum boot_src src = get_boot_src();
179
180 /* Init the QE IMMR base */
181 qe_immr = (qe_map_t *)qe_base;
182
183 if (src == BOOT_SOURCE_IFC_NOR) {
184 /*
185 * Upload microcode to IRAM for those SOCs
186 * which do not have ROM in QE.
187 */
188 qe_upload_firmware((const void *)(CONFIG_SYS_QE_FW_ADDR +
189 CONFIG_SYS_FSL_IFC_BASE));
190
191 /* enable the microcode in IRAM */
192 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
193 }
194
195 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
196 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
197
198 qe_sdma_init();
199 qe_snums_init();
200}
201#else
Dave Liue732e9c2006-11-03 12:11:15 -0600202void qe_init(uint qe_base)
203{
Dave Liue732e9c2006-11-03 12:11:15 -0600204 /* Init the QE IMMR base */
205 qe_immr = (qe_map_t *)qe_base;
206
Timur Tabi275f4bb2011-11-22 09:21:25 -0600207#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
Wolfgang Denke366f152009-04-05 00:27:57 +0200208 /*
209 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
210 */
Zhao Qiang83a90842014-03-21 16:21:44 +0800211 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
Haiying Wangec9d36c2009-03-26 17:01:49 -0400212
Wolfgang Denke366f152009-04-05 00:27:57 +0200213 /* enable the microcode in IRAM */
214 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
Haiying Wangec9d36c2009-03-26 17:01:49 -0400215#endif
216
Simon Glass8518b172012-12-13 20:48:50 +0000217 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
218 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
Dave Liue732e9c2006-11-03 12:11:15 -0600219
220 qe_sdma_init();
221 qe_snums_init();
222}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800223#endif
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000224#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600225
Zhao Qiang5ad93952014-09-25 13:52:25 +0800226#ifdef CONFIG_U_QE
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000227#ifdef CONFIG_TFABOOT
Zhao Qiang5ad93952014-09-25 13:52:25 +0800228void u_qe_init(void)
229{
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000230 enum boot_src src = get_boot_src();
231
Zhao Qiang0be9be82016-02-05 10:04:17 +0800232 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiang5ad93952014-09-25 13:52:25 +0800233
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800234 void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000235
236 if (src == BOOT_SOURCE_IFC_NOR)
237 addr = (void *)(CONFIG_SYS_QE_FW_ADDR + CONFIG_SYS_FSL_IFC_BASE);
238
239 if (src == BOOT_SOURCE_QSPI_NOR)
240 addr = (void *)(CONFIG_SYS_QE_FW_ADDR + CONFIG_SYS_FSL_QSPI_BASE);
241
242 if (src == BOOT_SOURCE_SD_MMC) {
243 int dev = CONFIG_SYS_MMC_ENV_DEV;
244 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
245 u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
246
247 if (mmc_initialize(gd->bd)) {
248 printf("%s: mmc_initialize() failed\n", __func__);
249 return;
250 }
251 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
252 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
253
254 if (!mmc) {
255 free(addr);
256 printf("\nMMC cannot find device for ucode\n");
257 } else {
258 printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
259 dev, blk, cnt);
260 mmc_init(mmc);
261 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
262 addr);
263 }
264 }
265 if (!u_qe_upload_firmware(addr))
266 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
267 if (src == BOOT_SOURCE_SD_MMC)
268 free(addr);
269}
270#else
271void u_qe_init(void)
272{
273 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
274
275 void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800276#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
277 int dev = CONFIG_SYS_MMC_ENV_DEV;
278 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
279 u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
280
281 if (mmc_initialize(gd->bd)) {
282 printf("%s: mmc_initialize() failed\n", __func__);
283 return;
284 }
285 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
286 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
287
288 if (!mmc) {
289 free(addr);
290 printf("\nMMC cannot find device for ucode\n");
291 } else {
292 printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
293 dev, blk, cnt);
294 mmc_init(mmc);
Yinbo Zhu45c20bd2018-09-25 14:47:06 +0800295 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800296 addr);
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800297 }
298#endif
Zhao Qiang10640212017-08-14 10:22:43 +0800299 if (!u_qe_upload_firmware(addr))
300 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800301#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
302 free(addr);
303#endif
Zhao Qiang5ad93952014-09-25 13:52:25 +0800304}
305#endif
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000306#endif
Zhao Qiang5ad93952014-09-25 13:52:25 +0800307
Zhao Qiangcfd76712015-03-25 17:02:59 +0800308#ifdef CONFIG_U_QE
309void u_qe_resume(void)
310{
311 qe_map_t *qe_immrr;
Zhao Qiangcfd76712015-03-25 17:02:59 +0800312
Zhao Qiang0be9be82016-02-05 10:04:17 +0800313 qe_immrr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
Zhao Qiangcfd76712015-03-25 17:02:59 +0800314 u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr);
315 out_be32(&qe_immrr->iram.iready, QE_IRAM_READY);
316}
317#endif
318
Dave Liue732e9c2006-11-03 12:11:15 -0600319void qe_reset(void)
320{
321 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
322 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
323}
324
Zhao Qiang3ae22202016-02-05 10:04:16 +0800325#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600326void qe_assign_page(uint snum, uint para_ram_base)
327{
328 u32 cecr;
329
330 out_be32(&qe_immr->cp.cecdr, para_ram_base);
331 out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
332 | QE_CR_FLG | QE_ASSIGN_PAGE);
333
334 /* Wait for the QE_CR_FLG to clear */
335 do {
336 cecr = in_be32(&qe_immr->cp.cecr);
337 } while (cecr & QE_CR_FLG );
338
339 return;
340}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800341#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600342
343/*
344 * brg: 0~15 as BRG1~BRG16
345 rate: baud rate
346 * BRG input clock comes from the BRGCLK (internal clock generated from
347 the QE clock, it is one-half of the QE clock), If need the clock source
348 from CLKn pin, we have te change the function.
349 */
350
Simon Glass34a194f2012-12-13 20:48:44 +0000351#define BRG_CLK (gd->arch.brg_clk)
Dave Liue732e9c2006-11-03 12:11:15 -0600352
Zhao Qiang5ad93952014-09-25 13:52:25 +0800353#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600354int qe_set_brg(uint brg, uint rate)
355{
Dave Liue732e9c2006-11-03 12:11:15 -0600356 volatile uint *bp;
357 u32 divisor;
358 int div16 = 0;
359
360 if (brg >= QE_NUM_OF_BRGS)
361 return -EINVAL;
362 bp = (uint *)&qe_immr->brg.brgc1;
363 bp += brg;
364
365 divisor = (BRG_CLK / rate);
366 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
367 div16 = 1;
368 divisor /= 16;
369 }
370
371 *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
372 __asm__ __volatile__("sync");
373
374 if (div16) {
375 *bp |= QE_BRGC_DIV16;
376 __asm__ __volatile__("sync");
377 }
378
379 return 0;
380}
Zhao Qiang5ad93952014-09-25 13:52:25 +0800381#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600382
383/* Set ethernet MII clock master
384*/
385int qe_set_mii_clk_src(int ucc_num)
386{
387 u32 cmxgcr;
388
389 /* check if the UCC number is in range. */
390 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) {
391 printf("%s: ucc num not in ranges\n", __FUNCTION__);
392 return -EINVAL;
393 }
394
395 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
396 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
397 cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT);
398 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
399
400 return 0;
401}
402
Timur Tabi6d838da2008-01-07 13:31:19 -0600403/* Firmware information stored here for qe_get_firmware_info() */
404static struct qe_firmware_info qe_firmware_info;
405
406/*
407 * Set to 1 if QE firmware has been uploaded, and therefore
408 * qe_firmware_info contains valid data.
409 */
410static int qe_firmware_uploaded;
411
412/*
413 * Upload a QE microcode
414 *
415 * This function is a worker function for qe_upload_firmware(). It does
416 * the actual uploading of the microcode.
417 */
418static void qe_upload_microcode(const void *base,
419 const struct qe_microcode *ucode)
420{
421 const u32 *code = base + be32_to_cpu(ucode->code_offset);
422 unsigned int i;
423
424 if (ucode->major || ucode->minor || ucode->revision)
425 printf("QE: uploading microcode '%s' version %u.%u.%u\n",
Zhao Qiang7879a492015-05-05 15:53:32 +0800426 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor,
427 (u16)ucode->revision);
Timur Tabi6d838da2008-01-07 13:31:19 -0600428 else
Zhao Qiang7879a492015-05-05 15:53:32 +0800429 printf("QE: uploading microcode '%s'\n", (char *)ucode->id);
Timur Tabi6d838da2008-01-07 13:31:19 -0600430
431 /* Use auto-increment */
432 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
433 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
434
435 for (i = 0; i < be32_to_cpu(ucode->count); i++)
436 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
437}
438
439/*
440 * Upload a microcode to the I-RAM at a specific address.
441 *
442 * See docs/README.qe_firmware for information on QE microcode uploading.
443 *
444 * Currently, only version 1 is supported, so the 'version' field must be
445 * set to 1.
446 *
447 * The SOC model and revision are not validated, they are only displayed for
448 * informational purposes.
449 *
450 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
451 * all of the microcode structures, minus the CRC.
452 *
453 * 'length' is the size that the structure says it is, including the CRC.
454 */
455int qe_upload_firmware(const struct qe_firmware *firmware)
456{
457 unsigned int i;
458 unsigned int j;
459 u32 crc;
460 size_t calc_size = sizeof(struct qe_firmware);
461 size_t length;
462 const struct qe_header *hdr;
Zhao Qiangb59534d2014-04-30 16:45:31 +0800463#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700464#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800465 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
466#else
Zhao Qiangb59534d2014-04-30 16:45:31 +0800467 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
468#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800469#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600470 if (!firmware) {
471 printf("Invalid address\n");
472 return -EINVAL;
473 }
474
475 hdr = &firmware->header;
476 length = be32_to_cpu(hdr->length);
477
478 /* Check the magic */
479 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
480 (hdr->magic[2] != 'F')) {
Vijay Raia4792292014-07-23 18:33:16 +0530481 printf("QE microcode not found\n");
Zhao Qiangb59534d2014-04-30 16:45:31 +0800482#ifdef CONFIG_DEEP_SLEEP
483 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
484#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600485 return -EPERM;
486 }
487
488 /* Check the version */
489 if (hdr->version != 1) {
490 printf("Unsupported version\n");
491 return -EPERM;
492 }
493
494 /* Validate some of the fields */
Timur Tabic6c0fd52008-03-03 09:58:52 -0600495 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabi6d838da2008-01-07 13:31:19 -0600496 printf("Invalid data\n");
497 return -EINVAL;
498 }
499
500 /* Validate the length and check if there's a CRC */
501 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
502
503 for (i = 0; i < firmware->count; i++)
504 /*
505 * For situations where the second RISC uses the same microcode
506 * as the first, the 'code_offset' and 'count' fields will be
507 * zero, so it's okay to add those.
508 */
509 calc_size += sizeof(u32) *
510 be32_to_cpu(firmware->microcode[i].count);
511
512 /* Validate the length */
513 if (length != calc_size + sizeof(u32)) {
514 printf("Invalid length\n");
515 return -EPERM;
516 }
517
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100518 /*
519 * Validate the CRC. We would normally call crc32_no_comp(), but that
520 * function isn't available unless you turn on JFFS support.
521 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600522 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
523 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
524 printf("Firmware CRC is invalid\n");
525 return -EIO;
526 }
527
528 /*
529 * If the microcode calls for it, split the I-RAM.
530 */
531 if (!firmware->split) {
532 out_be16(&qe_immr->cp.cercr,
533 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
534 }
535
536 if (firmware->soc.model)
537 printf("Firmware '%s' for %u V%u.%u\n",
538 firmware->id, be16_to_cpu(firmware->soc.model),
539 firmware->soc.major, firmware->soc.minor);
540 else
541 printf("Firmware '%s'\n", firmware->id);
542
543 /*
544 * The QE only supports one microcode per RISC, so clear out all the
545 * saved microcode information and put in the new.
546 */
547 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Zhao Qiangd64f1a42015-05-05 15:53:33 +0800548 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabi6d838da2008-01-07 13:31:19 -0600549 qe_firmware_info.extended_modes = firmware->extended_modes;
550 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
551 sizeof(firmware->vtraps));
552 qe_firmware_uploaded = 1;
553
554 /* Loop through each microcode. */
555 for (i = 0; i < firmware->count; i++) {
556 const struct qe_microcode *ucode = &firmware->microcode[i];
557
558 /* Upload a microcode if it's present */
559 if (ucode->code_offset)
560 qe_upload_microcode(firmware, ucode);
561
562 /* Program the traps for this processor */
563 for (j = 0; j < 16; j++) {
564 u32 trap = be32_to_cpu(ucode->traps[j]);
565
566 if (trap)
567 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
568 }
569
570 /* Enable traps */
571 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
572 }
573
574 return 0;
575}
576
Zhao Qianga985f822014-11-04 13:46:16 +0800577#ifdef CONFIG_U_QE
578/*
579 * Upload a microcode to the I-RAM at a specific address.
580 *
581 * See docs/README.qe_firmware for information on QE microcode uploading.
582 *
583 * Currently, only version 1 is supported, so the 'version' field must be
584 * set to 1.
585 *
586 * The SOC model and revision are not validated, they are only displayed for
587 * informational purposes.
588 *
589 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
590 * all of the microcode structures, minus the CRC.
591 *
592 * 'length' is the size that the structure says it is, including the CRC.
593 */
594int u_qe_upload_firmware(const struct qe_firmware *firmware)
595{
596 unsigned int i;
597 unsigned int j;
598 u32 crc;
599 size_t calc_size = sizeof(struct qe_firmware);
600 size_t length;
601 const struct qe_header *hdr;
602#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700603#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800604 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
605#else
Zhao Qianga985f822014-11-04 13:46:16 +0800606 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
607#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800608#endif
Zhao Qianga985f822014-11-04 13:46:16 +0800609 if (!firmware) {
610 printf("Invalid address\n");
611 return -EINVAL;
612 }
613
614 hdr = &firmware->header;
615 length = be32_to_cpu(hdr->length);
616
617 /* Check the magic */
618 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
619 (hdr->magic[2] != 'F')) {
620 printf("Not a microcode\n");
621#ifdef CONFIG_DEEP_SLEEP
622 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
623#endif
624 return -EPERM;
625 }
626
627 /* Check the version */
628 if (hdr->version != 1) {
629 printf("Unsupported version\n");
630 return -EPERM;
631 }
632
633 /* Validate some of the fields */
634 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
635 printf("Invalid data\n");
636 return -EINVAL;
637 }
638
639 /* Validate the length and check if there's a CRC */
640 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
641
642 for (i = 0; i < firmware->count; i++)
643 /*
644 * For situations where the second RISC uses the same microcode
645 * as the first, the 'code_offset' and 'count' fields will be
646 * zero, so it's okay to add those.
647 */
648 calc_size += sizeof(u32) *
649 be32_to_cpu(firmware->microcode[i].count);
650
651 /* Validate the length */
652 if (length != calc_size + sizeof(u32)) {
653 printf("Invalid length\n");
654 return -EPERM;
655 }
656
657 /*
658 * Validate the CRC. We would normally call crc32_no_comp(), but that
659 * function isn't available unless you turn on JFFS support.
660 */
661 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
662 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
663 printf("Firmware CRC is invalid\n");
664 return -EIO;
665 }
666
667 /*
668 * If the microcode calls for it, split the I-RAM.
669 */
670 if (!firmware->split) {
671 out_be16(&qe_immr->cp.cercr,
672 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
673 }
674
675 if (firmware->soc.model)
676 printf("Firmware '%s' for %u V%u.%u\n",
677 firmware->id, be16_to_cpu(firmware->soc.model),
678 firmware->soc.major, firmware->soc.minor);
679 else
680 printf("Firmware '%s'\n", firmware->id);
681
682 /* Loop through each microcode. */
683 for (i = 0; i < firmware->count; i++) {
684 const struct qe_microcode *ucode = &firmware->microcode[i];
685
686 /* Upload a microcode if it's present */
687 if (ucode->code_offset)
688 qe_upload_microcode(firmware, ucode);
689
690 /* Program the traps for this processor */
691 for (j = 0; j < 16; j++) {
692 u32 trap = be32_to_cpu(ucode->traps[j]);
693
694 if (trap)
695 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
696 }
697
698 /* Enable traps */
699 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
700 }
701
702 return 0;
703}
704#endif
705
Zhao Qiangcfd76712015-03-25 17:02:59 +0800706#ifdef CONFIG_U_QE
707int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
708{
709 unsigned int i;
710 unsigned int j;
711 const struct qe_header *hdr;
712 const u32 *code;
713#ifdef CONFIG_DEEP_SLEEP
714#ifdef CONFIG_PPC
715 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
716#else
717 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
718#endif
719#endif
720
721 if (!firmware)
722 return -EINVAL;
723
724 hdr = &firmware->header;
725
726 /* Check the magic */
727 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
728 (hdr->magic[2] != 'F')) {
729#ifdef CONFIG_DEEP_SLEEP
730 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
731#endif
732 return -EPERM;
733 }
734
735 /*
736 * If the microcode calls for it, split the I-RAM.
737 */
738 if (!firmware->split) {
739 out_be16(&qe_immrr->cp.cercr,
740 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
741 }
742
743 /* Loop through each microcode. */
744 for (i = 0; i < firmware->count; i++) {
745 const struct qe_microcode *ucode = &firmware->microcode[i];
746
747 /* Upload a microcode if it's present */
748 if (!ucode->code_offset)
749 return 0;
750
751 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
752
753 /* Use auto-increment */
754 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
755 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
756
757 for (i = 0; i < be32_to_cpu(ucode->count); i++)
758 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
759
760 /* Program the traps for this processor */
761 for (j = 0; j < 16; j++) {
762 u32 trap = be32_to_cpu(ucode->traps[j]);
763
764 if (trap)
765 out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
766 }
767
768 /* Enable traps */
769 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
770 }
771
772 return 0;
773}
774#endif
775
Timur Tabi6d838da2008-01-07 13:31:19 -0600776struct qe_firmware_info *qe_get_firmware_info(void)
777{
778 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
779}
780
Wolfgang Denk6262d0212010-06-28 22:00:46 +0200781static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Timur Tabi6d838da2008-01-07 13:31:19 -0600782{
783 ulong addr;
784
Wolfgang Denk3b683112010-07-17 01:06:04 +0200785 if (argc < 3)
786 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600787
788 if (strcmp(argv[1], "fw") == 0) {
789 addr = simple_strtoul(argv[2], NULL, 16);
790
791 if (!addr) {
792 printf("Invalid address\n");
793 return -EINVAL;
794 }
795
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100796 /*
797 * If a length was supplied, compare that with the 'length'
798 * field.
799 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600800
801 if (argc > 3) {
802 ulong length = simple_strtoul(argv[3], NULL, 16);
803 struct qe_firmware *firmware = (void *) addr;
804
805 if (length != be32_to_cpu(firmware->header.length)) {
806 printf("Length mismatch\n");
807 return -EINVAL;
808 }
809 }
810
811 return qe_upload_firmware((const struct qe_firmware *) addr);
812 }
813
Wolfgang Denk3b683112010-07-17 01:06:04 +0200814 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600815}
816
817U_BOOT_CMD(
818 qe, 4, 0, qe_cmd,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600819 "QUICC Engine commands",
Timur Tabi6d838da2008-01-07 13:31:19 -0600820 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200821 "the QE,\n"
822 "\twith optional length <length> verification."
823);