blob: cff550eec7e8d3054659d608c89405b0c1d658d4 [file] [log] [blame]
Li Yang98658532006-10-03 23:10:46 -05001/*
2 * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
3 *
4 * Authors: Shlomi Gridish <gridish@freescale.com>
5 * Li Yang <leoli@freescale.com>
6 * Based on cpm2_common.c from Dan Malek (dmalek@jlc.net)
7 *
8 * Description:
9 * General Purpose functions for the global management of the
10 * QUICC Engine (QE).
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17#include <linux/errno.h>
18#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/param.h>
21#include <linux/string.h>
22#include <linux/mm.h>
23#include <linux/interrupt.h>
24#include <linux/bootmem.h>
25#include <linux/module.h>
26#include <linux/delay.h>
27#include <linux/ioport.h>
Timur Tabibc556ba2008-01-08 10:30:58 -060028#include <linux/crc32.h>
Li Yang98658532006-10-03 23:10:46 -050029#include <asm/irq.h>
30#include <asm/page.h>
31#include <asm/pgtable.h>
32#include <asm/immap_qe.h>
33#include <asm/qe.h>
34#include <asm/prom.h>
35#include <asm/rheap.h>
36
37static void qe_snums_init(void);
38static void qe_muram_init(void);
39static int qe_sdma_init(void);
40
41static DEFINE_SPINLOCK(qe_lock);
42
43/* QE snum state */
44enum qe_snum_state {
45 QE_SNUM_STATE_USED,
46 QE_SNUM_STATE_FREE
47};
48
49/* QE snum */
50struct qe_snum {
51 u8 num;
52 enum qe_snum_state state;
53};
54
55/* We allocate this here because it is used almost exclusively for
56 * the communication processor devices.
57 */
Anton Vorontsov0b51b022008-03-11 20:24:13 +030058struct qe_immap __iomem *qe_immr;
Li Yang98658532006-10-03 23:10:46 -050059EXPORT_SYMBOL(qe_immr);
60
61static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
62
63static phys_addr_t qebase = -1;
64
65phys_addr_t get_qe_base(void)
66{
67 struct device_node *qe;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +030068 unsigned int size;
Anton Vorontsovd8985fd2008-02-04 16:46:17 +030069 const u32 *prop;
Li Yang98658532006-10-03 23:10:46 -050070
71 if (qebase != -1)
72 return qebase;
73
Anton Vorontsova2dd70a2008-01-24 18:39:59 +030074 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
75 if (!qe) {
76 qe = of_find_node_by_type(NULL, "qe");
77 if (!qe)
78 return qebase;
79 }
80
81 prop = of_get_property(qe, "reg", &size);
Anton Vorontsovd8985fd2008-02-04 16:46:17 +030082 if (prop && size >= sizeof(*prop))
83 qebase = of_translate_address(qe, prop);
Anton Vorontsova2dd70a2008-01-24 18:39:59 +030084 of_node_put(qe);
Li Yang98658532006-10-03 23:10:46 -050085
86 return qebase;
87}
88
89EXPORT_SYMBOL(get_qe_base);
90
91void qe_reset(void)
92{
93 if (qe_immr == NULL)
94 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
95
96 qe_snums_init();
97
98 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
99 QE_CR_PROTOCOL_UNSPECIFIED, 0);
100
101 /* Reclaim the MURAM memory for our use. */
102 qe_muram_init();
103
104 if (qe_sdma_init())
105 panic("sdma init failed!");
106}
107
108int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
109{
110 unsigned long flags;
111 u8 mcn_shift = 0, dev_shift = 0;
112
113 spin_lock_irqsave(&qe_lock, flags);
114 if (cmd == QE_RESET) {
115 out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
116 } else {
117 if (cmd == QE_ASSIGN_PAGE) {
118 /* Here device is the SNUM, not sub-block */
119 dev_shift = QE_CR_SNUM_SHIFT;
120 } else if (cmd == QE_ASSIGN_RISC) {
121 /* Here device is the SNUM, and mcnProtocol is
122 * e_QeCmdRiscAssignment value */
123 dev_shift = QE_CR_SNUM_SHIFT;
124 mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
125 } else {
126 if (device == QE_CR_SUBBLOCK_USB)
127 mcn_shift = QE_CR_MCN_USB_SHIFT;
128 else
129 mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
130 }
131
Timur Tabi302439d2006-10-31 17:53:42 +0800132 out_be32(&qe_immr->cp.cecdr, cmd_input);
Li Yang98658532006-10-03 23:10:46 -0500133 out_be32(&qe_immr->cp.cecr,
134 (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
135 mcn_protocol << mcn_shift));
136 }
137
138 /* wait for the QE_CR_FLG to clear */
139 while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG)
140 cpu_relax();
141 spin_unlock_irqrestore(&qe_lock, flags);
142
143 return 0;
144}
145EXPORT_SYMBOL(qe_issue_cmd);
146
147/* Set a baud rate generator. This needs lots of work. There are
148 * 16 BRGs, which can be connected to the QE channels or output
149 * as clocks. The BRGs are in two different block of internal
150 * memory mapped space.
Timur Tabi6b0b5942007-10-03 11:34:59 -0500151 * The BRG clock is the QE clock divided by 2.
Li Yang98658532006-10-03 23:10:46 -0500152 * It was set up long ago during the initial boot phase and is
153 * is given to us.
154 * Baud rate clocks are zero-based in the driver code (as that maps
155 * to port numbers). Documentation uses 1-based numbering.
156 */
157static unsigned int brg_clk = 0;
158
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300159unsigned int qe_get_brg_clk(void)
Li Yang98658532006-10-03 23:10:46 -0500160{
161 struct device_node *qe;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300162 unsigned int size;
163 const u32 *prop;
164
Li Yang98658532006-10-03 23:10:46 -0500165 if (brg_clk)
166 return brg_clk;
167
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300168 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
169 if (!qe) {
170 qe = of_find_node_by_type(NULL, "qe");
171 if (!qe)
172 return brg_clk;
173 }
174
175 prop = of_get_property(qe, "brg-frequency", &size);
Anton Vorontsovd8985fd2008-02-04 16:46:17 +0300176 if (prop && size == sizeof(*prop))
177 brg_clk = *prop;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300178
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300179 of_node_put(qe);
180
Li Yang98658532006-10-03 23:10:46 -0500181 return brg_clk;
182}
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300183EXPORT_SYMBOL(qe_get_brg_clk);
Li Yang98658532006-10-03 23:10:46 -0500184
Timur Tabi6b0b5942007-10-03 11:34:59 -0500185/* Program the BRG to the given sampling rate and multiplier
186 *
Timur Tabi7264ec42007-11-29 17:26:30 -0600187 * @brg: the BRG, QE_BRG1 - QE_BRG16
Timur Tabi6b0b5942007-10-03 11:34:59 -0500188 * @rate: the desired sampling rate
189 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
190 * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
191 * then 'multiplier' should be 8.
Li Yang98658532006-10-03 23:10:46 -0500192 */
Timur Tabi7264ec42007-11-29 17:26:30 -0600193int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
Li Yang98658532006-10-03 23:10:46 -0500194{
Li Yang98658532006-10-03 23:10:46 -0500195 u32 divisor, tempval;
Timur Tabi6b0b5942007-10-03 11:34:59 -0500196 u32 div16 = 0;
Li Yang98658532006-10-03 23:10:46 -0500197
Timur Tabi7264ec42007-11-29 17:26:30 -0600198 if ((brg < QE_BRG1) || (brg > QE_BRG16))
199 return -EINVAL;
200
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300201 divisor = qe_get_brg_clk() / (rate * multiplier);
Li Yang98658532006-10-03 23:10:46 -0500202
Li Yang98658532006-10-03 23:10:46 -0500203 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
Timur Tabi6b0b5942007-10-03 11:34:59 -0500204 div16 = QE_BRGC_DIV16;
Li Yang98658532006-10-03 23:10:46 -0500205 divisor /= 16;
206 }
207
Timur Tabi6b0b5942007-10-03 11:34:59 -0500208 /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
209 that the BRG divisor must be even if you're not using divide-by-16
210 mode. */
211 if (!div16 && (divisor & 1))
212 divisor++;
Li Yang98658532006-10-03 23:10:46 -0500213
Timur Tabi6b0b5942007-10-03 11:34:59 -0500214 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
215 QE_BRGC_ENABLE | div16;
216
Timur Tabi7264ec42007-11-29 17:26:30 -0600217 out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
218
219 return 0;
Li Yang98658532006-10-03 23:10:46 -0500220}
Timur Tabi7264ec42007-11-29 17:26:30 -0600221EXPORT_SYMBOL(qe_setbrg);
Li Yang98658532006-10-03 23:10:46 -0500222
Timur Tabi174b0da2007-12-03 15:17:58 -0600223/* Convert a string to a QE clock source enum
224 *
225 * This function takes a string, typically from a property in the device
226 * tree, and returns the corresponding "enum qe_clock" value.
227*/
228enum qe_clock qe_clock_source(const char *source)
229{
230 unsigned int i;
231
232 if (strcasecmp(source, "none") == 0)
233 return QE_CLK_NONE;
234
235 if (strncasecmp(source, "brg", 3) == 0) {
236 i = simple_strtoul(source + 3, NULL, 10);
237 if ((i >= 1) && (i <= 16))
238 return (QE_BRG1 - 1) + i;
239 else
240 return QE_CLK_DUMMY;
241 }
242
243 if (strncasecmp(source, "clk", 3) == 0) {
244 i = simple_strtoul(source + 3, NULL, 10);
245 if ((i >= 1) && (i <= 24))
246 return (QE_CLK1 - 1) + i;
247 else
248 return QE_CLK_DUMMY;
249 }
250
251 return QE_CLK_DUMMY;
252}
253EXPORT_SYMBOL(qe_clock_source);
254
Li Yang98658532006-10-03 23:10:46 -0500255/* Initialize SNUMs (thread serial numbers) according to
256 * QE Module Control chapter, SNUM table
257 */
258static void qe_snums_init(void)
259{
260 int i;
261 static const u8 snum_init[] = {
262 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
263 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
264 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
265 0xD8, 0xD9, 0xE8, 0xE9,
266 };
267
268 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
269 snums[i].num = snum_init[i];
270 snums[i].state = QE_SNUM_STATE_FREE;
271 }
272}
273
274int qe_get_snum(void)
275{
276 unsigned long flags;
277 int snum = -EBUSY;
278 int i;
279
280 spin_lock_irqsave(&qe_lock, flags);
281 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
282 if (snums[i].state == QE_SNUM_STATE_FREE) {
283 snums[i].state = QE_SNUM_STATE_USED;
284 snum = snums[i].num;
285 break;
286 }
287 }
288 spin_unlock_irqrestore(&qe_lock, flags);
289
290 return snum;
291}
292EXPORT_SYMBOL(qe_get_snum);
293
294void qe_put_snum(u8 snum)
295{
296 int i;
297
298 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
299 if (snums[i].num == snum) {
300 snums[i].state = QE_SNUM_STATE_FREE;
301 break;
302 }
303 }
304}
305EXPORT_SYMBOL(qe_put_snum);
306
307static int qe_sdma_init(void)
308{
309 struct sdma *sdma = &qe_immr->sdma;
Timur Tabi4c356302007-05-08 14:46:36 -0500310 unsigned long sdma_buf_offset;
Li Yang98658532006-10-03 23:10:46 -0500311
312 if (!sdma)
313 return -ENODEV;
314
315 /* allocate 2 internal temporary buffers (512 bytes size each) for
316 * the SDMA */
Chuck Meade7f013bc2007-03-27 10:46:10 -0400317 sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
Timur Tabi4c356302007-05-08 14:46:36 -0500318 if (IS_ERR_VALUE(sdma_buf_offset))
Li Yang98658532006-10-03 23:10:46 -0500319 return -ENOMEM;
320
Timur Tabi4c356302007-05-08 14:46:36 -0500321 out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
Chuck Meade7f013bc2007-03-27 10:46:10 -0400322 out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
323 (0x1 << QE_SDMR_CEN_SHIFT)));
Li Yang98658532006-10-03 23:10:46 -0500324
325 return 0;
326}
327
328/*
329 * muram_alloc / muram_free bits.
330 */
331static DEFINE_SPINLOCK(qe_muram_lock);
332
333/* 16 blocks should be enough to satisfy all requests
334 * until the memory subsystem goes up... */
335static rh_block_t qe_boot_muram_rh_block[16];
336static rh_info_t qe_muram_info;
337
338static void qe_muram_init(void)
339{
340 struct device_node *np;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300341 const u32 *address;
Li Yang98658532006-10-03 23:10:46 -0500342 u64 size;
343 unsigned int flags;
344
345 /* initialize the info header */
346 rh_init(&qe_muram_info, 1,
347 sizeof(qe_boot_muram_rh_block) /
348 sizeof(qe_boot_muram_rh_block[0]), qe_boot_muram_rh_block);
349
350 /* Attach the usable muram area */
351 /* XXX: This is a subset of the available muram. It
352 * varies with the processor and the microcode patches activated.
353 */
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300354 np = of_find_compatible_node(NULL, NULL, "fsl,qe-muram-data");
355 if (!np) {
356 np = of_find_node_by_name(NULL, "data-only");
357 if (!np) {
358 WARN_ON(1);
359 return;
360 }
Li Yang98658532006-10-03 23:10:46 -0500361 }
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300362
363 address = of_get_address(np, 0, &size, &flags);
364 WARN_ON(!address);
365
366 of_node_put(np);
367 if (address)
368 rh_attach_region(&qe_muram_info, *address, (int)size);
Li Yang98658532006-10-03 23:10:46 -0500369}
370
371/* This function returns an index into the MURAM area.
372 */
Timur Tabi4c356302007-05-08 14:46:36 -0500373unsigned long qe_muram_alloc(int size, int align)
Li Yang98658532006-10-03 23:10:46 -0500374{
Timur Tabi4c356302007-05-08 14:46:36 -0500375 unsigned long start;
Li Yang98658532006-10-03 23:10:46 -0500376 unsigned long flags;
377
378 spin_lock_irqsave(&qe_muram_lock, flags);
379 start = rh_alloc_align(&qe_muram_info, size, align, "QE");
380 spin_unlock_irqrestore(&qe_muram_lock, flags);
381
Timur Tabi4c356302007-05-08 14:46:36 -0500382 return start;
Li Yang98658532006-10-03 23:10:46 -0500383}
384EXPORT_SYMBOL(qe_muram_alloc);
385
Timur Tabi4c356302007-05-08 14:46:36 -0500386int qe_muram_free(unsigned long offset)
Li Yang98658532006-10-03 23:10:46 -0500387{
388 int ret;
389 unsigned long flags;
390
391 spin_lock_irqsave(&qe_muram_lock, flags);
Timur Tabi4c356302007-05-08 14:46:36 -0500392 ret = rh_free(&qe_muram_info, offset);
Li Yang98658532006-10-03 23:10:46 -0500393 spin_unlock_irqrestore(&qe_muram_lock, flags);
394
395 return ret;
396}
397EXPORT_SYMBOL(qe_muram_free);
398
399/* not sure if this is ever needed */
Timur Tabi4c356302007-05-08 14:46:36 -0500400unsigned long qe_muram_alloc_fixed(unsigned long offset, int size)
Li Yang98658532006-10-03 23:10:46 -0500401{
Timur Tabi4c356302007-05-08 14:46:36 -0500402 unsigned long start;
Li Yang98658532006-10-03 23:10:46 -0500403 unsigned long flags;
404
405 spin_lock_irqsave(&qe_muram_lock, flags);
Timur Tabi4c356302007-05-08 14:46:36 -0500406 start = rh_alloc_fixed(&qe_muram_info, offset, size, "commproc");
Li Yang98658532006-10-03 23:10:46 -0500407 spin_unlock_irqrestore(&qe_muram_lock, flags);
408
Timur Tabi4c356302007-05-08 14:46:36 -0500409 return start;
Li Yang98658532006-10-03 23:10:46 -0500410}
411EXPORT_SYMBOL(qe_muram_alloc_fixed);
412
413void qe_muram_dump(void)
414{
415 rh_dump(&qe_muram_info);
416}
417EXPORT_SYMBOL(qe_muram_dump);
418
Timur Tabibc556ba2008-01-08 10:30:58 -0600419/* The maximum number of RISCs we support */
420#define MAX_QE_RISC 2
421
422/* Firmware information stored here for qe_get_firmware_info() */
423static struct qe_firmware_info qe_firmware_info;
424
425/*
426 * Set to 1 if QE firmware has been uploaded, and therefore
427 * qe_firmware_info contains valid data.
428 */
429static int qe_firmware_uploaded;
430
431/*
432 * Upload a QE microcode
433 *
434 * This function is a worker function for qe_upload_firmware(). It does
435 * the actual uploading of the microcode.
436 */
437static void qe_upload_microcode(const void *base,
438 const struct qe_microcode *ucode)
439{
440 const __be32 *code = base + be32_to_cpu(ucode->code_offset);
441 unsigned int i;
442
443 if (ucode->major || ucode->minor || ucode->revision)
444 printk(KERN_INFO "qe-firmware: "
445 "uploading microcode '%s' version %u.%u.%u\n",
446 ucode->id, ucode->major, ucode->minor, ucode->revision);
447 else
448 printk(KERN_INFO "qe-firmware: "
449 "uploading microcode '%s'\n", ucode->id);
450
451 /* Use auto-increment */
452 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
453 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
454
455 for (i = 0; i < be32_to_cpu(ucode->count); i++)
456 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
457}
458
459/*
460 * Upload a microcode to the I-RAM at a specific address.
461 *
462 * See Documentation/powerpc/qe-firmware.txt for information on QE microcode
463 * uploading.
464 *
465 * Currently, only version 1 is supported, so the 'version' field must be
466 * set to 1.
467 *
468 * The SOC model and revision are not validated, they are only displayed for
469 * informational purposes.
470 *
471 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
472 * all of the microcode structures, minus the CRC.
473 *
474 * 'length' is the size that the structure says it is, including the CRC.
475 */
476int qe_upload_firmware(const struct qe_firmware *firmware)
477{
478 unsigned int i;
479 unsigned int j;
480 u32 crc;
481 size_t calc_size = sizeof(struct qe_firmware);
482 size_t length;
483 const struct qe_header *hdr;
484
485 if (!firmware) {
486 printk(KERN_ERR "qe-firmware: invalid pointer\n");
487 return -EINVAL;
488 }
489
490 hdr = &firmware->header;
491 length = be32_to_cpu(hdr->length);
492
493 /* Check the magic */
494 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
495 (hdr->magic[2] != 'F')) {
496 printk(KERN_ERR "qe-firmware: not a microcode\n");
497 return -EPERM;
498 }
499
500 /* Check the version */
501 if (hdr->version != 1) {
502 printk(KERN_ERR "qe-firmware: unsupported version\n");
503 return -EPERM;
504 }
505
506 /* Validate some of the fields */
Timur Tabi6f913162008-03-03 11:11:30 -0600507 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabibc556ba2008-01-08 10:30:58 -0600508 printk(KERN_ERR "qe-firmware: invalid data\n");
509 return -EINVAL;
510 }
511
512 /* Validate the length and check if there's a CRC */
513 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
514
515 for (i = 0; i < firmware->count; i++)
516 /*
517 * For situations where the second RISC uses the same microcode
518 * as the first, the 'code_offset' and 'count' fields will be
519 * zero, so it's okay to add those.
520 */
521 calc_size += sizeof(__be32) *
522 be32_to_cpu(firmware->microcode[i].count);
523
524 /* Validate the length */
525 if (length != calc_size + sizeof(__be32)) {
526 printk(KERN_ERR "qe-firmware: invalid length\n");
527 return -EPERM;
528 }
529
530 /* Validate the CRC */
531 crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
532 if (crc != crc32(0, firmware, calc_size)) {
533 printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
534 return -EIO;
535 }
536
537 /*
538 * If the microcode calls for it, split the I-RAM.
539 */
540 if (!firmware->split)
541 setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
542
543 if (firmware->soc.model)
544 printk(KERN_INFO
545 "qe-firmware: firmware '%s' for %u V%u.%u\n",
546 firmware->id, be16_to_cpu(firmware->soc.model),
547 firmware->soc.major, firmware->soc.minor);
548 else
549 printk(KERN_INFO "qe-firmware: firmware '%s'\n",
550 firmware->id);
551
552 /*
553 * The QE only supports one microcode per RISC, so clear out all the
554 * saved microcode information and put in the new.
555 */
556 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
557 strcpy(qe_firmware_info.id, firmware->id);
558 qe_firmware_info.extended_modes = firmware->extended_modes;
559 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
560 sizeof(firmware->vtraps));
561
562 /* Loop through each microcode. */
563 for (i = 0; i < firmware->count; i++) {
564 const struct qe_microcode *ucode = &firmware->microcode[i];
565
566 /* Upload a microcode if it's present */
567 if (ucode->code_offset)
568 qe_upload_microcode(firmware, ucode);
569
570 /* Program the traps for this processor */
571 for (j = 0; j < 16; j++) {
572 u32 trap = be32_to_cpu(ucode->traps[j]);
573
574 if (trap)
575 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
576 }
577
578 /* Enable traps */
579 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
580 }
581
582 qe_firmware_uploaded = 1;
583
584 return 0;
585}
586EXPORT_SYMBOL(qe_upload_firmware);
587
588/*
589 * Get info on the currently-loaded firmware
590 *
591 * This function also checks the device tree to see if the boot loader has
592 * uploaded a firmware already.
593 */
594struct qe_firmware_info *qe_get_firmware_info(void)
595{
596 static int initialized;
597 struct property *prop;
598 struct device_node *qe;
599 struct device_node *fw = NULL;
600 const char *sprop;
601 unsigned int i;
602
603 /*
604 * If we haven't checked yet, and a driver hasn't uploaded a firmware
605 * yet, then check the device tree for information.
606 */
Ionut Nicu86f4e5d2008-03-07 19:27:59 +0200607 if (qe_firmware_uploaded)
608 return &qe_firmware_info;
609
610 if (initialized)
Timur Tabibc556ba2008-01-08 10:30:58 -0600611 return NULL;
612
613 initialized = 1;
614
615 /*
616 * Newer device trees have an "fsl,qe" compatible property for the QE
617 * node, but we still need to support older device trees.
618 */
619 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
620 if (!qe) {
621 qe = of_find_node_by_type(NULL, "qe");
622 if (!qe)
623 return NULL;
624 }
625
626 /* Find the 'firmware' child node */
627 for_each_child_of_node(qe, fw) {
628 if (strcmp(fw->name, "firmware") == 0)
629 break;
630 }
631
632 of_node_put(qe);
633
634 /* Did we find the 'firmware' node? */
635 if (!fw)
636 return NULL;
637
638 qe_firmware_uploaded = 1;
639
640 /* Copy the data into qe_firmware_info*/
641 sprop = of_get_property(fw, "id", NULL);
642 if (sprop)
643 strncpy(qe_firmware_info.id, sprop,
644 sizeof(qe_firmware_info.id) - 1);
645
646 prop = of_find_property(fw, "extended-modes", NULL);
647 if (prop && (prop->length == sizeof(u64))) {
648 const u64 *iprop = prop->value;
649
650 qe_firmware_info.extended_modes = *iprop;
651 }
652
653 prop = of_find_property(fw, "virtual-traps", NULL);
654 if (prop && (prop->length == 32)) {
655 const u32 *iprop = prop->value;
656
657 for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
658 qe_firmware_info.vtraps[i] = iprop[i];
659 }
660
661 of_node_put(fw);
662
663 return &qe_firmware_info;
664}
665EXPORT_SYMBOL(qe_get_firmware_info);
666