Commit 1b601239 authored by Sonic Zhang's avatar Sonic Zhang Committed by Steven Miao

blackfin: Support L1 SRAM parity checking feature on bf60x

Move code for the SEC faults from the IRQ hanlders into IRQ actions.
refine bfin fault routine handle
Signed-off-by: default avatarSonic Zhang <sonic.zhang@analog.com>
Signed-off-by: default avatarSteven Miao <realmz6@gmail.com>
parent cccdfcf7
...@@ -544,6 +544,7 @@ do { \ ...@@ -544,6 +544,7 @@ do { \
#define DCBS_P 0x04 /* L1 Data Cache Bank Select */ #define DCBS_P 0x04 /* L1 Data Cache Bank Select */
#define PORT_PREF0_P 0x12 /* DAG0 Port Preference */ #define PORT_PREF0_P 0x12 /* DAG0 Port Preference */
#define PORT_PREF1_P 0x13 /* DAG1 Port Preference */ #define PORT_PREF1_P 0x13 /* DAG1 Port Preference */
#define RDCHK 0x9 /* Enable L1 Parity Check */
/* Masks */ /* Masks */
#define ENDM 0x00000001 /* (doesn't really exist) Enable #define ENDM 0x00000001 /* (doesn't really exist) Enable
......
...@@ -17,6 +17,12 @@ config SEC_IRQ_PRIORITY_LEVELS ...@@ -17,6 +17,12 @@ config SEC_IRQ_PRIORITY_LEVELS
Divide the total number of interrupt priority levels into sub-levels. Divide the total number of interrupt priority levels into sub-levels.
There is 2 ^ (SEC_IRQ_PRIORITY_LEVELS + 1) different 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" comment "System Cross Bar Priority Assignment"
......
...@@ -41,6 +41,16 @@ bfin_cache_init(struct cplb_entry *cplb_tbl, unsigned long cplb_addr, ...@@ -41,6 +41,16 @@ bfin_cache_init(struct cplb_entry *cplb_tbl, unsigned long cplb_addr,
unsigned long mem_mask) unsigned long mem_mask)
{ {
int i; 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++) { for (i = 0; i < MAX_CPLBS; i++) {
bfin_write32(cplb_addr + i * 4, cplb_tbl[i].addr); bfin_write32(cplb_addr + i * 4, cplb_tbl[i].addr);
......
...@@ -471,13 +471,8 @@ void handle_sec_ssi_fault(uint32_t gstat) ...@@ -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) { if (sec_gstat & SEC_GSTAT_ERR) {
switch (sec_gstat & SEC_GSTAT_ERRC) { switch (sec_gstat & SEC_GSTAT_ERRC) {
...@@ -494,18 +489,16 @@ void handle_sec_fault(unsigned int irq, struct irq_desc *desc) ...@@ -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(); struct pt_regs *fp = get_irq_regs();
raw_spin_lock(&desc->lock);
switch (irq) { switch (irq) {
case IRQ_C0_DBL_FAULT: case IRQ_C0_DBL_FAULT:
double_fault_c(fp); double_fault_c(fp);
...@@ -522,11 +515,15 @@ void handle_core_fault(unsigned int irq, struct irq_desc *desc) ...@@ -522,11 +515,15 @@ void handle_core_fault(unsigned int irq, struct irq_desc *desc)
case IRQ_C0_NMI_L1_PARITY_ERR: case IRQ_C0_NMI_L1_PARITY_ERR:
panic("Core 0 NMI L1 parity error"); panic("Core 0 NMI L1 parity error");
break; break;
case IRQ_SEC_ERR:
pr_err("SEC error\n");
handle_sec_fault(bfin_read32(SEC_GSTAT));
break;
default: 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 */ #endif /* SEC_GCTL */
...@@ -1195,11 +1192,6 @@ int __init init_arch_irq(void) ...@@ -1195,11 +1192,6 @@ int __init init_arch_irq(void)
handle_percpu_irq); handle_percpu_irq);
} else { } else {
irq_set_chip(irq, &bfin_sec_irqchip); 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); __irq_set_preflow_handler(irq, bfin_sec_preflow_handler);
} }
...@@ -1239,6 +1231,13 @@ int __init init_arch_irq(void) ...@@ -1239,6 +1231,13 @@ int __init init_arch_irq(void)
register_syscore_ops(&sec_pm_syscore_ops); register_syscore_ops(&sec_pm_syscore_ops);
#endif #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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment