blob: fff2701b90dfaf6469139fb1a44649720ce6a405 [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>
Anton Vorontsov09a3fba2008-11-11 18:31:39 +030022#include <linux/spinlock.h>
Li Yang98658532006-10-03 23:10:46 -050023#include <linux/mm.h>
24#include <linux/interrupt.h>
25#include <linux/bootmem.h>
26#include <linux/module.h>
27#include <linux/delay.h>
28#include <linux/ioport.h>
Timur Tabibc556ba2008-01-08 10:30:58 -060029#include <linux/crc32.h>
Li Yang98658532006-10-03 23:10:46 -050030#include <asm/irq.h>
31#include <asm/page.h>
32#include <asm/pgtable.h>
33#include <asm/immap_qe.h>
34#include <asm/qe.h>
35#include <asm/prom.h>
36#include <asm/rheap.h>
37
38static void qe_snums_init(void);
Li Yang98658532006-10-03 23:10:46 -050039static int qe_sdma_init(void);
40
41static DEFINE_SPINLOCK(qe_lock);
Anton Vorontsov09a3fba2008-11-11 18:31:39 +030042DEFINE_SPINLOCK(cmxgcr_lock);
43EXPORT_SYMBOL(cmxgcr_lock);
Li Yang98658532006-10-03 23:10:46 -050044
45/* QE snum state */
46enum qe_snum_state {
47 QE_SNUM_STATE_USED,
48 QE_SNUM_STATE_FREE
49};
50
51/* QE snum */
52struct qe_snum {
53 u8 num;
54 enum qe_snum_state state;
55};
56
57/* We allocate this here because it is used almost exclusively for
58 * the communication processor devices.
59 */
Anton Vorontsov0b51b022008-03-11 20:24:13 +030060struct qe_immap __iomem *qe_immr;
Li Yang98658532006-10-03 23:10:46 -050061EXPORT_SYMBOL(qe_immr);
62
63static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
Haiying Wang98ca77a2009-05-01 15:40:48 -040064static unsigned int qe_num_of_snum;
Li Yang98658532006-10-03 23:10:46 -050065
66static phys_addr_t qebase = -1;
67
Anton Vorontsoved241572009-08-27 07:35:50 +000068int qe_alive_during_sleep(void)
69{
70 static int ret = -1;
71
72 if (ret != -1)
73 return ret;
74
75 ret = !of_find_compatible_node(NULL, NULL, "fsl,mpc8569-pmc");
76
77 return ret;
78}
79EXPORT_SYMBOL(qe_alive_during_sleep);
80
Li Yang98658532006-10-03 23:10:46 -050081phys_addr_t get_qe_base(void)
82{
83 struct device_node *qe;
Andy Fleming7e1cc9c2008-05-07 13:19:44 -050084 int size;
Anton Vorontsovd8985fd2008-02-04 16:46:17 +030085 const u32 *prop;
Li Yang98658532006-10-03 23:10:46 -050086
87 if (qebase != -1)
88 return qebase;
89
Anton Vorontsova2dd70a2008-01-24 18:39:59 +030090 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
91 if (!qe) {
92 qe = of_find_node_by_type(NULL, "qe");
93 if (!qe)
94 return qebase;
95 }
96
97 prop = of_get_property(qe, "reg", &size);
Anton Vorontsovd8985fd2008-02-04 16:46:17 +030098 if (prop && size >= sizeof(*prop))
99 qebase = of_translate_address(qe, prop);
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300100 of_node_put(qe);
Li Yang98658532006-10-03 23:10:46 -0500101
102 return qebase;
103}
104
105EXPORT_SYMBOL(get_qe_base);
106
Anton Vorontsov5848f162008-06-11 16:32:48 +0400107void __init qe_reset(void)
Li Yang98658532006-10-03 23:10:46 -0500108{
109 if (qe_immr == NULL)
110 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
111
112 qe_snums_init();
113
114 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
115 QE_CR_PROTOCOL_UNSPECIFIED, 0);
116
117 /* Reclaim the MURAM memory for our use. */
118 qe_muram_init();
119
120 if (qe_sdma_init())
121 panic("sdma init failed!");
122}
123
124int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
125{
126 unsigned long flags;
127 u8 mcn_shift = 0, dev_shift = 0;
Timur Tabif49156ea2009-05-26 10:21:42 -0500128 u32 ret;
Li Yang98658532006-10-03 23:10:46 -0500129
130 spin_lock_irqsave(&qe_lock, flags);
131 if (cmd == QE_RESET) {
132 out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
133 } else {
134 if (cmd == QE_ASSIGN_PAGE) {
135 /* Here device is the SNUM, not sub-block */
136 dev_shift = QE_CR_SNUM_SHIFT;
137 } else if (cmd == QE_ASSIGN_RISC) {
138 /* Here device is the SNUM, and mcnProtocol is
139 * e_QeCmdRiscAssignment value */
140 dev_shift = QE_CR_SNUM_SHIFT;
141 mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
142 } else {
143 if (device == QE_CR_SUBBLOCK_USB)
144 mcn_shift = QE_CR_MCN_USB_SHIFT;
145 else
146 mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
147 }
148
Timur Tabi302439d2006-10-31 17:53:42 +0800149 out_be32(&qe_immr->cp.cecdr, cmd_input);
Li Yang98658532006-10-03 23:10:46 -0500150 out_be32(&qe_immr->cp.cecr,
151 (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
152 mcn_protocol << mcn_shift));
153 }
154
155 /* wait for the QE_CR_FLG to clear */
Timur Tabif49156ea2009-05-26 10:21:42 -0500156 ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
157 100, 0);
158 /* On timeout (e.g. failure), the expression will be false (ret == 0),
159 otherwise it will be true (ret == 1). */
Li Yang98658532006-10-03 23:10:46 -0500160 spin_unlock_irqrestore(&qe_lock, flags);
161
Timur Tabif49156ea2009-05-26 10:21:42 -0500162 return ret == 1;
Li Yang98658532006-10-03 23:10:46 -0500163}
164EXPORT_SYMBOL(qe_issue_cmd);
165
166/* Set a baud rate generator. This needs lots of work. There are
167 * 16 BRGs, which can be connected to the QE channels or output
168 * as clocks. The BRGs are in two different block of internal
169 * memory mapped space.
Timur Tabi6b0b5942007-10-03 11:34:59 -0500170 * The BRG clock is the QE clock divided by 2.
Li Yang98658532006-10-03 23:10:46 -0500171 * It was set up long ago during the initial boot phase and is
172 * is given to us.
173 * Baud rate clocks are zero-based in the driver code (as that maps
174 * to port numbers). Documentation uses 1-based numbering.
175 */
176static unsigned int brg_clk = 0;
177
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300178unsigned int qe_get_brg_clk(void)
Li Yang98658532006-10-03 23:10:46 -0500179{
180 struct device_node *qe;
Andy Fleming7e1cc9c2008-05-07 13:19:44 -0500181 int size;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300182 const u32 *prop;
183
Li Yang98658532006-10-03 23:10:46 -0500184 if (brg_clk)
185 return brg_clk;
186
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300187 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
188 if (!qe) {
189 qe = of_find_node_by_type(NULL, "qe");
190 if (!qe)
191 return brg_clk;
192 }
193
194 prop = of_get_property(qe, "brg-frequency", &size);
Anton Vorontsovd8985fd2008-02-04 16:46:17 +0300195 if (prop && size == sizeof(*prop))
196 brg_clk = *prop;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300197
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300198 of_node_put(qe);
199
Li Yang98658532006-10-03 23:10:46 -0500200 return brg_clk;
201}
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300202EXPORT_SYMBOL(qe_get_brg_clk);
Li Yang98658532006-10-03 23:10:46 -0500203
Timur Tabi6b0b5942007-10-03 11:34:59 -0500204/* Program the BRG to the given sampling rate and multiplier
205 *
Timur Tabi7264ec42007-11-29 17:26:30 -0600206 * @brg: the BRG, QE_BRG1 - QE_BRG16
Timur Tabi6b0b5942007-10-03 11:34:59 -0500207 * @rate: the desired sampling rate
208 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
209 * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
210 * then 'multiplier' should be 8.
Li Yang98658532006-10-03 23:10:46 -0500211 */
Timur Tabi7264ec42007-11-29 17:26:30 -0600212int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
Li Yang98658532006-10-03 23:10:46 -0500213{
Li Yang98658532006-10-03 23:10:46 -0500214 u32 divisor, tempval;
Timur Tabi6b0b5942007-10-03 11:34:59 -0500215 u32 div16 = 0;
Li Yang98658532006-10-03 23:10:46 -0500216
Timur Tabi7264ec42007-11-29 17:26:30 -0600217 if ((brg < QE_BRG1) || (brg > QE_BRG16))
218 return -EINVAL;
219
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300220 divisor = qe_get_brg_clk() / (rate * multiplier);
Li Yang98658532006-10-03 23:10:46 -0500221
Li Yang98658532006-10-03 23:10:46 -0500222 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
Timur Tabi6b0b5942007-10-03 11:34:59 -0500223 div16 = QE_BRGC_DIV16;
Li Yang98658532006-10-03 23:10:46 -0500224 divisor /= 16;
225 }
226
Timur Tabi6b0b5942007-10-03 11:34:59 -0500227 /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
228 that the BRG divisor must be even if you're not using divide-by-16
229 mode. */
230 if (!div16 && (divisor & 1))
231 divisor++;
Li Yang98658532006-10-03 23:10:46 -0500232
Timur Tabi6b0b5942007-10-03 11:34:59 -0500233 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
234 QE_BRGC_ENABLE | div16;
235
Timur Tabi7264ec42007-11-29 17:26:30 -0600236 out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
237
238 return 0;
Li Yang98658532006-10-03 23:10:46 -0500239}
Timur Tabi7264ec42007-11-29 17:26:30 -0600240EXPORT_SYMBOL(qe_setbrg);
Li Yang98658532006-10-03 23:10:46 -0500241
Timur Tabi174b0da2007-12-03 15:17:58 -0600242/* Convert a string to a QE clock source enum
243 *
244 * This function takes a string, typically from a property in the device
245 * tree, and returns the corresponding "enum qe_clock" value.
246*/
247enum qe_clock qe_clock_source(const char *source)
248{
249 unsigned int i;
250
251 if (strcasecmp(source, "none") == 0)
252 return QE_CLK_NONE;
253
254 if (strncasecmp(source, "brg", 3) == 0) {
255 i = simple_strtoul(source + 3, NULL, 10);
256 if ((i >= 1) && (i <= 16))
257 return (QE_BRG1 - 1) + i;
258 else
259 return QE_CLK_DUMMY;
260 }
261
262 if (strncasecmp(source, "clk", 3) == 0) {
263 i = simple_strtoul(source + 3, NULL, 10);
264 if ((i >= 1) && (i <= 24))
265 return (QE_CLK1 - 1) + i;
266 else
267 return QE_CLK_DUMMY;
268 }
269
270 return QE_CLK_DUMMY;
271}
272EXPORT_SYMBOL(qe_clock_source);
273
Li Yang98658532006-10-03 23:10:46 -0500274/* Initialize SNUMs (thread serial numbers) according to
275 * QE Module Control chapter, SNUM table
276 */
277static void qe_snums_init(void)
278{
279 int i;
280 static const u8 snum_init[] = {
281 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
282 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
283 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
Haiying Wang98ca77a2009-05-01 15:40:48 -0400284 0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
285 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
286 0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
Li Yang98658532006-10-03 23:10:46 -0500287 };
288
Haiying Wang98ca77a2009-05-01 15:40:48 -0400289 qe_num_of_snum = qe_get_num_of_snums();
290
291 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500292 snums[i].num = snum_init[i];
293 snums[i].state = QE_SNUM_STATE_FREE;
294 }
295}
296
297int qe_get_snum(void)
298{
299 unsigned long flags;
300 int snum = -EBUSY;
301 int i;
302
303 spin_lock_irqsave(&qe_lock, flags);
Haiying Wang98ca77a2009-05-01 15:40:48 -0400304 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500305 if (snums[i].state == QE_SNUM_STATE_FREE) {
306 snums[i].state = QE_SNUM_STATE_USED;
307 snum = snums[i].num;
308 break;
309 }
310 }
311 spin_unlock_irqrestore(&qe_lock, flags);
312
313 return snum;
314}
315EXPORT_SYMBOL(qe_get_snum);
316
317void qe_put_snum(u8 snum)
318{
319 int i;
320
Haiying Wang98ca77a2009-05-01 15:40:48 -0400321 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500322 if (snums[i].num == snum) {
323 snums[i].state = QE_SNUM_STATE_FREE;
324 break;
325 }
326 }
327}
328EXPORT_SYMBOL(qe_put_snum);
329
330static int qe_sdma_init(void)
331{
Andy Fleming7e1cc9c2008-05-07 13:19:44 -0500332 struct sdma __iomem *sdma = &qe_immr->sdma;
Timur Tabi4c356302007-05-08 14:46:36 -0500333 unsigned long sdma_buf_offset;
Li Yang98658532006-10-03 23:10:46 -0500334
335 if (!sdma)
336 return -ENODEV;
337
338 /* allocate 2 internal temporary buffers (512 bytes size each) for
339 * the SDMA */
Chuck Meade7f013bc2007-03-27 10:46:10 -0400340 sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
Timur Tabi4c356302007-05-08 14:46:36 -0500341 if (IS_ERR_VALUE(sdma_buf_offset))
Li Yang98658532006-10-03 23:10:46 -0500342 return -ENOMEM;
343
Timur Tabi4c356302007-05-08 14:46:36 -0500344 out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
Chuck Meade7f013bc2007-03-27 10:46:10 -0400345 out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
346 (0x1 << QE_SDMR_CEN_SHIFT)));
Li Yang98658532006-10-03 23:10:46 -0500347
348 return 0;
349}
350
Timur Tabibc556ba2008-01-08 10:30:58 -0600351/* The maximum number of RISCs we support */
Anton Vorontsov98eaa092009-08-27 21:30:11 +0400352#define MAX_QE_RISC 4
Timur Tabibc556ba2008-01-08 10:30:58 -0600353
354/* Firmware information stored here for qe_get_firmware_info() */
355static struct qe_firmware_info qe_firmware_info;
356
357/*
358 * Set to 1 if QE firmware has been uploaded, and therefore
359 * qe_firmware_info contains valid data.
360 */
361static int qe_firmware_uploaded;
362
363/*
364 * Upload a QE microcode
365 *
366 * This function is a worker function for qe_upload_firmware(). It does
367 * the actual uploading of the microcode.
368 */
369static void qe_upload_microcode(const void *base,
370 const struct qe_microcode *ucode)
371{
372 const __be32 *code = base + be32_to_cpu(ucode->code_offset);
373 unsigned int i;
374
375 if (ucode->major || ucode->minor || ucode->revision)
376 printk(KERN_INFO "qe-firmware: "
377 "uploading microcode '%s' version %u.%u.%u\n",
378 ucode->id, ucode->major, ucode->minor, ucode->revision);
379 else
380 printk(KERN_INFO "qe-firmware: "
381 "uploading microcode '%s'\n", ucode->id);
382
383 /* Use auto-increment */
384 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
385 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
386
387 for (i = 0; i < be32_to_cpu(ucode->count); i++)
388 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
389}
390
391/*
392 * Upload a microcode to the I-RAM at a specific address.
393 *
394 * See Documentation/powerpc/qe-firmware.txt for information on QE microcode
395 * uploading.
396 *
397 * Currently, only version 1 is supported, so the 'version' field must be
398 * set to 1.
399 *
400 * The SOC model and revision are not validated, they are only displayed for
401 * informational purposes.
402 *
403 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
404 * all of the microcode structures, minus the CRC.
405 *
406 * 'length' is the size that the structure says it is, including the CRC.
407 */
408int qe_upload_firmware(const struct qe_firmware *firmware)
409{
410 unsigned int i;
411 unsigned int j;
412 u32 crc;
413 size_t calc_size = sizeof(struct qe_firmware);
414 size_t length;
415 const struct qe_header *hdr;
416
417 if (!firmware) {
418 printk(KERN_ERR "qe-firmware: invalid pointer\n");
419 return -EINVAL;
420 }
421
422 hdr = &firmware->header;
423 length = be32_to_cpu(hdr->length);
424
425 /* Check the magic */
426 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
427 (hdr->magic[2] != 'F')) {
428 printk(KERN_ERR "qe-firmware: not a microcode\n");
429 return -EPERM;
430 }
431
432 /* Check the version */
433 if (hdr->version != 1) {
434 printk(KERN_ERR "qe-firmware: unsupported version\n");
435 return -EPERM;
436 }
437
438 /* Validate some of the fields */
Timur Tabi6f913162008-03-03 11:11:30 -0600439 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabibc556ba2008-01-08 10:30:58 -0600440 printk(KERN_ERR "qe-firmware: invalid data\n");
441 return -EINVAL;
442 }
443
444 /* Validate the length and check if there's a CRC */
445 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
446
447 for (i = 0; i < firmware->count; i++)
448 /*
449 * For situations where the second RISC uses the same microcode
450 * as the first, the 'code_offset' and 'count' fields will be
451 * zero, so it's okay to add those.
452 */
453 calc_size += sizeof(__be32) *
454 be32_to_cpu(firmware->microcode[i].count);
455
456 /* Validate the length */
457 if (length != calc_size + sizeof(__be32)) {
458 printk(KERN_ERR "qe-firmware: invalid length\n");
459 return -EPERM;
460 }
461
462 /* Validate the CRC */
463 crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
464 if (crc != crc32(0, firmware, calc_size)) {
465 printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
466 return -EIO;
467 }
468
469 /*
470 * If the microcode calls for it, split the I-RAM.
471 */
472 if (!firmware->split)
473 setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
474
475 if (firmware->soc.model)
476 printk(KERN_INFO
477 "qe-firmware: firmware '%s' for %u V%u.%u\n",
478 firmware->id, be16_to_cpu(firmware->soc.model),
479 firmware->soc.major, firmware->soc.minor);
480 else
481 printk(KERN_INFO "qe-firmware: firmware '%s'\n",
482 firmware->id);
483
484 /*
485 * The QE only supports one microcode per RISC, so clear out all the
486 * saved microcode information and put in the new.
487 */
488 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
489 strcpy(qe_firmware_info.id, firmware->id);
490 qe_firmware_info.extended_modes = firmware->extended_modes;
491 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
492 sizeof(firmware->vtraps));
493
494 /* Loop through each microcode. */
495 for (i = 0; i < firmware->count; i++) {
496 const struct qe_microcode *ucode = &firmware->microcode[i];
497
498 /* Upload a microcode if it's present */
499 if (ucode->code_offset)
500 qe_upload_microcode(firmware, ucode);
501
502 /* Program the traps for this processor */
503 for (j = 0; j < 16; j++) {
504 u32 trap = be32_to_cpu(ucode->traps[j]);
505
506 if (trap)
507 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
508 }
509
510 /* Enable traps */
511 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
512 }
513
514 qe_firmware_uploaded = 1;
515
516 return 0;
517}
518EXPORT_SYMBOL(qe_upload_firmware);
519
520/*
521 * Get info on the currently-loaded firmware
522 *
523 * This function also checks the device tree to see if the boot loader has
524 * uploaded a firmware already.
525 */
526struct qe_firmware_info *qe_get_firmware_info(void)
527{
528 static int initialized;
529 struct property *prop;
530 struct device_node *qe;
531 struct device_node *fw = NULL;
532 const char *sprop;
533 unsigned int i;
534
535 /*
536 * If we haven't checked yet, and a driver hasn't uploaded a firmware
537 * yet, then check the device tree for information.
538 */
Ionut Nicu86f4e5d2008-03-07 19:27:59 +0200539 if (qe_firmware_uploaded)
540 return &qe_firmware_info;
541
542 if (initialized)
Timur Tabibc556ba2008-01-08 10:30:58 -0600543 return NULL;
544
545 initialized = 1;
546
547 /*
548 * Newer device trees have an "fsl,qe" compatible property for the QE
549 * node, but we still need to support older device trees.
550 */
551 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
552 if (!qe) {
553 qe = of_find_node_by_type(NULL, "qe");
554 if (!qe)
555 return NULL;
556 }
557
558 /* Find the 'firmware' child node */
559 for_each_child_of_node(qe, fw) {
560 if (strcmp(fw->name, "firmware") == 0)
561 break;
562 }
563
564 of_node_put(qe);
565
566 /* Did we find the 'firmware' node? */
567 if (!fw)
568 return NULL;
569
570 qe_firmware_uploaded = 1;
571
572 /* Copy the data into qe_firmware_info*/
573 sprop = of_get_property(fw, "id", NULL);
574 if (sprop)
575 strncpy(qe_firmware_info.id, sprop,
576 sizeof(qe_firmware_info.id) - 1);
577
578 prop = of_find_property(fw, "extended-modes", NULL);
579 if (prop && (prop->length == sizeof(u64))) {
580 const u64 *iprop = prop->value;
581
582 qe_firmware_info.extended_modes = *iprop;
583 }
584
585 prop = of_find_property(fw, "virtual-traps", NULL);
586 if (prop && (prop->length == 32)) {
587 const u32 *iprop = prop->value;
588
589 for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
590 qe_firmware_info.vtraps[i] = iprop[i];
591 }
592
593 of_node_put(fw);
594
595 return &qe_firmware_info;
596}
597EXPORT_SYMBOL(qe_get_firmware_info);
598
Haiying Wang06c44352009-05-01 15:40:47 -0400599unsigned int qe_get_num_of_risc(void)
600{
601 struct device_node *qe;
602 int size;
603 unsigned int num_of_risc = 0;
604 const u32 *prop;
605
606 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
607 if (!qe) {
608 /* Older devices trees did not have an "fsl,qe"
609 * compatible property, so we need to look for
610 * the QE node by name.
611 */
612 qe = of_find_node_by_type(NULL, "qe");
613 if (!qe)
614 return num_of_risc;
615 }
616
617 prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
618 if (prop && size == sizeof(*prop))
619 num_of_risc = *prop;
620
621 of_node_put(qe);
622
623 return num_of_risc;
624}
625EXPORT_SYMBOL(qe_get_num_of_risc);
626
Haiying Wang98ca77a2009-05-01 15:40:48 -0400627unsigned int qe_get_num_of_snums(void)
628{
629 struct device_node *qe;
630 int size;
631 unsigned int num_of_snums;
632 const u32 *prop;
633
634 num_of_snums = 28; /* The default number of snum for threads is 28 */
635 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
636 if (!qe) {
637 /* Older devices trees did not have an "fsl,qe"
638 * compatible property, so we need to look for
639 * the QE node by name.
640 */
641 qe = of_find_node_by_type(NULL, "qe");
642 if (!qe)
643 return num_of_snums;
644 }
645
646 prop = of_get_property(qe, "fsl,qe-num-snums", &size);
647 if (prop && size == sizeof(*prop)) {
648 num_of_snums = *prop;
649 if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
650 /* No QE ever has fewer than 28 SNUMs */
651 pr_err("QE: number of snum is invalid\n");
652 return -EINVAL;
653 }
654 }
655
656 of_node_put(qe);
657
658 return num_of_snums;
659}
660EXPORT_SYMBOL(qe_get_num_of_snums);