diff options
Diffstat (limited to 'drivers/edac/cpc925_edac.c')
-rw-r--r-- | drivers/edac/cpc925_edac.c | 67 |
1 files changed, 64 insertions, 3 deletions
diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index a687a0d16962..a774c0ddaf5b 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c | |||
@@ -90,6 +90,7 @@ enum apimask_bits { | |||
90 | ECC_MASK_ENABLE = (APIMASK_ECC_UE_H | APIMASK_ECC_CE_H | | 90 | ECC_MASK_ENABLE = (APIMASK_ECC_UE_H | APIMASK_ECC_CE_H | |
91 | APIMASK_ECC_UE_L | APIMASK_ECC_CE_L), | 91 | APIMASK_ECC_UE_L | APIMASK_ECC_CE_L), |
92 | }; | 92 | }; |
93 | #define APIMASK_ADI(n) CPC925_BIT(((n)+1)) | ||
93 | 94 | ||
94 | /************************************************************ | 95 | /************************************************************ |
95 | * Processor Interface Exception Register (APIEXCP) | 96 | * Processor Interface Exception Register (APIEXCP) |
@@ -581,16 +582,73 @@ static void cpc925_mc_check(struct mem_ctl_info *mci) | |||
581 | } | 582 | } |
582 | 583 | ||
583 | /******************** CPU err device********************************/ | 584 | /******************** CPU err device********************************/ |
585 | static u32 cpc925_cpu_mask_disabled(void) | ||
586 | { | ||
587 | struct device_node *cpus; | ||
588 | struct device_node *cpunode = NULL; | ||
589 | static u32 mask = 0; | ||
590 | |||
591 | /* use cached value if available */ | ||
592 | if (mask != 0) | ||
593 | return mask; | ||
594 | |||
595 | mask = APIMASK_ADI0 | APIMASK_ADI1; | ||
596 | |||
597 | cpus = of_find_node_by_path("/cpus"); | ||
598 | if (cpus == NULL) { | ||
599 | cpc925_printk(KERN_DEBUG, "No /cpus node !\n"); | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | while ((cpunode = of_get_next_child(cpus, cpunode)) != NULL) { | ||
604 | const u32 *reg = of_get_property(cpunode, "reg", NULL); | ||
605 | |||
606 | if (strcmp(cpunode->type, "cpu")) { | ||
607 | cpc925_printk(KERN_ERR, "Not a cpu node in /cpus: %s\n", cpunode->name); | ||
608 | continue; | ||
609 | } | ||
610 | |||
611 | if (reg == NULL || *reg > 2) { | ||
612 | cpc925_printk(KERN_ERR, "Bad reg value at %s\n", cpunode->full_name); | ||
613 | continue; | ||
614 | } | ||
615 | |||
616 | mask &= ~APIMASK_ADI(*reg); | ||
617 | } | ||
618 | |||
619 | if (mask != (APIMASK_ADI0 | APIMASK_ADI1)) { | ||
620 | /* We assume that each CPU sits on it's own PI and that | ||
621 | * for present CPUs the reg property equals to the PI | ||
622 | * interface id */ | ||
623 | cpc925_printk(KERN_WARNING, | ||
624 | "Assuming PI id is equal to CPU MPIC id!\n"); | ||
625 | } | ||
626 | |||
627 | of_node_put(cpunode); | ||
628 | of_node_put(cpus); | ||
629 | |||
630 | return mask; | ||
631 | } | ||
632 | |||
584 | /* Enable CPU Errors detection */ | 633 | /* Enable CPU Errors detection */ |
585 | static void cpc925_cpu_init(struct cpc925_dev_info *dev_info) | 634 | static void cpc925_cpu_init(struct cpc925_dev_info *dev_info) |
586 | { | 635 | { |
587 | u32 apimask; | 636 | u32 apimask; |
637 | u32 cpumask; | ||
588 | 638 | ||
589 | apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET); | 639 | apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET); |
590 | if ((apimask & CPU_MASK_ENABLE) == 0) { | 640 | |
591 | apimask |= CPU_MASK_ENABLE; | 641 | cpumask = cpc925_cpu_mask_disabled(); |
592 | __raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET); | 642 | if (apimask & cpumask) { |
643 | cpc925_printk(KERN_WARNING, "CPU(s) not present, " | ||
644 | "but enabled in APIMASK, disabling\n"); | ||
645 | apimask &= ~cpumask; | ||
593 | } | 646 | } |
647 | |||
648 | if ((apimask & CPU_MASK_ENABLE) == 0) | ||
649 | apimask |= CPU_MASK_ENABLE; | ||
650 | |||
651 | __raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET); | ||
594 | } | 652 | } |
595 | 653 | ||
596 | /* Disable CPU Errors detection */ | 654 | /* Disable CPU Errors detection */ |
@@ -622,6 +680,9 @@ static void cpc925_cpu_check(struct edac_device_ctl_info *edac_dev) | |||
622 | if ((apiexcp & CPU_EXCP_DETECTED) == 0) | 680 | if ((apiexcp & CPU_EXCP_DETECTED) == 0) |
623 | return; | 681 | return; |
624 | 682 | ||
683 | if ((apiexcp & ~cpc925_cpu_mask_disabled()) == 0) | ||
684 | return; | ||
685 | |||
625 | apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET); | 686 | apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET); |
626 | cpc925_printk(KERN_INFO, "Processor Interface Fault\n" | 687 | cpc925_printk(KERN_INFO, "Processor Interface Fault\n" |
627 | "Processor Interface register dump:\n"); | 688 | "Processor Interface register dump:\n"); |