aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/qe_lib/qe.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/qe_lib/qe.c')
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c356
1 files changed, 332 insertions, 24 deletions
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 3d57d3835b04..5ef844da9355 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -25,6 +25,7 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/ioport.h> 27#include <linux/ioport.h>
28#include <linux/crc32.h>
28#include <asm/irq.h> 29#include <asm/irq.h>
29#include <asm/page.h> 30#include <asm/page.h>
30#include <asm/pgtable.h> 31#include <asm/pgtable.h>
@@ -64,17 +65,22 @@ static phys_addr_t qebase = -1;
64phys_addr_t get_qe_base(void) 65phys_addr_t get_qe_base(void)
65{ 66{
66 struct device_node *qe; 67 struct device_node *qe;
68 unsigned int size;
69 const void *prop;
67 70
68 if (qebase != -1) 71 if (qebase != -1)
69 return qebase; 72 return qebase;
70 73
71 qe = of_find_node_by_type(NULL, "qe"); 74 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
72 if (qe) { 75 if (!qe) {
73 unsigned int size; 76 qe = of_find_node_by_type(NULL, "qe");
74 const void *prop = of_get_property(qe, "reg", &size); 77 if (!qe)
75 qebase = of_translate_address(qe, prop); 78 return qebase;
76 of_node_put(qe); 79 }
77 }; 80
81 prop = of_get_property(qe, "reg", &size);
82 qebase = of_translate_address(qe, prop);
83 of_node_put(qe);
78 84
79 return qebase; 85 return qebase;
80} 86}
@@ -152,34 +158,45 @@ static unsigned int brg_clk = 0;
152unsigned int get_brg_clk(void) 158unsigned int get_brg_clk(void)
153{ 159{
154 struct device_node *qe; 160 struct device_node *qe;
161 unsigned int size;
162 const u32 *prop;
163
155 if (brg_clk) 164 if (brg_clk)
156 return brg_clk; 165 return brg_clk;
157 166
158 qe = of_find_node_by_type(NULL, "qe"); 167 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
159 if (qe) { 168 if (!qe) {
160 unsigned int size; 169 qe = of_find_node_by_type(NULL, "qe");
161 const u32 *prop = of_get_property(qe, "brg-frequency", &size); 170 if (!qe)
162 brg_clk = *prop; 171 return brg_clk;
163 of_node_put(qe); 172 }
164 }; 173
174 prop = of_get_property(qe, "brg-frequency", &size);
175 if (!prop || size != sizeof(*prop))
176 return brg_clk;
177
178 brg_clk = *prop;
179 of_node_put(qe);
180
165 return brg_clk; 181 return brg_clk;
166} 182}
167 183
168/* Program the BRG to the given sampling rate and multiplier 184/* Program the BRG to the given sampling rate and multiplier
169 * 185 *
170 * @brg: the BRG, 1-16 186 * @brg: the BRG, QE_BRG1 - QE_BRG16
171 * @rate: the desired sampling rate 187 * @rate: the desired sampling rate
172 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or 188 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
173 * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01, 189 * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
174 * then 'multiplier' should be 8. 190 * then 'multiplier' should be 8.
175 *
176 * Also note that the value programmed into the BRGC register must be even.
177 */ 191 */
178void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier) 192int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
179{ 193{
180 u32 divisor, tempval; 194 u32 divisor, tempval;
181 u32 div16 = 0; 195 u32 div16 = 0;
182 196
197 if ((brg < QE_BRG1) || (brg > QE_BRG16))
198 return -EINVAL;
199
183 divisor = get_brg_clk() / (rate * multiplier); 200 divisor = get_brg_clk() / (rate * multiplier);
184 201
185 if (divisor > QE_BRGC_DIVISOR_MAX + 1) { 202 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
@@ -196,8 +213,43 @@ void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
196 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | 213 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
197 QE_BRGC_ENABLE | div16; 214 QE_BRGC_ENABLE | div16;
198 215
199 out_be32(&qe_immr->brg.brgc[brg - 1], tempval); 216 out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
217
218 return 0;
219}
220EXPORT_SYMBOL(qe_setbrg);
221
222/* Convert a string to a QE clock source enum
223 *
224 * This function takes a string, typically from a property in the device
225 * tree, and returns the corresponding "enum qe_clock" value.
226*/
227enum qe_clock qe_clock_source(const char *source)
228{
229 unsigned int i;
230
231 if (strcasecmp(source, "none") == 0)
232 return QE_CLK_NONE;
233
234 if (strncasecmp(source, "brg", 3) == 0) {
235 i = simple_strtoul(source + 3, NULL, 10);
236 if ((i >= 1) && (i <= 16))
237 return (QE_BRG1 - 1) + i;
238 else
239 return QE_CLK_DUMMY;
240 }
241
242 if (strncasecmp(source, "clk", 3) == 0) {
243 i = simple_strtoul(source + 3, NULL, 10);
244 if ((i >= 1) && (i <= 24))
245 return (QE_CLK1 - 1) + i;
246 else
247 return QE_CLK_DUMMY;
248 }
249
250 return QE_CLK_DUMMY;
200} 251}
252EXPORT_SYMBOL(qe_clock_source);
201 253
202/* Initialize SNUMs (thread serial numbers) according to 254/* Initialize SNUMs (thread serial numbers) according to
203 * QE Module Control chapter, SNUM table 255 * QE Module Control chapter, SNUM table
@@ -285,7 +337,7 @@ static rh_info_t qe_muram_info;
285static void qe_muram_init(void) 337static void qe_muram_init(void)
286{ 338{
287 struct device_node *np; 339 struct device_node *np;
288 u32 address; 340 const u32 *address;
289 u64 size; 341 u64 size;
290 unsigned int flags; 342 unsigned int flags;
291 343
@@ -298,11 +350,21 @@ static void qe_muram_init(void)
298 /* XXX: This is a subset of the available muram. It 350 /* XXX: This is a subset of the available muram. It
299 * varies with the processor and the microcode patches activated. 351 * varies with the processor and the microcode patches activated.
300 */ 352 */
301 if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) { 353 np = of_find_compatible_node(NULL, NULL, "fsl,qe-muram-data");
302 address = *of_get_address(np, 0, &size, &flags); 354 if (!np) {
303 of_node_put(np); 355 np = of_find_node_by_name(NULL, "data-only");
304 rh_attach_region(&qe_muram_info, address, (int) size); 356 if (!np) {
357 WARN_ON(1);
358 return;
359 }
305 } 360 }
361
362 address = of_get_address(np, 0, &size, &flags);
363 WARN_ON(!address);
364
365 of_node_put(np);
366 if (address)
367 rh_attach_region(&qe_muram_info, *address, (int)size);
306} 368}
307 369
308/* This function returns an index into the MURAM area. 370/* This function returns an index into the MURAM area.
@@ -358,3 +420,249 @@ void *qe_muram_addr(unsigned long offset)
358 return (void *)&qe_immr->muram[offset]; 420 return (void *)&qe_immr->muram[offset];
359} 421}
360EXPORT_SYMBOL(qe_muram_addr); 422EXPORT_SYMBOL(qe_muram_addr);
423
424/* The maximum number of RISCs we support */
425#define MAX_QE_RISC 2
426
427/* Firmware information stored here for qe_get_firmware_info() */
428static struct qe_firmware_info qe_firmware_info;
429
430/*
431 * Set to 1 if QE firmware has been uploaded, and therefore
432 * qe_firmware_info contains valid data.
433 */
434static int qe_firmware_uploaded;
435
436/*
437 * Upload a QE microcode
438 *
439 * This function is a worker function for qe_upload_firmware(). It does
440 * the actual uploading of the microcode.
441 */
442static void qe_upload_microcode(const void *base,
443 const struct qe_microcode *ucode)
444{
445 const __be32 *code = base + be32_to_cpu(ucode->code_offset);
446 unsigned int i;
447
448 if (ucode->major || ucode->minor || ucode->revision)
449 printk(KERN_INFO "qe-firmware: "
450 "uploading microcode '%s' version %u.%u.%u\n",
451 ucode->id, ucode->major, ucode->minor, ucode->revision);
452 else
453 printk(KERN_INFO "qe-firmware: "
454 "uploading microcode '%s'\n", ucode->id);
455
456 /* Use auto-increment */
457 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
458 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
459
460 for (i = 0; i < be32_to_cpu(ucode->count); i++)
461 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
462}
463
464/*
465 * Upload a microcode to the I-RAM at a specific address.
466 *
467 * See Documentation/powerpc/qe-firmware.txt for information on QE microcode
468 * uploading.
469 *
470 * Currently, only version 1 is supported, so the 'version' field must be
471 * set to 1.
472 *
473 * The SOC model and revision are not validated, they are only displayed for
474 * informational purposes.
475 *
476 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
477 * all of the microcode structures, minus the CRC.
478 *
479 * 'length' is the size that the structure says it is, including the CRC.
480 */
481int qe_upload_firmware(const struct qe_firmware *firmware)
482{
483 unsigned int i;
484 unsigned int j;
485 u32 crc;
486 size_t calc_size = sizeof(struct qe_firmware);
487 size_t length;
488 const struct qe_header *hdr;
489
490 if (!firmware) {
491 printk(KERN_ERR "qe-firmware: invalid pointer\n");
492 return -EINVAL;
493 }
494
495 hdr = &firmware->header;
496 length = be32_to_cpu(hdr->length);
497
498 /* Check the magic */
499 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
500 (hdr->magic[2] != 'F')) {
501 printk(KERN_ERR "qe-firmware: not a microcode\n");
502 return -EPERM;
503 }
504
505 /* Check the version */
506 if (hdr->version != 1) {
507 printk(KERN_ERR "qe-firmware: unsupported version\n");
508 return -EPERM;
509 }
510
511 /* Validate some of the fields */
512 if ((firmware->count < 1) || (firmware->count >= MAX_QE_RISC)) {
513 printk(KERN_ERR "qe-firmware: invalid data\n");
514 return -EINVAL;
515 }
516
517 /* Validate the length and check if there's a CRC */
518 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
519
520 for (i = 0; i < firmware->count; i++)
521 /*
522 * For situations where the second RISC uses the same microcode
523 * as the first, the 'code_offset' and 'count' fields will be
524 * zero, so it's okay to add those.
525 */
526 calc_size += sizeof(__be32) *
527 be32_to_cpu(firmware->microcode[i].count);
528
529 /* Validate the length */
530 if (length != calc_size + sizeof(__be32)) {
531 printk(KERN_ERR "qe-firmware: invalid length\n");
532 return -EPERM;
533 }
534
535 /* Validate the CRC */
536 crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
537 if (crc != crc32(0, firmware, calc_size)) {
538 printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
539 return -EIO;
540 }
541
542 /*
543 * If the microcode calls for it, split the I-RAM.
544 */
545 if (!firmware->split)
546 setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
547
548 if (firmware->soc.model)
549 printk(KERN_INFO
550 "qe-firmware: firmware '%s' for %u V%u.%u\n",
551 firmware->id, be16_to_cpu(firmware->soc.model),
552 firmware->soc.major, firmware->soc.minor);
553 else
554 printk(KERN_INFO "qe-firmware: firmware '%s'\n",
555 firmware->id);
556
557 /*
558 * The QE only supports one microcode per RISC, so clear out all the
559 * saved microcode information and put in the new.
560 */
561 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
562 strcpy(qe_firmware_info.id, firmware->id);
563 qe_firmware_info.extended_modes = firmware->extended_modes;
564 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
565 sizeof(firmware->vtraps));
566
567 /* Loop through each microcode. */
568 for (i = 0; i < firmware->count; i++) {
569 const struct qe_microcode *ucode = &firmware->microcode[i];
570
571 /* Upload a microcode if it's present */
572 if (ucode->code_offset)
573 qe_upload_microcode(firmware, ucode);
574
575 /* Program the traps for this processor */
576 for (j = 0; j < 16; j++) {
577 u32 trap = be32_to_cpu(ucode->traps[j]);
578
579 if (trap)
580 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
581 }
582
583 /* Enable traps */
584 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
585 }
586
587 qe_firmware_uploaded = 1;
588
589 return 0;
590}
591EXPORT_SYMBOL(qe_upload_firmware);
592
593/*
594 * Get info on the currently-loaded firmware
595 *
596 * This function also checks the device tree to see if the boot loader has
597 * uploaded a firmware already.
598 */
599struct qe_firmware_info *qe_get_firmware_info(void)
600{
601 static int initialized;
602 struct property *prop;
603 struct device_node *qe;
604 struct device_node *fw = NULL;
605 const char *sprop;
606 unsigned int i;
607
608 /*
609 * If we haven't checked yet, and a driver hasn't uploaded a firmware
610 * yet, then check the device tree for information.
611 */
612 if (initialized || qe_firmware_uploaded)
613 return NULL;
614
615 initialized = 1;
616
617 /*
618 * Newer device trees have an "fsl,qe" compatible property for the QE
619 * node, but we still need to support older device trees.
620 */
621 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
622 if (!qe) {
623 qe = of_find_node_by_type(NULL, "qe");
624 if (!qe)
625 return NULL;
626 }
627
628 /* Find the 'firmware' child node */
629 for_each_child_of_node(qe, fw) {
630 if (strcmp(fw->name, "firmware") == 0)
631 break;
632 }
633
634 of_node_put(qe);
635
636 /* Did we find the 'firmware' node? */
637 if (!fw)
638 return NULL;
639
640 qe_firmware_uploaded = 1;
641
642 /* Copy the data into qe_firmware_info*/
643 sprop = of_get_property(fw, "id", NULL);
644 if (sprop)
645 strncpy(qe_firmware_info.id, sprop,
646 sizeof(qe_firmware_info.id) - 1);
647
648 prop = of_find_property(fw, "extended-modes", NULL);
649 if (prop && (prop->length == sizeof(u64))) {
650 const u64 *iprop = prop->value;
651
652 qe_firmware_info.extended_modes = *iprop;
653 }
654
655 prop = of_find_property(fw, "virtual-traps", NULL);
656 if (prop && (prop->length == 32)) {
657 const u32 *iprop = prop->value;
658
659 for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
660 qe_firmware_info.vtraps[i] = iprop[i];
661 }
662
663 of_node_put(fw);
664
665 return &qe_firmware_info;
666}
667EXPORT_SYMBOL(qe_get_firmware_info);
668