~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/sysdev/qe_lib/qe.c

Version: ~ [ linux-5.8-rc3 ] ~ [ linux-5.7.5 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.48 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.129 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.185 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.228 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.228 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (C) 2006-2010 Freescale Semiconductor, 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/spinlock.h>
 23 #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>
 29 #include <linux/crc32.h>
 30 #include <linux/mod_devicetable.h>
 31 #include <linux/of_platform.h>
 32 #include <asm/irq.h>
 33 #include <asm/page.h>
 34 #include <asm/pgtable.h>
 35 #include <asm/immap_qe.h>
 36 #include <asm/qe.h>
 37 #include <asm/prom.h>
 38 #include <asm/rheap.h>
 39 
 40 static void qe_snums_init(void);
 41 static int qe_sdma_init(void);
 42 
 43 static DEFINE_SPINLOCK(qe_lock);
 44 DEFINE_SPINLOCK(cmxgcr_lock);
 45 EXPORT_SYMBOL(cmxgcr_lock);
 46 
 47 /* QE snum state */
 48 enum qe_snum_state {
 49         QE_SNUM_STATE_USED,
 50         QE_SNUM_STATE_FREE
 51 };
 52 
 53 /* QE snum */
 54 struct qe_snum {
 55         u8 num;
 56         enum qe_snum_state state;
 57 };
 58 
 59 /* We allocate this here because it is used almost exclusively for
 60  * the communication processor devices.
 61  */
 62 struct qe_immap __iomem *qe_immr;
 63 EXPORT_SYMBOL(qe_immr);
 64 
 65 static struct qe_snum snums[QE_NUM_OF_SNUM];    /* Dynamically allocated SNUMs */
 66 static unsigned int qe_num_of_snum;
 67 
 68 static phys_addr_t qebase = -1;
 69 
 70 phys_addr_t get_qe_base(void)
 71 {
 72         struct device_node *qe;
 73         int size;
 74         const u32 *prop;
 75 
 76         if (qebase != -1)
 77                 return qebase;
 78 
 79         qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
 80         if (!qe) {
 81                 qe = of_find_node_by_type(NULL, "qe");
 82                 if (!qe)
 83                         return qebase;
 84         }
 85 
 86         prop = of_get_property(qe, "reg", &size);
 87         if (prop && size >= sizeof(*prop))
 88                 qebase = of_translate_address(qe, prop);
 89         of_node_put(qe);
 90 
 91         return qebase;
 92 }
 93 
 94 EXPORT_SYMBOL(get_qe_base);
 95 
 96 void qe_reset(void)
 97 {
 98         if (qe_immr == NULL)
 99                 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
100 
101         qe_snums_init();
102 
103         qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
104                      QE_CR_PROTOCOL_UNSPECIFIED, 0);
105 
106         /* Reclaim the MURAM memory for our use. */
107         qe_muram_init();
108 
109         if (qe_sdma_init())
110                 panic("sdma init failed!");
111 }
112 
113 int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
114 {
115         unsigned long flags;
116         u8 mcn_shift = 0, dev_shift = 0;
117         u32 ret;
118 
119         spin_lock_irqsave(&qe_lock, flags);
120         if (cmd == QE_RESET) {
121                 out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
122         } else {
123                 if (cmd == QE_ASSIGN_PAGE) {
124                         /* Here device is the SNUM, not sub-block */
125                         dev_shift = QE_CR_SNUM_SHIFT;
126                 } else if (cmd == QE_ASSIGN_RISC) {
127                         /* Here device is the SNUM, and mcnProtocol is
128                          * e_QeCmdRiscAssignment value */
129                         dev_shift = QE_CR_SNUM_SHIFT;
130                         mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
131                 } else {
132                         if (device == QE_CR_SUBBLOCK_USB)
133                                 mcn_shift = QE_CR_MCN_USB_SHIFT;
134                         else
135                                 mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
136                 }
137 
138                 out_be32(&qe_immr->cp.cecdr, cmd_input);
139                 out_be32(&qe_immr->cp.cecr,
140                          (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
141                           mcn_protocol << mcn_shift));
142         }
143 
144         /* wait for the QE_CR_FLG to clear */
145         ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
146                            100, 0);
147         /* On timeout (e.g. failure), the expression will be false (ret == 0),
148            otherwise it will be true (ret == 1). */
149         spin_unlock_irqrestore(&qe_lock, flags);
150 
151         return ret == 1;
152 }
153 EXPORT_SYMBOL(qe_issue_cmd);
154 
155 /* Set a baud rate generator. This needs lots of work. There are
156  * 16 BRGs, which can be connected to the QE channels or output
157  * as clocks. The BRGs are in two different block of internal
158  * memory mapped space.
159  * The BRG clock is the QE clock divided by 2.
160  * It was set up long ago during the initial boot phase and is
161  * is given to us.
162  * Baud rate clocks are zero-based in the driver code (as that maps
163  * to port numbers). Documentation uses 1-based numbering.
164  */
165 static unsigned int brg_clk = 0;
166 
167 unsigned int qe_get_brg_clk(void)
168 {
169         struct device_node *qe;
170         int size;
171         const u32 *prop;
172 
173         if (brg_clk)
174                 return brg_clk;
175 
176         qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
177         if (!qe) {
178                 qe = of_find_node_by_type(NULL, "qe");
179                 if (!qe)
180                         return brg_clk;
181         }
182 
183         prop = of_get_property(qe, "brg-frequency", &size);
184         if (prop && size == sizeof(*prop))
185                 brg_clk = *prop;
186 
187         of_node_put(qe);
188 
189         return brg_clk;
190 }
191 EXPORT_SYMBOL(qe_get_brg_clk);
192 
193 /* Program the BRG to the given sampling rate and multiplier
194  *
195  * @brg: the BRG, QE_BRG1 - QE_BRG16
196  * @rate: the desired sampling rate
197  * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
198  * GUMR_L[TDCR].  E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
199  * then 'multiplier' should be 8.
200  */
201 int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
202 {
203         u32 divisor, tempval;
204         u32 div16 = 0;
205 
206         if ((brg < QE_BRG1) || (brg > QE_BRG16))
207                 return -EINVAL;
208 
209         divisor = qe_get_brg_clk() / (rate * multiplier);
210 
211         if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
212                 div16 = QE_BRGC_DIV16;
213                 divisor /= 16;
214         }
215 
216         /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
217            that the BRG divisor must be even if you're not using divide-by-16
218            mode. */
219         if (!div16 && (divisor & 1) && (divisor > 3))
220                 divisor++;
221 
222         tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
223                 QE_BRGC_ENABLE | div16;
224 
225         out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
226 
227         return 0;
228 }
229 EXPORT_SYMBOL(qe_setbrg);
230 
231 /* Convert a string to a QE clock source enum
232  *
233  * This function takes a string, typically from a property in the device
234  * tree, and returns the corresponding "enum qe_clock" value.
235 */
236 enum qe_clock qe_clock_source(const char *source)
237 {
238         unsigned int i;
239 
240         if (strcasecmp(source, "none") == 0)
241                 return QE_CLK_NONE;
242 
243         if (strncasecmp(source, "brg", 3) == 0) {
244                 i = simple_strtoul(source + 3, NULL, 10);
245                 if ((i >= 1) && (i <= 16))
246                         return (QE_BRG1 - 1) + i;
247                 else
248                         return QE_CLK_DUMMY;
249         }
250 
251         if (strncasecmp(source, "clk", 3) == 0) {
252                 i = simple_strtoul(source + 3, NULL, 10);
253                 if ((i >= 1) && (i <= 24))
254                         return (QE_CLK1 - 1) + i;
255                 else
256                         return QE_CLK_DUMMY;
257         }
258 
259         return QE_CLK_DUMMY;
260 }
261 EXPORT_SYMBOL(qe_clock_source);
262 
263 /* Initialize SNUMs (thread serial numbers) according to
264  * QE Module Control chapter, SNUM table
265  */
266 static void qe_snums_init(void)
267 {
268         int i;
269         static const u8 snum_init_76[] = {
270                 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
271                 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
272                 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
273                 0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D,
274                 0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D,
275                 0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D,
276                 0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD,
277                 0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD,
278                 0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED,
279                 0xF4, 0xF5, 0xFC, 0xFD,
280         };
281         static const u8 snum_init_46[] = {
282                 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
283                 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
284                 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
285                 0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
286                 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
287                 0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
288         };
289         static const u8 *snum_init;
290 
291         qe_num_of_snum = qe_get_num_of_snums();
292 
293         if (qe_num_of_snum == 76)
294                 snum_init = snum_init_76;
295         else
296                 snum_init = snum_init_46;
297 
298         for (i = 0; i < qe_num_of_snum; i++) {
299                 snums[i].num = snum_init[i];
300                 snums[i].state = QE_SNUM_STATE_FREE;
301         }
302 }
303 
304 int qe_get_snum(void)
305 {
306         unsigned long flags;
307         int snum = -EBUSY;
308         int i;
309 
310         spin_lock_irqsave(&qe_lock, flags);
311         for (i = 0; i < qe_num_of_snum; i++) {
312                 if (snums[i].state == QE_SNUM_STATE_FREE) {
313                         snums[i].state = QE_SNUM_STATE_USED;
314                         snum = snums[i].num;
315                         break;
316                 }
317         }
318         spin_unlock_irqrestore(&qe_lock, flags);
319 
320         return snum;
321 }
322 EXPORT_SYMBOL(qe_get_snum);
323 
324 void qe_put_snum(u8 snum)
325 {
326         int i;
327 
328         for (i = 0; i < qe_num_of_snum; i++) {
329                 if (snums[i].num == snum) {
330                         snums[i].state = QE_SNUM_STATE_FREE;
331                         break;
332                 }
333         }
334 }
335 EXPORT_SYMBOL(qe_put_snum);
336 
337 static int qe_sdma_init(void)
338 {
339         struct sdma __iomem *sdma = &qe_immr->sdma;
340         static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM;
341 
342         if (!sdma)
343                 return -ENODEV;
344 
345         /* allocate 2 internal temporary buffers (512 bytes size each) for
346          * the SDMA */
347         if (IS_ERR_VALUE(sdma_buf_offset)) {
348                 sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
349                 if (IS_ERR_VALUE(sdma_buf_offset))
350                         return -ENOMEM;
351         }
352 
353         out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
354         out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
355                                         (0x1 << QE_SDMR_CEN_SHIFT)));
356 
357         return 0;
358 }
359 
360 /* The maximum number of RISCs we support */
361 #define MAX_QE_RISC     4
362 
363 /* Firmware information stored here for qe_get_firmware_info() */
364 static struct qe_firmware_info qe_firmware_info;
365 
366 /*
367  * Set to 1 if QE firmware has been uploaded, and therefore
368  * qe_firmware_info contains valid data.
369  */
370 static int qe_firmware_uploaded;
371 
372 /*
373  * Upload a QE microcode
374  *
375  * This function is a worker function for qe_upload_firmware().  It does
376  * the actual uploading of the microcode.
377  */
378 static void qe_upload_microcode(const void *base,
379         const struct qe_microcode *ucode)
380 {
381         const __be32 *code = base + be32_to_cpu(ucode->code_offset);
382         unsigned int i;
383 
384         if (ucode->major || ucode->minor || ucode->revision)
385                 printk(KERN_INFO "qe-firmware: "
386                         "uploading microcode '%s' version %u.%u.%u\n",
387                         ucode->id, ucode->major, ucode->minor, ucode->revision);
388         else
389                 printk(KERN_INFO "qe-firmware: "
390                         "uploading microcode '%s'\n", ucode->id);
391 
392         /* Use auto-increment */
393         out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
394                 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
395 
396         for (i = 0; i < be32_to_cpu(ucode->count); i++)
397                 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
398         
399         /* Set I-RAM Ready Register */
400         out_be32(&qe_immr->iram.iready, be32_to_cpu(QE_IRAM_READY));
401 }
402 
403 /*
404  * Upload a microcode to the I-RAM at a specific address.
405  *
406  * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
407  * uploading.
408  *
409  * Currently, only version 1 is supported, so the 'version' field must be
410  * set to 1.
411  *
412  * The SOC model and revision are not validated, they are only displayed for
413  * informational purposes.
414  *
415  * 'calc_size' is the calculated size, in bytes, of the firmware structure and
416  * all of the microcode structures, minus the CRC.
417  *
418  * 'length' is the size that the structure says it is, including the CRC.
419  */
420 int qe_upload_firmware(const struct qe_firmware *firmware)
421 {
422         unsigned int i;
423         unsigned int j;
424         u32 crc;
425         size_t calc_size = sizeof(struct qe_firmware);
426         size_t length;
427         const struct qe_header *hdr;
428 
429         if (!firmware) {
430                 printk(KERN_ERR "qe-firmware: invalid pointer\n");
431                 return -EINVAL;
432         }
433 
434         hdr = &firmware->header;
435         length = be32_to_cpu(hdr->length);
436 
437         /* Check the magic */
438         if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
439             (hdr->magic[2] != 'F')) {
440                 printk(KERN_ERR "qe-firmware: not a microcode\n");
441                 return -EPERM;
442         }
443 
444         /* Check the version */
445         if (hdr->version != 1) {
446                 printk(KERN_ERR "qe-firmware: unsupported version\n");
447                 return -EPERM;
448         }
449 
450         /* Validate some of the fields */
451         if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
452                 printk(KERN_ERR "qe-firmware: invalid data\n");
453                 return -EINVAL;
454         }
455 
456         /* Validate the length and check if there's a CRC */
457         calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
458 
459         for (i = 0; i < firmware->count; i++)
460                 /*
461                  * For situations where the second RISC uses the same microcode
462                  * as the first, the 'code_offset' and 'count' fields will be
463                  * zero, so it's okay to add those.
464                  */
465                 calc_size += sizeof(__be32) *
466                         be32_to_cpu(firmware->microcode[i].count);
467 
468         /* Validate the length */
469         if (length != calc_size + sizeof(__be32)) {
470                 printk(KERN_ERR "qe-firmware: invalid length\n");
471                 return -EPERM;
472         }
473 
474         /* Validate the CRC */
475         crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
476         if (crc != crc32(0, firmware, calc_size)) {
477                 printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
478                 return -EIO;
479         }
480 
481         /*
482          * If the microcode calls for it, split the I-RAM.
483          */
484         if (!firmware->split)
485                 setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
486 
487         if (firmware->soc.model)
488                 printk(KERN_INFO
489                         "qe-firmware: firmware '%s' for %u V%u.%u\n",
490                         firmware->id, be16_to_cpu(firmware->soc.model),
491                         firmware->soc.major, firmware->soc.minor);
492         else
493                 printk(KERN_INFO "qe-firmware: firmware '%s'\n",
494                         firmware->id);
495 
496         /*
497          * The QE only supports one microcode per RISC, so clear out all the
498          * saved microcode information and put in the new.
499          */
500         memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
501         strcpy(qe_firmware_info.id, firmware->id);
502         qe_firmware_info.extended_modes = firmware->extended_modes;
503         memcpy(qe_firmware_info.vtraps, firmware->vtraps,
504                 sizeof(firmware->vtraps));
505 
506         /* Loop through each microcode. */
507         for (i = 0; i < firmware->count; i++) {
508                 const struct qe_microcode *ucode = &firmware->microcode[i];
509 
510                 /* Upload a microcode if it's present */
511                 if (ucode->code_offset)
512                         qe_upload_microcode(firmware, ucode);
513 
514                 /* Program the traps for this processor */
515                 for (j = 0; j < 16; j++) {
516                         u32 trap = be32_to_cpu(ucode->traps[j]);
517 
518                         if (trap)
519                                 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
520                 }
521 
522                 /* Enable traps */
523                 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
524         }
525 
526         qe_firmware_uploaded = 1;
527 
528         return 0;
529 }
530 EXPORT_SYMBOL(qe_upload_firmware);
531 
532 /*
533  * Get info on the currently-loaded firmware
534  *
535  * This function also checks the device tree to see if the boot loader has
536  * uploaded a firmware already.
537  */
538 struct qe_firmware_info *qe_get_firmware_info(void)
539 {
540         static int initialized;
541         struct property *prop;
542         struct device_node *qe;
543         struct device_node *fw = NULL;
544         const char *sprop;
545         unsigned int i;
546 
547         /*
548          * If we haven't checked yet, and a driver hasn't uploaded a firmware
549          * yet, then check the device tree for information.
550          */
551         if (qe_firmware_uploaded)
552                 return &qe_firmware_info;
553 
554         if (initialized)
555                 return NULL;
556 
557         initialized = 1;
558 
559         /*
560          * Newer device trees have an "fsl,qe" compatible property for the QE
561          * node, but we still need to support older device trees.
562         */
563         qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
564         if (!qe) {
565                 qe = of_find_node_by_type(NULL, "qe");
566                 if (!qe)
567                         return NULL;
568         }
569 
570         /* Find the 'firmware' child node */
571         for_each_child_of_node(qe, fw) {
572                 if (strcmp(fw->name, "firmware") == 0)
573                         break;
574         }
575 
576         of_node_put(qe);
577 
578         /* Did we find the 'firmware' node? */
579         if (!fw)
580                 return NULL;
581 
582         qe_firmware_uploaded = 1;
583 
584         /* Copy the data into qe_firmware_info*/
585         sprop = of_get_property(fw, "id", NULL);
586         if (sprop)
587                 strncpy(qe_firmware_info.id, sprop,
588                         sizeof(qe_firmware_info.id) - 1);
589 
590         prop = of_find_property(fw, "extended-modes", NULL);
591         if (prop && (prop->length == sizeof(u64))) {
592                 const u64 *iprop = prop->value;
593 
594                 qe_firmware_info.extended_modes = *iprop;
595         }
596 
597         prop = of_find_property(fw, "virtual-traps", NULL);
598         if (prop && (prop->length == 32)) {
599                 const u32 *iprop = prop->value;
600 
601                 for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
602                         qe_firmware_info.vtraps[i] = iprop[i];
603         }
604 
605         of_node_put(fw);
606 
607         return &qe_firmware_info;
608 }
609 EXPORT_SYMBOL(qe_get_firmware_info);
610 
611 unsigned int qe_get_num_of_risc(void)
612 {
613         struct device_node *qe;
614         int size;
615         unsigned int num_of_risc = 0;
616         const u32 *prop;
617 
618         qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
619         if (!qe) {
620                 /* Older devices trees did not have an "fsl,qe"
621                  * compatible property, so we need to look for
622                  * the QE node by name.
623                  */
624                 qe = of_find_node_by_type(NULL, "qe");
625                 if (!qe)
626                         return num_of_risc;
627         }
628 
629         prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
630         if (prop && size == sizeof(*prop))
631                 num_of_risc = *prop;
632 
633         of_node_put(qe);
634 
635         return num_of_risc;
636 }
637 EXPORT_SYMBOL(qe_get_num_of_risc);
638 
639 unsigned int qe_get_num_of_snums(void)
640 {
641         struct device_node *qe;
642         int size;
643         unsigned int num_of_snums;
644         const u32 *prop;
645 
646         num_of_snums = 28; /* The default number of snum for threads is 28 */
647         qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
648         if (!qe) {
649                 /* Older devices trees did not have an "fsl,qe"
650                  * compatible property, so we need to look for
651                  * the QE node by name.
652                  */
653                 qe = of_find_node_by_type(NULL, "qe");
654                 if (!qe)
655                         return num_of_snums;
656         }
657 
658         prop = of_get_property(qe, "fsl,qe-num-snums", &size);
659         if (prop && size == sizeof(*prop)) {
660                 num_of_snums = *prop;
661                 if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
662                         /* No QE ever has fewer than 28 SNUMs */
663                         pr_err("QE: number of snum is invalid\n");
664                         of_node_put(qe);
665                         return -EINVAL;
666                 }
667         }
668 
669         of_node_put(qe);
670 
671         return num_of_snums;
672 }
673 EXPORT_SYMBOL(qe_get_num_of_snums);
674 
675 #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx)
676 static int qe_resume(struct platform_device *ofdev)
677 {
678         if (!qe_alive_during_sleep())
679                 qe_reset();
680         return 0;
681 }
682 
683 static int qe_probe(struct platform_device *ofdev)
684 {
685         return 0;
686 }
687 
688 static const struct of_device_id qe_ids[] = {
689         { .compatible = "fsl,qe", },
690         { },
691 };
692 
693 static struct platform_driver qe_driver = {
694         .driver = {
695                 .name = "fsl-qe",
696                 .owner = THIS_MODULE,
697                 .of_match_table = qe_ids,
698         },
699         .probe = qe_probe,
700         .resume = qe_resume,
701 };
702 
703 static int __init qe_drv_init(void)
704 {
705         return platform_driver_register(&qe_driver);
706 }
707 device_initcall(qe_drv_init);
708 #endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */
709 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp