]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/qe/qe.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[people/ms/u-boot.git] / drivers / qe / qe.c
1 /*
2 * Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
3 *
4 * Dave Liu <daveliu@freescale.com>
5 * based on source code of Shlomi Gridish
6 *
7 * SPDX-License-Identifier: GPL-2.0+
8 */
9
10 #include "common.h"
11 #include <command.h>
12 #include "asm/errno.h"
13 #include "asm/io.h"
14 #include "linux/immap_qe.h"
15 #include "qe.h"
16
17 #define MPC85xx_DEVDISR_QE_DISABLE 0x1
18
19 qe_map_t *qe_immr = NULL;
20 static qe_snum_t snums[QE_NUM_OF_SNUM];
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
25 {
26 u32 cecr;
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
43 uint qe_muram_alloc(uint size, uint align)
44 {
45 uint retloc;
46 uint align_mask, off;
47 uint savebase;
48
49 align_mask = align - 1;
50 savebase = gd->arch.mp_alloc_base;
51
52 off = gd->arch.mp_alloc_base & align_mask;
53 if (off != 0)
54 gd->arch.mp_alloc_base += (align - off);
55
56 if ((off = size & align_mask) != 0)
57 size += (align - off);
58
59 if ((gd->arch.mp_alloc_base + size) >= gd->arch.mp_alloc_top) {
60 gd->arch.mp_alloc_base = savebase;
61 printf("%s: ran out of ram.\n", __FUNCTION__);
62 }
63
64 retloc = gd->arch.mp_alloc_base;
65 gd->arch.mp_alloc_base += size;
66
67 memset((void *)&qe_immr->muram[retloc], 0, size);
68
69 __asm__ __volatile__("sync");
70
71 return retloc;
72 }
73
74 void *qe_muram_addr(uint offset)
75 {
76 return (void *)&qe_immr->muram[offset];
77 }
78
79 static 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 */
91 sdma_buffer_base = qe_muram_alloc(2048, 4096);
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
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 */
105 static u8 thread_snum[] = {
106 /* Evthreads 16-29 are not supported in MPC8309 */
107 #if !defined(CONFIG_MPC8309)
108 0x04, 0x05, 0x0c, 0x0d,
109 0x14, 0x15, 0x1c, 0x1d,
110 0x24, 0x25, 0x2c, 0x2d,
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
121 };
122
123 static 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
133 int 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
149 void 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
161 void qe_init(uint qe_base)
162 {
163 /* Init the QE IMMR base */
164 qe_immr = (qe_map_t *)qe_base;
165
166 #ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
167 /*
168 * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
169 */
170 qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
171
172 /* enable the microcode in IRAM */
173 out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
174 #endif
175
176 gd->arch.mp_alloc_base = QE_DATAONLY_BASE;
177 gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;
178
179 qe_sdma_init();
180 qe_snums_init();
181 }
182
183 void qe_reset(void)
184 {
185 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
186 (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
187 }
188
189 void 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
213 #define BRG_CLK (gd->arch.brg_clk)
214
215 int qe_set_brg(uint brg, uint rate)
216 {
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 */
245 int 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
263 /* Firmware information stored here for qe_get_firmware_info() */
264 static 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 */
270 static 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 */
278 static 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 */
314 int 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;
322 #ifdef CONFIG_DEEP_SLEEP
323 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
324 #endif
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')) {
336 printf("QE microcode not found\n");
337 #ifdef CONFIG_DEEP_SLEEP
338 setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
339 #endif
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 */
350 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
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
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 */
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));
403 strcpy(qe_firmware_info.id, (char *)firmware->id);
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
432 struct qe_firmware_info *qe_get_firmware_info(void)
433 {
434 return qe_firmware_uploaded ? &qe_firmware_info : NULL;
435 }
436
437 static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
438 {
439 ulong addr;
440
441 if (argc < 3)
442 return cmd_usage(cmdtp);
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
452 /*
453 * If a length was supplied, compare that with the 'length'
454 * field.
455 */
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
470 return cmd_usage(cmdtp);
471 }
472
473 U_BOOT_CMD(
474 qe, 4, 0, qe_cmd,
475 "QUICC Engine commands",
476 "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
477 "the QE,\n"
478 "\twith optional length <length> verification."
479 );