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: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Steven Miao <realmz6@gmail.com>
This commit is contained in:
parent
cccdfcf728
commit
1b6012394b
|
@ -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
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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,12 +1192,7 @@ 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_fasteoi_irq);
|
||||||
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_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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue