]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/qe/qe.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[people/ms/u-boot.git] / drivers / qe / qe.c
CommitLineData
7737d5c6 1/*
4e7b25e4 2 * Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
7737d5c6
DL
3 *
4 * Dave Liu <daveliu@freescale.com>
5 * based on source code of Shlomi Gridish
6 *
1a459660 7 * SPDX-License-Identifier: GPL-2.0+
7737d5c6
DL
8 */
9
10#include "common.h"
b8ec2385 11#include <command.h>
7737d5c6
DL
12#include "asm/errno.h"
13#include "asm/io.h"
38d67a4e 14#include "linux/immap_qe.h"
7737d5c6
DL
15#include "qe.h"
16
ca721fb2
ZQ
17#define MPC85xx_DEVDISR_QE_DISABLE 0x1
18
7737d5c6
DL
19qe_map_t *qe_immr = NULL;
20static qe_snum_t snums[QE_NUM_OF_SNUM];
21
1218abf1
WD
22DECLARE_GLOBAL_DATA_PTR;
23
7737d5c6
DL
24void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
25{
d3a6532c 26 u32 cecr;
7737d5c6
DL
27
28 if (cmd == QE_RESET) {
29 out_be32(&qe_immr->cp.cecr,(u32) (cmd | QE_CR_FLG));
30 } else {
31 out_be32(&qe_immr->cp.cecdr, cmd_data);
32 out_be32(&qe_immr->cp.cecr, (sbc | QE_CR_FLG |
33 ((u32) mcn<<QE_CR_PROTOCOL_SHIFT) | cmd));
34 }
35 /* Wait for the QE_CR_FLG to clear */
36 do {
37 cecr = in_be32(&qe_immr->cp.cecr);
38 } while (cecr & QE_CR_FLG);
39
40 return;
41}
42
43uint qe_muram_alloc(uint size, uint align)
44{
7737d5c6
DL
45 uint retloc;
46 uint align_mask, off;
47 uint savebase;
48
49 align_mask = align - 1;
45bae2e3 50 savebase = gd->arch.mp_alloc_base;
7737d5c6 51
45bae2e3
SG
52 off = gd->arch.mp_alloc_base & align_mask;
53 if (off != 0)
54 gd->arch.mp_alloc_base += (align - off);
7737d5c6
DL
55
56 if ((off = size & align_mask) != 0)
57 size += (align - off);
58
45bae2e3
SG
59 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) {
60 gd->arch.mp_alloc_base = savebase;
7737d5c6
DL
61 printf("%s: ran out of ram.\n", __FUNCTION__);
62 }
63
45bae2e3
SG
64 retloc = gd->arch.mp_alloc_base;
65 gd->arch.mp_alloc_base += size;
7737d5c6
DL
66
67 memset((void *)&qe_immr->muram[retloc], 0, size);
68
69 __asm__ __volatile__("sync");
70
71 return retloc;
72}
73
74void *qe_muram_addr(uint offset)
75{
76 return (void *)&qe_immr->muram[offset];
77}
78
79static void qe_sdma_init(void)
80{
81 volatile sdma_t *p;
82 uint sdma_buffer_base;
83
84 p = (volatile sdma_t *)&qe_immr->sdma;
85
86 /* All of DMA transaction in bus 1 */
87 out_be32(&p->sdaqr, 0);
88 out_be32(&p->sdaqmr, 0);
89
90 /* Allocate 2KB temporary buffer for sdma */
ff9658d7 91 sdma_buffer_base = qe_muram_alloc(2048, 4096);
7737d5c6
DL
92 out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);
93
94 /* Clear sdma status */
95 out_be32(&p->sdsr, 0x03000000);
96
97 /* Enable global mode on bus 1, and 2KB buffer size */
98 out_be32(&p->sdmr, QE_SDMR_GLB_1_MSK | (0x3 << QE_SDMR_CEN_SHIFT));
99}
100
4e7b25e4
HW
101/* This table is a list of the serial numbers of the Threads, taken from the
102 * "SNUM Table" chart in the QE Reference Manual. The order is not important,
103 * we just need to know what the SNUMs are for the threads.
104 */
105static u8 thread_snum[] = {
a88731a6
GF
106/* Evthreads 16-29 are not supported in MPC8309 */
107#if !defined(CONFIG_MPC8309)
7737d5c6
DL
108 0x04, 0x05, 0x0c, 0x0d,
109 0x14, 0x15, 0x1c, 0x1d,
110 0x24, 0x25, 0x2c, 0x2d,
a88731a6
GF
111 0x34, 0x35,
112#endif
113 0x88, 0x89, 0x98, 0x99,
114 0xa8, 0xa9, 0xb8, 0xb9,
115 0xc8, 0xc9, 0xd8, 0xd9,
116 0xe8, 0xe9, 0x08, 0x09,
117 0x18, 0x19, 0x28, 0x29,
118 0x38, 0x39, 0x48, 0x49,
119 0x58, 0x59, 0x68, 0x69,
120 0x78, 0x79, 0x80, 0x81
7737d5c6
DL
121};
122
123static void qe_snums_init(void)
124{
125 int i;
126
127 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
128 snums[i].state = QE_SNUM_STATE_FREE;
129 snums[i].num = thread_snum[i];
130 }
131}
132
133int qe_get_snum(void)
134{
135 int snum = -EBUSY;
136 int i;
137
138 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
139 if (snums[i].state == QE_SNUM_STATE_FREE) {
140 snums[i].state = QE_SNUM_STATE_USED;
141 snum = snums[i].num;
142 break;
143 }
144 }
145
146 return snum;
147}
148
149void qe_put_snum(u8 snum)
150{
151 int i;
152
153 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
154 if (snums[i].num == snum) {
155 snums[i].state = QE_SNUM_STATE_FREE;
156 break;
157 }
158 }
159}
160
161void qe_init(uint qe_base)
162{
7737d5c6
DL
163 /* Init the QE IMMR base */
164 qe_immr = (qe_map_t *)qe_base;
165
f2717b47 166#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
c0a14aed
WD
167 /*
168 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
169 */
dcf1d774 170 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
2d4de6ae 171
c0a14aed
WD
172 /* enable the microcode in IRAM */
173 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
2d4de6ae
HW
174#endif
175
45bae2e3
SG
176 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
177 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
7737d5c6
DL
178
179 qe_sdma_init();
180 qe_snums_init();
181}
182
183void qe_reset(void)
184{
185 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
186 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
187}
188
189void qe_assign_page(uint snum, uint para_ram_base)
190{
191 u32 cecr;
192
193 out_be32(&qe_immr->cp.cecdr, para_ram_base);
194 out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
195 | QE_CR_FLG | QE_ASSIGN_PAGE);
196
197 /* Wait for the QE_CR_FLG to clear */
198 do {
199 cecr = in_be32(&qe_immr->cp.cecr);
200 } while (cecr & QE_CR_FLG );
201
202 return;
203}
204
205/*
206 * brg: 0~15 as BRG1~BRG16
207 rate: baud rate
208 * BRG input clock comes from the BRGCLK (internal clock generated from
209 the QE clock, it is one-half of the QE clock), If need the clock source
210 from CLKn pin, we have te change the function.
211 */
212
1206c184 213#define BRG_CLK (gd->arch.brg_clk)
7737d5c6
DL
214
215int qe_set_brg(uint brg, uint rate)
216{
7737d5c6
DL
217 volatile uint *bp;
218 u32 divisor;
219 int div16 = 0;
220
221 if (brg >= QE_NUM_OF_BRGS)
222 return -EINVAL;
223 bp = (uint *)&qe_immr->brg.brgc1;
224 bp += brg;
225
226 divisor = (BRG_CLK / rate);
227 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
228 div16 = 1;
229 divisor /= 16;
230 }
231
232 *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
233 __asm__ __volatile__("sync");
234
235 if (div16) {
236 *bp |= QE_BRGC_DIV16;
237 __asm__ __volatile__("sync");
238 }
239
240 return 0;
241}
242
243/* Set ethernet MII clock master
244*/
245int qe_set_mii_clk_src(int ucc_num)
246{
247 u32 cmxgcr;
248
249 /* check if the UCC number is in range. */
250 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) {
251 printf("%s: ucc num not in ranges\n", __FUNCTION__);
252 return -EINVAL;
253 }
254
255 cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
256 cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
257 cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT);
258 out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
259
260 return 0;
261}
262
b8ec2385
TT
263/* Firmware information stored here for qe_get_firmware_info() */
264static struct qe_firmware_info qe_firmware_info;
265
266/*
267 * Set to 1 if QE firmware has been uploaded, and therefore
268 * qe_firmware_info contains valid data.
269 */
270static int qe_firmware_uploaded;
271
272/*
273 * Upload a QE microcode
274 *
275 * This function is a worker function for qe_upload_firmware(). It does
276 * the actual uploading of the microcode.
277 */
278static void qe_upload_microcode(const void *base,
279 const struct qe_microcode *ucode)
280{
281 const u32 *code = base + be32_to_cpu(ucode->code_offset);
282 unsigned int i;
283
284 if (ucode->major || ucode->minor || ucode->revision)
285 printf("QE: uploading microcode '%s' version %u.%u.%u\n",
286 ucode->id, ucode->major, ucode->minor, ucode->revision);
287 else
288 printf("QE: uploading microcode '%s'\n", ucode->id);
289
290 /* Use auto-increment */
291 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
292 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
293
294 for (i = 0; i < be32_to_cpu(ucode->count); i++)
295 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
296}
297
298/*
299 * Upload a microcode to the I-RAM at a specific address.
300 *
301 * See docs/README.qe_firmware for information on QE microcode uploading.
302 *
303 * Currently, only version 1 is supported, so the 'version' field must be
304 * set to 1.
305 *
306 * The SOC model and revision are not validated, they are only displayed for
307 * informational purposes.
308 *
309 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
310 * all of the microcode structures, minus the CRC.
311 *
312 * 'length' is the size that the structure says it is, including the CRC.
313 */
314int qe_upload_firmware(const struct qe_firmware *firmware)
315{
316 unsigned int i;
317 unsigned int j;
318 u32 crc;
319 size_t calc_size = sizeof(struct qe_firmware);
320 size_t length;
321 const struct qe_header *hdr;
ca721fb2
ZQ
322#ifdef CONFIG_DEEP_SLEEP
323 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
324#endif
b8ec2385
TT
325 if (!firmware) {
326 printf("Invalid address\n");
327 return -EINVAL;
328 }
329
330 hdr = &firmware->header;
331 length = be32_to_cpu(hdr->length);
332
333 /* Check the magic */
334 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
335 (hdr->magic[2] != 'F')) {
12eeb135 336 printf("QE microcode not found\n");
ca721fb2
ZQ
337#ifdef CONFIG_DEEP_SLEEP
338 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
339#endif
b8ec2385
TT
340 return -EPERM;
341 }
342
343 /* Check the version */
344 if (hdr->version != 1) {
345 printf("Unsupported version\n");
346 return -EPERM;
347 }
348
349 /* Validate some of the fields */
491fb6de 350 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
b8ec2385
TT
351 printf("Invalid data\n");
352 return -EINVAL;
353 }
354
355 /* Validate the length and check if there's a CRC */
356 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
357
358 for (i = 0; i < firmware->count; i++)
359 /*
360 * For situations where the second RISC uses the same microcode
361 * as the first, the 'code_offset' and 'count' fields will be
362 * zero, so it's okay to add those.
363 */
364 calc_size += sizeof(u32) *
365 be32_to_cpu(firmware->microcode[i].count);
366
367 /* Validate the length */
368 if (length != calc_size + sizeof(u32)) {
369 printf("Invalid length\n");
370 return -EPERM;
371 }
372
d3a6532c
WD
373 /*
374 * Validate the CRC. We would normally call crc32_no_comp(), but that
375 * function isn't available unless you turn on JFFS support.
376 */
b8ec2385
TT
377 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
378 if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
379 printf("Firmware CRC is invalid\n");
380 return -EIO;
381 }
382
383 /*
384 * If the microcode calls for it, split the I-RAM.
385 */
386 if (!firmware->split) {
387 out_be16(&qe_immr->cp.cercr,
388 in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
389 }
390
391 if (firmware->soc.model)
392 printf("Firmware '%s' for %u V%u.%u\n",
393 firmware->id, be16_to_cpu(firmware->soc.model),
394 firmware->soc.major, firmware->soc.minor);
395 else
396 printf("Firmware '%s'\n", firmware->id);
397
398 /*
399 * The QE only supports one microcode per RISC, so clear out all the
400 * saved microcode information and put in the new.
401 */
402 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
06c428bc 403 strcpy(qe_firmware_info.id, (char *)firmware->id);
b8ec2385
TT
404 qe_firmware_info.extended_modes = firmware->extended_modes;
405 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
406 sizeof(firmware->vtraps));
407 qe_firmware_uploaded = 1;
408
409 /* Loop through each microcode. */
410 for (i = 0; i < firmware->count; i++) {
411 const struct qe_microcode *ucode = &firmware->microcode[i];
412
413 /* Upload a microcode if it's present */
414 if (ucode->code_offset)
415 qe_upload_microcode(firmware, ucode);
416
417 /* Program the traps for this processor */
418 for (j = 0; j < 16; j++) {
419 u32 trap = be32_to_cpu(ucode->traps[j]);
420
421 if (trap)
422 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
423 }
424
425 /* Enable traps */
426 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
427 }
428
429 return 0;
430}
431
432struct qe_firmware_info *qe_get_firmware_info(void)
433{
434 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
435}
436
54841ab5 437static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
b8ec2385
TT
438{
439 ulong addr;
440
47e26b1b
WD
441 if (argc < 3)
442 return cmd_usage(cmdtp);
b8ec2385
TT
443
444 if (strcmp(argv[1], "fw") == 0) {
445 addr = simple_strtoul(argv[2], NULL, 16);
446
447 if (!addr) {
448 printf("Invalid address\n");
449 return -EINVAL;
450 }
451
d3a6532c
WD
452 /*
453 * If a length was supplied, compare that with the 'length'
454 * field.
455 */
b8ec2385
TT
456
457 if (argc > 3) {
458 ulong length = simple_strtoul(argv[3], NULL, 16);
459 struct qe_firmware *firmware = (void *) addr;
460
461 if (length != be32_to_cpu(firmware->header.length)) {
462 printf("Length mismatch\n");
463 return -EINVAL;
464 }
465 }
466
467 return qe_upload_firmware((const struct qe_firmware *) addr);
468 }
469
47e26b1b 470 return cmd_usage(cmdtp);
b8ec2385
TT
471}
472
473U_BOOT_CMD(
474 qe, 4, 0, qe_cmd,
2fb2604d 475 "QUICC Engine commands",
b8ec2385 476 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
a89c33db
WD
477 "the QE,\n"
478 "\twith optional length <length> verification."
479);