blob: 259e4e3e678127dfe894b20850572b8ba09fa008 [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
Heiko Schocherbaf84a92020-05-25 07:27:26 +020029qe_map_t *qe_immr;
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) {
Heiko Schocherbaf84a92020-05-25 07:27:26 +020041 out_be32(&qe_immr->cp.cecr, (u32)(cmd | QE_CR_FLG));
Dave Liue732e9c2006-11-03 12:11:15 -060042 } else {
43 out_be32(&qe_immr->cp.cecdr, cmd_data);
44 out_be32(&qe_immr->cp.cecr, (sbc | QE_CR_FLG |
Heiko Schocherbaf84a92020-05-25 07:27:26 +020045 ((u32)mcn << QE_CR_PROTOCOL_SHIFT) | cmd));
Dave Liue732e9c2006-11-03 12:11:15 -060046 }
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);
Dave Liue732e9c2006-11-03 12:11:15 -060051}
52
Zhao Qiang5ad93952014-09-25 13:52:25 +080053#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -060054uint qe_muram_alloc(uint size, uint align)
55{
Dave Liue732e9c2006-11-03 12:11:15 -060056 uint retloc;
57 uint align_mask, off;
58 uint savebase;
59
60 align_mask = align - 1;
Simon Glass8518b172012-12-13 20:48:50 +000061 savebase = gd->arch.mp_alloc_base;
Dave Liue732e9c2006-11-03 12:11:15 -060062
Simon Glass8518b172012-12-13 20:48:50 +000063 off = gd->arch.mp_alloc_base & align_mask;
64 if (off != 0)
65 gd->arch.mp_alloc_base += (align - off);
Dave Liue732e9c2006-11-03 12:11:15 -060066
Heiko Schocherbaf84a92020-05-25 07:27:26 +020067 off = size & align_mask;
68 if (off != 0)
Dave Liue732e9c2006-11-03 12:11:15 -060069 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;
Heiko Schocherbaf84a92020-05-25 07:27:26 +020073 printf("%s: ran out of ram.\n", __func__);
Dave Liue732e9c2006-11-03 12:11:15 -060074 }
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{
Heiko Schocherbaf84a92020-05-25 07:27:26 +020095 sdma_t *p;
96 uint sdma_buffer_base;
Dave Liue732e9c2006-11-03 12:11:15 -060097
Heiko Schocherbaf84a92020-05-25 07:27:26 +020098 p = (sdma_t *)&qe_immr->sdma;
Dave Liue732e9c2006-11-03 12:11:15 -060099
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 */
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200214 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)
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200237 addr = (void *)(CONFIG_SYS_QE_FW_ADDR +
238 CONFIG_SYS_FSL_IFC_BASE);
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000239
240 if (src == BOOT_SOURCE_QSPI_NOR)
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200241 addr = (void *)(CONFIG_SYS_QE_FW_ADDR +
242 CONFIG_SYS_FSL_QSPI_BASE);
Rajesh Bhagat4fb459e2018-11-05 18:02:28 +0000243
244 if (src == BOOT_SOURCE_SD_MMC) {
245 int dev = CONFIG_SYS_MMC_ENV_DEV;
246 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
247 u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
248
249 if (mmc_initialize(gd->bd)) {
250 printf("%s: mmc_initialize() failed\n", __func__);
251 return;
252 }
253 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
254 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
255
256 if (!mmc) {
257 free(addr);
258 printf("\nMMC cannot find device for ucode\n");
259 } else {
260 printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
261 dev, blk, cnt);
262 mmc_init(mmc);
263 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
264 addr);
265 }
266 }
267 if (!u_qe_upload_firmware(addr))
268 out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
269 if (src == BOOT_SOURCE_SD_MMC)
270 free(addr);
271}
272#else
273void u_qe_init(void)
274{
275 qe_immr = (qe_map_t *)(CONFIG_SYS_IMMR + QE_IMMR_OFFSET);
276
277 void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800278#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
279 int dev = CONFIG_SYS_MMC_ENV_DEV;
280 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
281 u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
282
283 if (mmc_initialize(gd->bd)) {
284 printf("%s: mmc_initialize() failed\n", __func__);
285 return;
286 }
287 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
288 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
289
290 if (!mmc) {
Zhao Qiang82cd8c62017-05-25 09:47:40 +0800291 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,
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200323 (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0);
Dave Liue732e9c2006-11-03 12:11:15 -0600324}
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);
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200332 out_be32(&qe_immr->cp.cecr, ((u32)snum << QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
Dave Liue732e9c2006-11-03 12:11:15 -0600333 | 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);
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200338 } while (cecr & QE_CR_FLG);
Dave Liue732e9c2006-11-03 12:11:15 -0600339}
Zhao Qiang3ae22202016-02-05 10:04:16 +0800340#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600341
342/*
343 * brg: 0~15 as BRG1~BRG16
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200344 * rate: baud rate
Dave Liue732e9c2006-11-03 12:11:15 -0600345 * BRG input clock comes from the BRGCLK (internal clock generated from
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200346 * the QE clock, it is one-half of the QE clock), If need the clock source
347 * from CLKn pin, we have te change the function.
Dave Liue732e9c2006-11-03 12:11:15 -0600348 */
349
Simon Glass34a194f2012-12-13 20:48:44 +0000350#define BRG_CLK (gd->arch.brg_clk)
Dave Liue732e9c2006-11-03 12:11:15 -0600351
Zhao Qiang5ad93952014-09-25 13:52:25 +0800352#ifdef CONFIG_QE
Dave Liue732e9c2006-11-03 12:11:15 -0600353int qe_set_brg(uint brg, uint rate)
354{
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200355 uint *bp;
356 u32 divisor;
357 u32 val;
358 int div16 = 0;
Dave Liue732e9c2006-11-03 12:11:15 -0600359
360 if (brg >= QE_NUM_OF_BRGS)
361 return -EINVAL;
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200362
Dave Liue732e9c2006-11-03 12:11:15 -0600363 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
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200372 /* CHECK TODO */
373 /*
374 * was
375 * *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
376 * __asm__ __volatile__("sync");
377 */
Dave Liue732e9c2006-11-03 12:11:15 -0600378
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200379 val = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
380 if (div16)
381 val |= QE_BRGC_DIV16;
382
383 out_be32(bp, val);
Dave Liue732e9c2006-11-03 12:11:15 -0600384
385 return 0;
386}
Zhao Qiang5ad93952014-09-25 13:52:25 +0800387#endif
Dave Liue732e9c2006-11-03 12:11:15 -0600388
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200389/* Set ethernet MII clock master */
Dave Liue732e9c2006-11-03 12:11:15 -0600390int qe_set_mii_clk_src(int ucc_num)
391{
392 u32 cmxgcr;
393
394 /* check if the UCC number is in range. */
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200395 if ((ucc_num > UCC_MAX_NUM - 1) || ucc_num < 0) {
396 printf("%s: ucc num not in ranges\n", __func__);
Dave Liue732e9c2006-11-03 12:11:15 -0600397 return -EINVAL;
398 }
399
400 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
401 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200402 cmxgcr |= (ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
Dave Liue732e9c2006-11-03 12:11:15 -0600403 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
404
405 return 0;
406}
407
Timur Tabi6d838da2008-01-07 13:31:19 -0600408/* Firmware information stored here for qe_get_firmware_info() */
409static struct qe_firmware_info qe_firmware_info;
410
411/*
412 * Set to 1 if QE firmware has been uploaded, and therefore
413 * qe_firmware_info contains valid data.
414 */
415static int qe_firmware_uploaded;
416
417/*
418 * Upload a QE microcode
419 *
420 * This function is a worker function for qe_upload_firmware(). It does
421 * the actual uploading of the microcode.
422 */
423static void qe_upload_microcode(const void *base,
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200424 const struct qe_microcode *ucode)
Timur Tabi6d838da2008-01-07 13:31:19 -0600425{
426 const u32 *code = base + be32_to_cpu(ucode->code_offset);
427 unsigned int i;
428
429 if (ucode->major || ucode->minor || ucode->revision)
430 printf("QE: uploading microcode '%s' version %u.%u.%u\n",
Zhao Qiang7879a492015-05-05 15:53:32 +0800431 (char *)ucode->id, (u16)ucode->major, (u16)ucode->minor,
432 (u16)ucode->revision);
Timur Tabi6d838da2008-01-07 13:31:19 -0600433 else
Zhao Qiang7879a492015-05-05 15:53:32 +0800434 printf("QE: uploading microcode '%s'\n", (char *)ucode->id);
Timur Tabi6d838da2008-01-07 13:31:19 -0600435
436 /* Use auto-increment */
437 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
438 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
439
440 for (i = 0; i < be32_to_cpu(ucode->count); i++)
441 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
442}
443
444/*
445 * Upload a microcode to the I-RAM at a specific address.
446 *
Heinrich Schuchardtb0289282020-04-19 09:19:04 +0200447 * See Documentation/powerpc/qe_firmware.rst in the Linux kernel tree for
448 * information on QE microcode uploading.
Timur Tabi6d838da2008-01-07 13:31:19 -0600449 *
450 * Currently, only version 1 is supported, so the 'version' field must be
451 * set to 1.
452 *
453 * The SOC model and revision are not validated, they are only displayed for
454 * informational purposes.
455 *
456 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
457 * all of the microcode structures, minus the CRC.
458 *
459 * 'length' is the size that the structure says it is, including the CRC.
460 */
461int qe_upload_firmware(const struct qe_firmware *firmware)
462{
463 unsigned int i;
464 unsigned int j;
465 u32 crc;
466 size_t calc_size = sizeof(struct qe_firmware);
467 size_t length;
468 const struct qe_header *hdr;
Zhao Qiangb59534d2014-04-30 16:45:31 +0800469#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700470#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800471 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
472#else
Zhao Qiangb59534d2014-04-30 16:45:31 +0800473 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
474#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800475#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600476 if (!firmware) {
477 printf("Invalid address\n");
478 return -EINVAL;
479 }
480
481 hdr = &firmware->header;
482 length = be32_to_cpu(hdr->length);
483
484 /* Check the magic */
485 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
486 (hdr->magic[2] != 'F')) {
Vijay Raia4792292014-07-23 18:33:16 +0530487 printf("QE microcode not found\n");
Zhao Qiangb59534d2014-04-30 16:45:31 +0800488#ifdef CONFIG_DEEP_SLEEP
489 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
490#endif
Timur Tabi6d838da2008-01-07 13:31:19 -0600491 return -EPERM;
492 }
493
494 /* Check the version */
495 if (hdr->version != 1) {
496 printf("Unsupported version\n");
497 return -EPERM;
498 }
499
500 /* Validate some of the fields */
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200501 if (firmware->count < 1 || firmware->count > MAX_QE_RISC) {
Timur Tabi6d838da2008-01-07 13:31:19 -0600502 printf("Invalid data\n");
503 return -EINVAL;
504 }
505
506 /* Validate the length and check if there's a CRC */
507 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
508
509 for (i = 0; i < firmware->count; i++)
510 /*
511 * For situations where the second RISC uses the same microcode
512 * as the first, the 'code_offset' and 'count' fields will be
513 * zero, so it's okay to add those.
514 */
515 calc_size += sizeof(u32) *
516 be32_to_cpu(firmware->microcode[i].count);
517
518 /* Validate the length */
519 if (length != calc_size + sizeof(u32)) {
520 printf("Invalid length\n");
521 return -EPERM;
522 }
523
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100524 /*
525 * Validate the CRC. We would normally call crc32_no_comp(), but that
526 * function isn't available unless you turn on JFFS support.
527 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600528 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200529 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
Timur Tabi6d838da2008-01-07 13:31:19 -0600530 printf("Firmware CRC is invalid\n");
531 return -EIO;
532 }
533
534 /*
535 * If the microcode calls for it, split the I-RAM.
536 */
537 if (!firmware->split) {
538 out_be16(&qe_immr->cp.cercr,
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200539 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
Timur Tabi6d838da2008-01-07 13:31:19 -0600540 }
541
542 if (firmware->soc.model)
543 printf("Firmware '%s' for %u V%u.%u\n",
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200544 firmware->id, be16_to_cpu(firmware->soc.model),
Timur Tabi6d838da2008-01-07 13:31:19 -0600545 firmware->soc.major, firmware->soc.minor);
546 else
547 printf("Firmware '%s'\n", firmware->id);
548
549 /*
550 * The QE only supports one microcode per RISC, so clear out all the
551 * saved microcode information and put in the new.
552 */
553 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Zhao Qiangd64f1a42015-05-05 15:53:33 +0800554 strncpy(qe_firmware_info.id, (char *)firmware->id, 62);
Timur Tabi6d838da2008-01-07 13:31:19 -0600555 qe_firmware_info.extended_modes = firmware->extended_modes;
556 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200557 sizeof(firmware->vtraps));
Timur Tabi6d838da2008-01-07 13:31:19 -0600558 qe_firmware_uploaded = 1;
559
560 /* Loop through each microcode. */
561 for (i = 0; i < firmware->count; i++) {
562 const struct qe_microcode *ucode = &firmware->microcode[i];
563
564 /* Upload a microcode if it's present */
565 if (ucode->code_offset)
566 qe_upload_microcode(firmware, ucode);
567
568 /* Program the traps for this processor */
569 for (j = 0; j < 16; j++) {
570 u32 trap = be32_to_cpu(ucode->traps[j]);
571
572 if (trap)
573 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
574 }
575
576 /* Enable traps */
577 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
578 }
579
580 return 0;
581}
582
Zhao Qianga985f822014-11-04 13:46:16 +0800583#ifdef CONFIG_U_QE
584/*
585 * Upload a microcode to the I-RAM at a specific address.
586 *
Heinrich Schuchardtb0289282020-04-19 09:19:04 +0200587 * See Documentation/powerpc/qe_firmware.rst in the Linux kernel tree for
588 * information on QE microcode uploading.
Zhao Qianga985f822014-11-04 13:46:16 +0800589 *
590 * Currently, only version 1 is supported, so the 'version' field must be
591 * set to 1.
592 *
593 * The SOC model and revision are not validated, they are only displayed for
594 * informational purposes.
595 *
596 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
597 * all of the microcode structures, minus the CRC.
598 *
599 * 'length' is the size that the structure says it is, including the CRC.
600 */
601int u_qe_upload_firmware(const struct qe_firmware *firmware)
602{
603 unsigned int i;
604 unsigned int j;
605 u32 crc;
606 size_t calc_size = sizeof(struct qe_firmware);
607 size_t length;
608 const struct qe_header *hdr;
609#ifdef CONFIG_DEEP_SLEEP
York Sunc4f047c2017-03-27 11:41:03 -0700610#ifdef CONFIG_ARCH_LS1021A
Zhao Qiangdf412c62014-12-15 15:50:49 +0800611 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
612#else
Zhao Qianga985f822014-11-04 13:46:16 +0800613 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
614#endif
Zhao Qiangdf412c62014-12-15 15:50:49 +0800615#endif
Zhao Qianga985f822014-11-04 13:46:16 +0800616 if (!firmware) {
617 printf("Invalid address\n");
618 return -EINVAL;
619 }
620
621 hdr = &firmware->header;
622 length = be32_to_cpu(hdr->length);
623
624 /* Check the magic */
625 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
626 (hdr->magic[2] != 'F')) {
627 printf("Not a microcode\n");
628#ifdef CONFIG_DEEP_SLEEP
629 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
630#endif
631 return -EPERM;
632 }
633
634 /* Check the version */
635 if (hdr->version != 1) {
636 printf("Unsupported version\n");
637 return -EPERM;
638 }
639
640 /* Validate some of the fields */
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200641 if (firmware->count < 1 || firmware->count > MAX_QE_RISC) {
Zhao Qianga985f822014-11-04 13:46:16 +0800642 printf("Invalid data\n");
643 return -EINVAL;
644 }
645
646 /* Validate the length and check if there's a CRC */
647 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
648
649 for (i = 0; i < firmware->count; i++)
650 /*
651 * For situations where the second RISC uses the same microcode
652 * as the first, the 'code_offset' and 'count' fields will be
653 * zero, so it's okay to add those.
654 */
655 calc_size += sizeof(u32) *
656 be32_to_cpu(firmware->microcode[i].count);
657
658 /* Validate the length */
659 if (length != calc_size + sizeof(u32)) {
660 printf("Invalid length\n");
661 return -EPERM;
662 }
663
664 /*
665 * Validate the CRC. We would normally call crc32_no_comp(), but that
666 * function isn't available unless you turn on JFFS support.
667 */
668 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
669 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
670 printf("Firmware CRC is invalid\n");
671 return -EIO;
672 }
673
674 /*
675 * If the microcode calls for it, split the I-RAM.
676 */
677 if (!firmware->split) {
678 out_be16(&qe_immr->cp.cercr,
679 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
680 }
681
682 if (firmware->soc.model)
683 printf("Firmware '%s' for %u V%u.%u\n",
684 firmware->id, be16_to_cpu(firmware->soc.model),
685 firmware->soc.major, firmware->soc.minor);
686 else
687 printf("Firmware '%s'\n", firmware->id);
688
689 /* Loop through each microcode. */
690 for (i = 0; i < firmware->count; i++) {
691 const struct qe_microcode *ucode = &firmware->microcode[i];
692
693 /* Upload a microcode if it's present */
694 if (ucode->code_offset)
695 qe_upload_microcode(firmware, ucode);
696
697 /* Program the traps for this processor */
698 for (j = 0; j < 16; j++) {
699 u32 trap = be32_to_cpu(ucode->traps[j]);
700
701 if (trap)
702 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
703 }
704
705 /* Enable traps */
706 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
707 }
708
709 return 0;
710}
711#endif
712
Zhao Qiangcfd76712015-03-25 17:02:59 +0800713#ifdef CONFIG_U_QE
714int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr)
715{
716 unsigned int i;
717 unsigned int j;
718 const struct qe_header *hdr;
719 const u32 *code;
720#ifdef CONFIG_DEEP_SLEEP
721#ifdef CONFIG_PPC
722 ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
723#else
724 struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
725#endif
726#endif
727
728 if (!firmware)
729 return -EINVAL;
730
731 hdr = &firmware->header;
732
733 /* Check the magic */
734 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
735 (hdr->magic[2] != 'F')) {
736#ifdef CONFIG_DEEP_SLEEP
737 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
738#endif
739 return -EPERM;
740 }
741
742 /*
743 * If the microcode calls for it, split the I-RAM.
744 */
745 if (!firmware->split) {
746 out_be16(&qe_immrr->cp.cercr,
747 in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR);
748 }
749
750 /* Loop through each microcode. */
751 for (i = 0; i < firmware->count; i++) {
752 const struct qe_microcode *ucode = &firmware->microcode[i];
753
754 /* Upload a microcode if it's present */
755 if (!ucode->code_offset)
756 return 0;
757
758 code = (const void *)firmware + be32_to_cpu(ucode->code_offset);
759
760 /* Use auto-increment */
761 out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
762 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
763
764 for (i = 0; i < be32_to_cpu(ucode->count); i++)
765 out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i]));
766
767 /* Program the traps for this processor */
768 for (j = 0; j < 16; j++) {
769 u32 trap = be32_to_cpu(ucode->traps[j]);
770
771 if (trap)
772 out_be32(&qe_immrr->rsp[i].tibcr[j], trap);
773 }
774
775 /* Enable traps */
776 out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
777 }
778
779 return 0;
780}
781#endif
782
Timur Tabi6d838da2008-01-07 13:31:19 -0600783struct qe_firmware_info *qe_get_firmware_info(void)
784{
785 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
786}
787
Simon Glassed38aef2020-05-10 11:40:03 -0600788static int qe_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Timur Tabi6d838da2008-01-07 13:31:19 -0600789{
790 ulong addr;
791
Wolfgang Denk3b683112010-07-17 01:06:04 +0200792 if (argc < 3)
793 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600794
795 if (strcmp(argv[1], "fw") == 0) {
796 addr = simple_strtoul(argv[2], NULL, 16);
797
798 if (!addr) {
799 printf("Invalid address\n");
800 return -EINVAL;
801 }
802
Wolfgang Denk545b06a2008-01-10 00:55:14 +0100803 /*
804 * If a length was supplied, compare that with the 'length'
805 * field.
806 */
Timur Tabi6d838da2008-01-07 13:31:19 -0600807
808 if (argc > 3) {
809 ulong length = simple_strtoul(argv[3], NULL, 16);
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200810 struct qe_firmware *firmware = (void *)addr;
Timur Tabi6d838da2008-01-07 13:31:19 -0600811
812 if (length != be32_to_cpu(firmware->header.length)) {
813 printf("Length mismatch\n");
814 return -EINVAL;
815 }
816 }
817
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200818 return qe_upload_firmware((const struct qe_firmware *)addr);
Timur Tabi6d838da2008-01-07 13:31:19 -0600819 }
820
Wolfgang Denk3b683112010-07-17 01:06:04 +0200821 return cmd_usage(cmdtp);
Timur Tabi6d838da2008-01-07 13:31:19 -0600822}
823
824U_BOOT_CMD(
825 qe, 4, 0, qe_cmd,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600826 "QUICC Engine commands",
Heiko Schocherbaf84a92020-05-25 07:27:26 +0200827 "fw <addr> [<length>] - Upload firmware binary at address <addr> to the QE,\n"
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200828 "\twith optional length <length> verification."
829);