]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/qe/qe.c
Make sure that argv[] argument pointers are not modified.
[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         0x04, 0x05, 0x0c, 0x0d,
117         0x14, 0x15, 0x1c, 0x1d,
118         0x24, 0x25, 0x2c, 0x2d,
119         0x34, 0x35, 0x88, 0x89,
120         0x98, 0x99, 0xa8, 0xa9,
121         0xb8, 0xb9, 0xc8, 0xc9,
122         0xd8, 0xd9, 0xe8, 0xe9,
123         0x08, 0x09, 0x18, 0x19,
124         0x28, 0x29, 0x38, 0x39,
125         0x48, 0x49, 0x58, 0x59,
126         0x68, 0x69, 0x78, 0x79,
127         0x80, 0x81
128 };
129
130 static void qe_snums_init(void)
131 {
132         int     i;
133
134         for (i = 0; i < QE_NUM_OF_SNUM; i++) {
135                 snums[i].state = QE_SNUM_STATE_FREE;
136                 snums[i].num   = thread_snum[i];
137         }
138 }
139
140 int qe_get_snum(void)
141 {
142         int     snum = -EBUSY;
143         int     i;
144
145         for (i = 0; i < QE_NUM_OF_SNUM; i++) {
146                 if (snums[i].state == QE_SNUM_STATE_FREE) {
147                         snums[i].state = QE_SNUM_STATE_USED;
148                         snum = snums[i].num;
149                         break;
150                 }
151         }
152
153         return snum;
154 }
155
156 void qe_put_snum(u8 snum)
157 {
158         int     i;
159
160         for (i = 0; i < QE_NUM_OF_SNUM; i++) {
161                 if (snums[i].num == snum) {
162                         snums[i].state = QE_SNUM_STATE_FREE;
163                         break;
164                 }
165         }
166 }
167
168 void qe_init(uint qe_base)
169 {
170         /* Init the QE IMMR base */
171         qe_immr = (qe_map_t *)qe_base;
172
173 #ifdef CONFIG_SYS_QE_FW_ADDR
174         /*
175          * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
176          */
177         qe_upload_firmware((const struct qe_firmware *) CONFIG_SYS_QE_FW_ADDR);
178
179         /* enable the microcode in IRAM */
180         out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
181 #endif
182
183         gd->mp_alloc_base = QE_DATAONLY_BASE;
184         gd->mp_alloc_top = gd->mp_alloc_base + QE_DATAONLY_SIZE;
185
186         qe_sdma_init();
187         qe_snums_init();
188 }
189
190 void qe_reset(void)
191 {
192         qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
193                          (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
194 }
195
196 void qe_assign_page(uint snum, uint para_ram_base)
197 {
198         u32     cecr;
199
200         out_be32(&qe_immr->cp.cecdr, para_ram_base);
201         out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
202                                          | QE_CR_FLG | QE_ASSIGN_PAGE);
203
204         /* Wait for the QE_CR_FLG to clear */
205         do {
206                 cecr = in_be32(&qe_immr->cp.cecr);
207         } while (cecr & QE_CR_FLG );
208
209         return;
210 }
211
212 /*
213  * brg: 0~15 as BRG1~BRG16
214    rate: baud rate
215  * BRG input clock comes from the BRGCLK (internal clock generated from
216    the QE clock, it is one-half of the QE clock), If need the clock source
217    from CLKn pin, we have te change the function.
218  */
219
220 #define BRG_CLK         (gd->brg_clk)
221
222 int qe_set_brg(uint brg, uint rate)
223 {
224         volatile uint   *bp;
225         u32             divisor;
226         int             div16 = 0;
227
228         if (brg >= QE_NUM_OF_BRGS)
229                 return -EINVAL;
230         bp = (uint *)&qe_immr->brg.brgc1;
231         bp += brg;
232
233         divisor = (BRG_CLK / rate);
234         if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
235                 div16 = 1;
236                 divisor /= 16;
237         }
238
239         *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
240         __asm__ __volatile__("sync");
241
242         if (div16) {
243                 *bp |= QE_BRGC_DIV16;
244                 __asm__ __volatile__("sync");
245         }
246
247         return 0;
248 }
249
250 /* Set ethernet MII clock master
251 */
252 int qe_set_mii_clk_src(int ucc_num)
253 {
254         u32     cmxgcr;
255
256         /* check if the UCC number is in range. */
257         if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) {
258                 printf("%s: ucc num not in ranges\n", __FUNCTION__);
259                 return -EINVAL;
260         }
261
262         cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
263         cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
264         cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT);
265         out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
266
267         return 0;
268 }
269
270 /* Firmware information stored here for qe_get_firmware_info() */
271 static struct qe_firmware_info qe_firmware_info;
272
273 /*
274  * Set to 1 if QE firmware has been uploaded, and therefore
275  * qe_firmware_info contains valid data.
276  */
277 static int qe_firmware_uploaded;
278
279 /*
280  * Upload a QE microcode
281  *
282  * This function is a worker function for qe_upload_firmware().  It does
283  * the actual uploading of the microcode.
284  */
285 static void qe_upload_microcode(const void *base,
286         const struct qe_microcode *ucode)
287 {
288         const u32 *code = base + be32_to_cpu(ucode->code_offset);
289         unsigned int i;
290
291         if (ucode->major || ucode->minor || ucode->revision)
292                 printf("QE: uploading microcode '%s' version %u.%u.%u\n",
293                         ucode->id, ucode->major, ucode->minor, ucode->revision);
294         else
295                 printf("QE: uploading microcode '%s'\n", ucode->id);
296
297         /* Use auto-increment */
298         out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
299                 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
300
301         for (i = 0; i < be32_to_cpu(ucode->count); i++)
302                 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
303 }
304
305 /*
306  * Upload a microcode to the I-RAM at a specific address.
307  *
308  * See docs/README.qe_firmware for information on QE microcode uploading.
309  *
310  * Currently, only version 1 is supported, so the 'version' field must be
311  * set to 1.
312  *
313  * The SOC model and revision are not validated, they are only displayed for
314  * informational purposes.
315  *
316  * 'calc_size' is the calculated size, in bytes, of the firmware structure and
317  * all of the microcode structures, minus the CRC.
318  *
319  * 'length' is the size that the structure says it is, including the CRC.
320  */
321 int qe_upload_firmware(const struct qe_firmware *firmware)
322 {
323         unsigned int i;
324         unsigned int j;
325         u32 crc;
326         size_t calc_size = sizeof(struct qe_firmware);
327         size_t length;
328         const struct qe_header *hdr;
329
330         if (!firmware) {
331                 printf("Invalid address\n");
332                 return -EINVAL;
333         }
334
335         hdr = &firmware->header;
336         length = be32_to_cpu(hdr->length);
337
338         /* Check the magic */
339         if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
340             (hdr->magic[2] != 'F')) {
341                 printf("Not a microcode\n");
342                 return -EPERM;
343         }
344
345         /* Check the version */
346         if (hdr->version != 1) {
347                 printf("Unsupported version\n");
348                 return -EPERM;
349         }
350
351         /* Validate some of the fields */
352         if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
353                 printf("Invalid data\n");
354                 return -EINVAL;
355         }
356
357         /* Validate the length and check if there's a CRC */
358         calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
359
360         for (i = 0; i < firmware->count; i++)
361                 /*
362                  * For situations where the second RISC uses the same microcode
363                  * as the first, the 'code_offset' and 'count' fields will be
364                  * zero, so it's okay to add those.
365                  */
366                 calc_size += sizeof(u32) *
367                         be32_to_cpu(firmware->microcode[i].count);
368
369         /* Validate the length */
370         if (length != calc_size + sizeof(u32)) {
371                 printf("Invalid length\n");
372                 return -EPERM;
373         }
374
375         /*
376          * Validate the CRC.  We would normally call crc32_no_comp(), but that
377          * function isn't available unless you turn on JFFS support.
378          */
379         crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
380         if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
381                 printf("Firmware CRC is invalid\n");
382                 return -EIO;
383         }
384
385         /*
386          * If the microcode calls for it, split the I-RAM.
387          */
388         if (!firmware->split) {
389                 out_be16(&qe_immr->cp.cercr,
390                         in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
391         }
392
393         if (firmware->soc.model)
394                 printf("Firmware '%s' for %u V%u.%u\n",
395                         firmware->id, be16_to_cpu(firmware->soc.model),
396                         firmware->soc.major, firmware->soc.minor);
397         else
398                 printf("Firmware '%s'\n", firmware->id);
399
400         /*
401          * The QE only supports one microcode per RISC, so clear out all the
402          * saved microcode information and put in the new.
403          */
404         memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
405         strcpy(qe_firmware_info.id, (char *)firmware->id);
406         qe_firmware_info.extended_modes = firmware->extended_modes;
407         memcpy(qe_firmware_info.vtraps, firmware->vtraps,
408                 sizeof(firmware->vtraps));
409         qe_firmware_uploaded = 1;
410
411         /* Loop through each microcode. */
412         for (i = 0; i < firmware->count; i++) {
413                 const struct qe_microcode *ucode = &firmware->microcode[i];
414
415                 /* Upload a microcode if it's present */
416                 if (ucode->code_offset)
417                         qe_upload_microcode(firmware, ucode);
418
419                 /* Program the traps for this processor */
420                 for (j = 0; j < 16; j++) {
421                         u32 trap = be32_to_cpu(ucode->traps[j]);
422
423                         if (trap)
424                                 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
425                 }
426
427                 /* Enable traps */
428                 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
429         }
430
431         return 0;
432 }
433
434 struct qe_firmware_info *qe_get_firmware_info(void)
435 {
436         return qe_firmware_uploaded ? &qe_firmware_info : NULL;
437 }
438
439 static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
440 {
441         ulong addr;
442
443         if (argc < 3) {
444                 cmd_usage(cmdtp);
445                 return 1;
446         }
447
448         if (strcmp(argv[1], "fw") == 0) {
449                 addr = simple_strtoul(argv[2], NULL, 16);
450
451                 if (!addr) {
452                         printf("Invalid address\n");
453                         return -EINVAL;
454                 }
455
456                 /*
457                  * If a length was supplied, compare that with the 'length'
458                  * field.
459                  */
460
461                 if (argc > 3) {
462                         ulong length = simple_strtoul(argv[3], NULL, 16);
463                         struct qe_firmware *firmware = (void *) addr;
464
465                         if (length != be32_to_cpu(firmware->header.length)) {
466                                 printf("Length mismatch\n");
467                                 return -EINVAL;
468                         }
469                 }
470
471                 return qe_upload_firmware((const struct qe_firmware *) addr);
472         }
473
474         cmd_usage(cmdtp);
475         return 1;
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 );