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