blob: 3925eae9b0f579a4cfd7496af8af14339c9d7369 [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 */
58struct qe_immap *qe_immr = NULL;
59EXPORT_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;
68
69 if (qebase != -1)
70 return qebase;
71
72 qe = of_find_node_by_type(NULL, "qe");
73 if (qe) {
74 unsigned int size;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +100075 const void *prop = of_get_property(qe, "reg", &size);
Li Yang98658532006-10-03 23:10:46 -050076 qebase = of_translate_address(qe, prop);
77 of_node_put(qe);
78 };
79
80 return qebase;
81}
82
83EXPORT_SYMBOL(get_qe_base);
84
85void qe_reset(void)
86{
87 if (qe_immr == NULL)
88 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
89
90 qe_snums_init();
91
92 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
93 QE_CR_PROTOCOL_UNSPECIFIED, 0);
94
95 /* Reclaim the MURAM memory for our use. */
96 qe_muram_init();
97
98 if (qe_sdma_init())
99 panic("sdma init failed!");
100}
101
102int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
103{
104 unsigned long flags;
105 u8 mcn_shift = 0, dev_shift = 0;
106
107 spin_lock_irqsave(&qe_lock, flags);
108 if (cmd == QE_RESET) {
109 out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
110 } else {
111 if (cmd == QE_ASSIGN_PAGE) {
112 /* Here device is the SNUM, not sub-block */
113 dev_shift = QE_CR_SNUM_SHIFT;
114 } else if (cmd == QE_ASSIGN_RISC) {
115 /* Here device is the SNUM, and mcnProtocol is
116 * e_QeCmdRiscAssignment value */
117 dev_shift = QE_CR_SNUM_SHIFT;
118 mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
119 } else {
120 if (device == QE_CR_SUBBLOCK_USB)
121 mcn_shift = QE_CR_MCN_USB_SHIFT;
122 else
123 mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
124 }
125
Timur Tabi302439d2006-10-31 17:53:42 +0800126 out_be32(&qe_immr->cp.cecdr, cmd_input);
Li Yang98658532006-10-03 23:10:46 -0500127 out_be32(&qe_immr->cp.cecr,
128 (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
129 mcn_protocol << mcn_shift));
130 }
131
132 /* wait for the QE_CR_FLG to clear */
133 while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG)
134 cpu_relax();
135 spin_unlock_irqrestore(&qe_lock, flags);
136
137 return 0;
138}
139EXPORT_SYMBOL(qe_issue_cmd);
140
141/* Set a baud rate generator. This needs lots of work. There are
142 * 16 BRGs, which can be connected to the QE channels or output
143 * as clocks. The BRGs are in two different block of internal
144 * memory mapped space.
Timur Tabi6b0b5942007-10-03 11:34:59 -0500145 * The BRG clock is the QE clock divided by 2.
Li Yang98658532006-10-03 23:10:46 -0500146 * It was set up long ago during the initial boot phase and is
147 * is given to us.
148 * Baud rate clocks are zero-based in the driver code (as that maps
149 * to port numbers). Documentation uses 1-based numbering.
150 */
151static unsigned int brg_clk = 0;
152
153unsigned int get_brg_clk(void)
154{
155 struct device_node *qe;
156 if (brg_clk)
157 return brg_clk;
158
159 qe = of_find_node_by_type(NULL, "qe");
160 if (qe) {
161 unsigned int size;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000162 const u32 *prop = of_get_property(qe, "brg-frequency", &size);
Li Yang98658532006-10-03 23:10:46 -0500163 brg_clk = *prop;
164 of_node_put(qe);
165 };
166 return brg_clk;
167}
168
Timur Tabi6b0b5942007-10-03 11:34:59 -0500169/* Program the BRG to the given sampling rate and multiplier
170 *
Timur Tabi7264ec42007-11-29 17:26:30 -0600171 * @brg: the BRG, QE_BRG1 - QE_BRG16
Timur Tabi6b0b5942007-10-03 11:34:59 -0500172 * @rate: the desired sampling rate
173 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
174 * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
175 * then 'multiplier' should be 8.
Li Yang98658532006-10-03 23:10:46 -0500176 */
Timur Tabi7264ec42007-11-29 17:26:30 -0600177int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
Li Yang98658532006-10-03 23:10:46 -0500178{
Li Yang98658532006-10-03 23:10:46 -0500179 u32 divisor, tempval;
Timur Tabi6b0b5942007-10-03 11:34:59 -0500180 u32 div16 = 0;
Li Yang98658532006-10-03 23:10:46 -0500181
Timur Tabi7264ec42007-11-29 17:26:30 -0600182 if ((brg < QE_BRG1) || (brg > QE_BRG16))
183 return -EINVAL;
184
Timur Tabi6b0b5942007-10-03 11:34:59 -0500185 divisor = get_brg_clk() / (rate * multiplier);
Li Yang98658532006-10-03 23:10:46 -0500186
Li Yang98658532006-10-03 23:10:46 -0500187 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
Timur Tabi6b0b5942007-10-03 11:34:59 -0500188 div16 = QE_BRGC_DIV16;
Li Yang98658532006-10-03 23:10:46 -0500189 divisor /= 16;
190 }
191
Timur Tabi6b0b5942007-10-03 11:34:59 -0500192 /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
193 that the BRG divisor must be even if you're not using divide-by-16
194 mode. */
195 if (!div16 && (divisor & 1))
196 divisor++;
Li Yang98658532006-10-03 23:10:46 -0500197
Timur Tabi6b0b5942007-10-03 11:34:59 -0500198 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
199 QE_BRGC_ENABLE | div16;
200
Timur Tabi7264ec42007-11-29 17:26:30 -0600201 out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
202
203 return 0;
Li Yang98658532006-10-03 23:10:46 -0500204}
Timur Tabi7264ec42007-11-29 17:26:30 -0600205EXPORT_SYMBOL(qe_setbrg);
Li Yang98658532006-10-03 23:10:46 -0500206
Timur Tabi174b0da2007-12-03 15:17:58 -0600207/* Convert a string to a QE clock source enum
208 *
209 * This function takes a string, typically from a property in the device
210 * tree, and returns the corresponding "enum qe_clock" value.
211*/
212enum qe_clock qe_clock_source(const char *source)
213{
214 unsigned int i;
215
216 if (strcasecmp(source, "none") == 0)
217 return QE_CLK_NONE;
218
219 if (strncasecmp(source, "brg", 3) == 0) {
220 i = simple_strtoul(source + 3, NULL, 10);
221 if ((i >= 1) && (i <= 16))
222 return (QE_BRG1 - 1) + i;
223 else
224 return QE_CLK_DUMMY;
225 }
226
227 if (strncasecmp(source, "clk", 3) == 0) {
228 i = simple_strtoul(source + 3, NULL, 10);
229 if ((i >= 1) && (i <= 24))
230 return (QE_CLK1 - 1) + i;
231 else
232 return QE_CLK_DUMMY;
233 }
234
235 return QE_CLK_DUMMY;
236}
237EXPORT_SYMBOL(qe_clock_source);
238
Li Yang98658532006-10-03 23:10:46 -0500239/* Initialize SNUMs (thread serial numbers) according to
240 * QE Module Control chapter, SNUM table
241 */
242static void qe_snums_init(void)
243{
244 int i;
245 static const u8 snum_init[] = {
246 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
247 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
248 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
249 0xD8, 0xD9, 0xE8, 0xE9,
250 };
251
252 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
253 snums[i].num = snum_init[i];
254 snums[i].state = QE_SNUM_STATE_FREE;
255 }
256}
257
258int qe_get_snum(void)
259{
260 unsigned long flags;
261 int snum = -EBUSY;
262 int i;
263
264 spin_lock_irqsave(&qe_lock, flags);
265 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
266 if (snums[i].state == QE_SNUM_STATE_FREE) {
267 snums[i].state = QE_SNUM_STATE_USED;
268 snum = snums[i].num;
269 break;
270 }
271 }
272 spin_unlock_irqrestore(&qe_lock, flags);
273
274 return snum;
275}
276EXPORT_SYMBOL(qe_get_snum);
277
278void qe_put_snum(u8 snum)
279{
280 int i;
281
282 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
283 if (snums[i].num == snum) {
284 snums[i].state = QE_SNUM_STATE_FREE;
285 break;
286 }
287 }
288}
289EXPORT_SYMBOL(qe_put_snum);
290
291static int qe_sdma_init(void)
292{
293 struct sdma *sdma = &qe_immr->sdma;
Timur Tabi4c356302007-05-08 14:46:36 -0500294 unsigned long sdma_buf_offset;
Li Yang98658532006-10-03 23:10:46 -0500295
296 if (!sdma)
297 return -ENODEV;
298
299 /* allocate 2 internal temporary buffers (512 bytes size each) for
300 * the SDMA */
Chuck Meade7f013bc2007-03-27 10:46:10 -0400301 sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
Timur Tabi4c356302007-05-08 14:46:36 -0500302 if (IS_ERR_VALUE(sdma_buf_offset))
Li Yang98658532006-10-03 23:10:46 -0500303 return -ENOMEM;
304
Timur Tabi4c356302007-05-08 14:46:36 -0500305 out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
Chuck Meade7f013bc2007-03-27 10:46:10 -0400306 out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
307 (0x1 << QE_SDMR_CEN_SHIFT)));
Li Yang98658532006-10-03 23:10:46 -0500308
309 return 0;
310}
311
312/*
313 * muram_alloc / muram_free bits.
314 */
315static DEFINE_SPINLOCK(qe_muram_lock);
316
317/* 16 blocks should be enough to satisfy all requests
318 * until the memory subsystem goes up... */
319static rh_block_t qe_boot_muram_rh_block[16];
320static rh_info_t qe_muram_info;
321
322static void qe_muram_init(void)
323{
324 struct device_node *np;
325 u32 address;
326 u64 size;
327 unsigned int flags;
328
329 /* initialize the info header */
330 rh_init(&qe_muram_info, 1,
331 sizeof(qe_boot_muram_rh_block) /
332 sizeof(qe_boot_muram_rh_block[0]), qe_boot_muram_rh_block);
333
334 /* Attach the usable muram area */
335 /* XXX: This is a subset of the available muram. It
336 * varies with the processor and the microcode patches activated.
337 */
338 if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) {
339 address = *of_get_address(np, 0, &size, &flags);
340 of_node_put(np);
Timur Tabi4c356302007-05-08 14:46:36 -0500341 rh_attach_region(&qe_muram_info, address, (int) size);
Li Yang98658532006-10-03 23:10:46 -0500342 }
343}
344
345/* This function returns an index into the MURAM area.
346 */
Timur Tabi4c356302007-05-08 14:46:36 -0500347unsigned long qe_muram_alloc(int size, int align)
Li Yang98658532006-10-03 23:10:46 -0500348{
Timur Tabi4c356302007-05-08 14:46:36 -0500349 unsigned long start;
Li Yang98658532006-10-03 23:10:46 -0500350 unsigned long flags;
351
352 spin_lock_irqsave(&qe_muram_lock, flags);
353 start = rh_alloc_align(&qe_muram_info, size, align, "QE");
354 spin_unlock_irqrestore(&qe_muram_lock, flags);
355
Timur Tabi4c356302007-05-08 14:46:36 -0500356 return start;
Li Yang98658532006-10-03 23:10:46 -0500357}
358EXPORT_SYMBOL(qe_muram_alloc);
359
Timur Tabi4c356302007-05-08 14:46:36 -0500360int qe_muram_free(unsigned long offset)
Li Yang98658532006-10-03 23:10:46 -0500361{
362 int ret;
363 unsigned long flags;
364
365 spin_lock_irqsave(&qe_muram_lock, flags);
Timur Tabi4c356302007-05-08 14:46:36 -0500366 ret = rh_free(&qe_muram_info, offset);
Li Yang98658532006-10-03 23:10:46 -0500367 spin_unlock_irqrestore(&qe_muram_lock, flags);
368
369 return ret;
370}
371EXPORT_SYMBOL(qe_muram_free);
372
373/* not sure if this is ever needed */
Timur Tabi4c356302007-05-08 14:46:36 -0500374unsigned long qe_muram_alloc_fixed(unsigned long offset, int size)
Li Yang98658532006-10-03 23:10:46 -0500375{
Timur Tabi4c356302007-05-08 14:46:36 -0500376 unsigned long start;
Li Yang98658532006-10-03 23:10:46 -0500377 unsigned long flags;
378
379 spin_lock_irqsave(&qe_muram_lock, flags);
Timur Tabi4c356302007-05-08 14:46:36 -0500380 start = rh_alloc_fixed(&qe_muram_info, offset, size, "commproc");
Li Yang98658532006-10-03 23:10:46 -0500381 spin_unlock_irqrestore(&qe_muram_lock, flags);
382
Timur Tabi4c356302007-05-08 14:46:36 -0500383 return start;
Li Yang98658532006-10-03 23:10:46 -0500384}
385EXPORT_SYMBOL(qe_muram_alloc_fixed);
386
387void qe_muram_dump(void)
388{
389 rh_dump(&qe_muram_info);
390}
391EXPORT_SYMBOL(qe_muram_dump);
392
Timur Tabi4c356302007-05-08 14:46:36 -0500393void *qe_muram_addr(unsigned long offset)
Li Yang98658532006-10-03 23:10:46 -0500394{
395 return (void *)&qe_immr->muram[offset];
396}
397EXPORT_SYMBOL(qe_muram_addr);
Timur Tabibc556ba2008-01-08 10:30:58 -0600398
399/* The maximum number of RISCs we support */
400#define MAX_QE_RISC 2
401
402/* Firmware information stored here for qe_get_firmware_info() */
403static struct qe_firmware_info qe_firmware_info;
404
405/*
406 * Set to 1 if QE firmware has been uploaded, and therefore
407 * qe_firmware_info contains valid data.
408 */
409static int qe_firmware_uploaded;
410
411/*
412 * Upload a QE microcode
413 *
414 * This function is a worker function for qe_upload_firmware(). It does
415 * the actual uploading of the microcode.
416 */
417static void qe_upload_microcode(const void *base,
418 const struct qe_microcode *ucode)
419{
420 const __be32 *code = base + be32_to_cpu(ucode->code_offset);
421 unsigned int i;
422
423 if (ucode->major || ucode->minor || ucode->revision)
424 printk(KERN_INFO "qe-firmware: "
425 "uploading microcode '%s' version %u.%u.%u\n",
426 ucode->id, ucode->major, ucode->minor, ucode->revision);
427 else
428 printk(KERN_INFO "qe-firmware: "
429 "uploading microcode '%s'\n", ucode->id);
430
431 /* Use auto-increment */
432 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
433 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
434
435 for (i = 0; i < be32_to_cpu(ucode->count); i++)
436 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
437}
438
439/*
440 * Upload a microcode to the I-RAM at a specific address.
441 *
442 * See Documentation/powerpc/qe-firmware.txt for information on QE microcode
443 * uploading.
444 *
445 * Currently, only version 1 is supported, so the 'version' field must be
446 * set to 1.
447 *
448 * The SOC model and revision are not validated, they are only displayed for
449 * informational purposes.
450 *
451 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
452 * all of the microcode structures, minus the CRC.
453 *
454 * 'length' is the size that the structure says it is, including the CRC.
455 */
456int qe_upload_firmware(const struct qe_firmware *firmware)
457{
458 unsigned int i;
459 unsigned int j;
460 u32 crc;
461 size_t calc_size = sizeof(struct qe_firmware);
462 size_t length;
463 const struct qe_header *hdr;
464
465 if (!firmware) {
466 printk(KERN_ERR "qe-firmware: invalid pointer\n");
467 return -EINVAL;
468 }
469
470 hdr = &firmware->header;
471 length = be32_to_cpu(hdr->length);
472
473 /* Check the magic */
474 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
475 (hdr->magic[2] != 'F')) {
476 printk(KERN_ERR "qe-firmware: not a microcode\n");
477 return -EPERM;
478 }
479
480 /* Check the version */
481 if (hdr->version != 1) {
482 printk(KERN_ERR "qe-firmware: unsupported version\n");
483 return -EPERM;
484 }
485
486 /* Validate some of the fields */
487 if ((firmware->count < 1) || (firmware->count >= MAX_QE_RISC)) {
488 printk(KERN_ERR "qe-firmware: invalid data\n");
489 return -EINVAL;
490 }
491
492 /* Validate the length and check if there's a CRC */
493 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
494
495 for (i = 0; i < firmware->count; i++)
496 /*
497 * For situations where the second RISC uses the same microcode
498 * as the first, the 'code_offset' and 'count' fields will be
499 * zero, so it's okay to add those.
500 */
501 calc_size += sizeof(__be32) *
502 be32_to_cpu(firmware->microcode[i].count);
503
504 /* Validate the length */
505 if (length != calc_size + sizeof(__be32)) {
506 printk(KERN_ERR "qe-firmware: invalid length\n");
507 return -EPERM;
508 }
509
510 /* Validate the CRC */
511 crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
512 if (crc != crc32(0, firmware, calc_size)) {
513 printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
514 return -EIO;
515 }
516
517 /*
518 * If the microcode calls for it, split the I-RAM.
519 */
520 if (!firmware->split)
521 setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
522
523 if (firmware->soc.model)
524 printk(KERN_INFO
525 "qe-firmware: firmware '%s' for %u V%u.%u\n",
526 firmware->id, be16_to_cpu(firmware->soc.model),
527 firmware->soc.major, firmware->soc.minor);
528 else
529 printk(KERN_INFO "qe-firmware: firmware '%s'\n",
530 firmware->id);
531
532 /*
533 * The QE only supports one microcode per RISC, so clear out all the
534 * saved microcode information and put in the new.
535 */
536 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
537 strcpy(qe_firmware_info.id, firmware->id);
538 qe_firmware_info.extended_modes = firmware->extended_modes;
539 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
540 sizeof(firmware->vtraps));
541
542 /* Loop through each microcode. */
543 for (i = 0; i < firmware->count; i++) {
544 const struct qe_microcode *ucode = &firmware->microcode[i];
545
546 /* Upload a microcode if it's present */
547 if (ucode->code_offset)
548 qe_upload_microcode(firmware, ucode);
549
550 /* Program the traps for this processor */
551 for (j = 0; j < 16; j++) {
552 u32 trap = be32_to_cpu(ucode->traps[j]);
553
554 if (trap)
555 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
556 }
557
558 /* Enable traps */
559 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
560 }
561
562 qe_firmware_uploaded = 1;
563
564 return 0;
565}
566EXPORT_SYMBOL(qe_upload_firmware);
567
568/*
569 * Get info on the currently-loaded firmware
570 *
571 * This function also checks the device tree to see if the boot loader has
572 * uploaded a firmware already.
573 */
574struct qe_firmware_info *qe_get_firmware_info(void)
575{
576 static int initialized;
577 struct property *prop;
578 struct device_node *qe;
579 struct device_node *fw = NULL;
580 const char *sprop;
581 unsigned int i;
582
583 /*
584 * If we haven't checked yet, and a driver hasn't uploaded a firmware
585 * yet, then check the device tree for information.
586 */
587 if (initialized || qe_firmware_uploaded)
588 return NULL;
589
590 initialized = 1;
591
592 /*
593 * Newer device trees have an "fsl,qe" compatible property for the QE
594 * node, but we still need to support older device trees.
595 */
596 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
597 if (!qe) {
598 qe = of_find_node_by_type(NULL, "qe");
599 if (!qe)
600 return NULL;
601 }
602
603 /* Find the 'firmware' child node */
604 for_each_child_of_node(qe, fw) {
605 if (strcmp(fw->name, "firmware") == 0)
606 break;
607 }
608
609 of_node_put(qe);
610
611 /* Did we find the 'firmware' node? */
612 if (!fw)
613 return NULL;
614
615 qe_firmware_uploaded = 1;
616
617 /* Copy the data into qe_firmware_info*/
618 sprop = of_get_property(fw, "id", NULL);
619 if (sprop)
620 strncpy(qe_firmware_info.id, sprop,
621 sizeof(qe_firmware_info.id) - 1);
622
623 prop = of_find_property(fw, "extended-modes", NULL);
624 if (prop && (prop->length == sizeof(u64))) {
625 const u64 *iprop = prop->value;
626
627 qe_firmware_info.extended_modes = *iprop;
628 }
629
630 prop = of_find_property(fw, "virtual-traps", NULL);
631 if (prop && (prop->length == 32)) {
632 const u32 *iprop = prop->value;
633
634 for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
635 qe_firmware_info.vtraps[i] = iprop[i];
636 }
637
638 of_node_put(fw);
639
640 return &qe_firmware_info;
641}
642EXPORT_SYMBOL(qe_get_firmware_info);
643