blackfin: Support L1 SRAM parity checking feature on bf60x
authorSonic Zhang <sonic.zhang@analog.com>
Wed, 4 Dec 2013 07:27:47 +0000 (15:27 +0800)
committerSteven Miao <realmz6@gmail.com>
Wed, 29 Jan 2014 07:12:20 +0000 (15:12 +0800)
Move code for the SEC faults from the IRQ hanlders into IRQ actions.
refine bfin fault routine handle

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Steven Miao <realmz6@gmail.com>
arch/blackfin/include/asm/def_LPBlackfin.h
arch/blackfin/mach-bf609/Kconfig
arch/blackfin/mach-common/cache-c.c
arch/blackfin/mach-common/ints-priority.c

index ca67145..c5c8d8a 100644 (file)
@@ -544,6 +544,7 @@ do { \
 #define DCBS_P                 0x04    /* L1 Data Cache Bank Select */
 #define PORT_PREF0_P           0x12    /* DAG0 Port Preference */
 #define PORT_PREF1_P           0x13    /* DAG1 Port Preference */
+#define RDCHK                  0x9     /* Enable L1 Parity Check */
 
 /* Masks */
 #define ENDM               0x00000001  /* (doesn't really exist) Enable
index b0fca44..6584190 100644 (file)
@@ -17,6 +17,12 @@ config SEC_IRQ_PRIORITY_LEVELS
          Divide the total number of interrupt priority levels into sub-levels.
          There is 2 ^ (SEC_IRQ_PRIORITY_LEVELS + 1) different levels.
 
+config L1_PARITY_CHECK
+       bool "Enable L1 parity check"
+       default n
+       help
+         Enable the L1 parity check in L1 sram. A fault event is raised
+         when L1 parity error is found.
 
 comment "System Cross Bar Priority Assignment"
 
index 1a5a288..f4adedc 100644 (file)
@@ -41,6 +41,16 @@ bfin_cache_init(struct cplb_entry *cplb_tbl, unsigned long cplb_addr,
                 unsigned long mem_mask)
 {
        int i;
+#ifdef CONFIG_L1_PARITY_CHECK
+       u32 ctrl;
+
+       if (cplb_addr == DCPLB_ADDR0) {
+               ctrl = bfin_read32(mem_control) | (1 << RDCHK);
+               CSYNC();
+               bfin_write32(mem_control, ctrl);
+               SSYNC();
+       }
+#endif
 
        for (i = 0; i < MAX_CPLBS; i++) {
                bfin_write32(cplb_addr + i * 4, cplb_tbl[i].addr);
index ca75613..867b7ce 100644 (file)
@@ -471,13 +471,8 @@ void handle_sec_ssi_fault(uint32_t gstat)
 
 }
 
-void handle_sec_fault(unsigned int irq, struct irq_desc *desc)
+void handle_sec_fault(uint32_t sec_gstat)
 {
-       uint32_t sec_gstat;
-
-       raw_spin_lock(&desc->lock);
-
-       sec_gstat = bfin_read32(SEC_GSTAT);
        if (sec_gstat & SEC_GSTAT_ERR) {
 
                switch (sec_gstat & SEC_GSTAT_ERRC) {
@@ -494,18 +489,16 @@ void handle_sec_fault(unsigned int irq, struct irq_desc *desc)
 
 
        }
-
-       raw_spin_unlock(&desc->lock);
-
-       handle_fasteoi_irq(irq, desc);
 }
 
-void handle_core_fault(unsigned int irq, struct irq_desc *desc)
+static struct irqaction bfin_fault_irq = {
+       .name = "Blackfin fault",
+};
+
+static irqreturn_t bfin_fault_routine(int irq, void *data)
 {
        struct pt_regs *fp = get_irq_regs();
 
-       raw_spin_lock(&desc->lock);
-
        switch (irq) {
        case IRQ_C0_DBL_FAULT:
                double_fault_c(fp);
@@ -522,11 +515,15 @@ void handle_core_fault(unsigned int irq, struct irq_desc *desc)
        case IRQ_C0_NMI_L1_PARITY_ERR:
                panic("Core 0 NMI L1 parity error");
                break;
+       case IRQ_SEC_ERR:
+               pr_err("SEC error\n");
+               handle_sec_fault(bfin_read32(SEC_GSTAT));
+               break;
        default:
-               panic("Core 1 fault %d occurs unexpectedly", irq);
+               panic("Unknown fault %d", irq);
        }
 
-       raw_spin_unlock(&desc->lock);
+       return IRQ_HANDLED;
 }
 #endif /* SEC_GCTL */
 
@@ -1195,12 +1192,7 @@ int __init init_arch_irq(void)
                                handle_percpu_irq);
                } else {
                        irq_set_chip(irq, &bfin_sec_irqchip);
-                       if (irq == IRQ_SEC_ERR)
-                               irq_set_handler(irq, handle_sec_fault);
-                       else if (irq >= IRQ_C0_DBL_FAULT && irq < CORE_IRQS)
-                               irq_set_handler(irq, handle_core_fault);
-                       else
-                               irq_set_handler(irq, handle_fasteoi_irq);
+                       irq_set_handler(irq, handle_fasteoi_irq);
                        __irq_set_preflow_handler(irq, bfin_sec_preflow_handler);
                }
        }
@@ -1239,6 +1231,13 @@ int __init init_arch_irq(void)
        register_syscore_ops(&sec_pm_syscore_ops);
 #endif
 
+       bfin_fault_irq.handler = bfin_fault_routine;
+#ifdef CONFIG_L1_PARITY_CHECK
+       setup_irq(IRQ_C0_NMI_L1_PARITY_ERR, &bfin_fault_irq);
+#endif
+       setup_irq(IRQ_C0_DBL_FAULT, &bfin_fault_irq);
+       setup_irq(IRQ_SEC_ERR, &bfin_fault_irq);
+
        return 0;
 }