diff options
author | Sonic Zhang <sonic.zhang@analog.com> | 2013-12-04 02:27:47 -0500 |
---|---|---|
committer | Steven Miao <realmz6@gmail.com> | 2014-01-29 02:12:20 -0500 |
commit | 1b6012394bec5dc653d495245c5495db08f817f6 (patch) | |
tree | 88c290099d8155fd3c4c5828843c29837c815e05 /arch | |
parent | cccdfcf728e2f322e8986a39bc02bf5aaa8fe8a7 (diff) |
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/blackfin/include/asm/def_LPBlackfin.h | 1 | ||||
-rw-r--r-- | arch/blackfin/mach-bf609/Kconfig | 6 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cache-c.c | 10 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 41 |
4 files changed, 37 insertions, 21 deletions
diff --git a/arch/blackfin/include/asm/def_LPBlackfin.h b/arch/blackfin/include/asm/def_LPBlackfin.h index ca67145c6a45..c5c8d8a3a5fa 100644 --- a/arch/blackfin/include/asm/def_LPBlackfin.h +++ b/arch/blackfin/include/asm/def_LPBlackfin.h | |||
@@ -544,6 +544,7 @@ do { \ | |||
544 | #define DCBS_P 0x04 /* L1 Data Cache Bank Select */ | 544 | #define DCBS_P 0x04 /* L1 Data Cache Bank Select */ |
545 | #define PORT_PREF0_P 0x12 /* DAG0 Port Preference */ | 545 | #define PORT_PREF0_P 0x12 /* DAG0 Port Preference */ |
546 | #define PORT_PREF1_P 0x13 /* DAG1 Port Preference */ | 546 | #define PORT_PREF1_P 0x13 /* DAG1 Port Preference */ |
547 | #define RDCHK 0x9 /* Enable L1 Parity Check */ | ||
547 | 548 | ||
548 | /* Masks */ | 549 | /* Masks */ |
549 | #define ENDM 0x00000001 /* (doesn't really exist) Enable | 550 | #define ENDM 0x00000001 /* (doesn't really exist) Enable |
diff --git a/arch/blackfin/mach-bf609/Kconfig b/arch/blackfin/mach-bf609/Kconfig index b0fca44110b0..6584190faeb8 100644 --- a/arch/blackfin/mach-bf609/Kconfig +++ b/arch/blackfin/mach-bf609/Kconfig | |||
@@ -17,6 +17,12 @@ config SEC_IRQ_PRIORITY_LEVELS | |||
17 | Divide the total number of interrupt priority levels into sub-levels. | 17 | Divide the total number of interrupt priority levels into sub-levels. |
18 | There is 2 ^ (SEC_IRQ_PRIORITY_LEVELS + 1) different levels. | 18 | There is 2 ^ (SEC_IRQ_PRIORITY_LEVELS + 1) different levels. |
19 | 19 | ||
20 | config L1_PARITY_CHECK | ||
21 | bool "Enable L1 parity check" | ||
22 | default n | ||
23 | help | ||
24 | Enable the L1 parity check in L1 sram. A fault event is raised | ||
25 | when L1 parity error is found. | ||
20 | 26 | ||
21 | comment "System Cross Bar Priority Assignment" | 27 | comment "System Cross Bar Priority Assignment" |
22 | 28 | ||
diff --git a/arch/blackfin/mach-common/cache-c.c b/arch/blackfin/mach-common/cache-c.c index 1a5a28829c6b..f4adedc92895 100644 --- a/arch/blackfin/mach-common/cache-c.c +++ b/arch/blackfin/mach-common/cache-c.c | |||
@@ -41,6 +41,16 @@ bfin_cache_init(struct cplb_entry *cplb_tbl, unsigned long cplb_addr, | |||
41 | unsigned long mem_mask) | 41 | unsigned long mem_mask) |
42 | { | 42 | { |
43 | int i; | 43 | int i; |
44 | #ifdef CONFIG_L1_PARITY_CHECK | ||
45 | u32 ctrl; | ||
46 | |||
47 | if (cplb_addr == DCPLB_ADDR0) { | ||
48 | ctrl = bfin_read32(mem_control) | (1 << RDCHK); | ||
49 | CSYNC(); | ||
50 | bfin_write32(mem_control, ctrl); | ||
51 | SSYNC(); | ||
52 | } | ||
53 | #endif | ||
44 | 54 | ||
45 | for (i = 0; i < MAX_CPLBS; i++) { | 55 | for (i = 0; i < MAX_CPLBS; i++) { |
46 | bfin_write32(cplb_addr + i * 4, cplb_tbl[i].addr); | 56 | bfin_write32(cplb_addr + i * 4, cplb_tbl[i].addr); |
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index ca75613231c8..867b7cef204c 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c | |||
@@ -471,13 +471,8 @@ void handle_sec_ssi_fault(uint32_t gstat) | |||
471 | 471 | ||
472 | } | 472 | } |
473 | 473 | ||
474 | void handle_sec_fault(unsigned int irq, struct irq_desc *desc) | 474 | void handle_sec_fault(uint32_t sec_gstat) |
475 | { | 475 | { |
476 | uint32_t sec_gstat; | ||
477 | |||
478 | raw_spin_lock(&desc->lock); | ||
479 | |||
480 | sec_gstat = bfin_read32(SEC_GSTAT); | ||
481 | if (sec_gstat & SEC_GSTAT_ERR) { | 476 | if (sec_gstat & SEC_GSTAT_ERR) { |
482 | 477 | ||
483 | switch (sec_gstat & SEC_GSTAT_ERRC) { | 478 | switch (sec_gstat & SEC_GSTAT_ERRC) { |
@@ -494,18 +489,16 @@ void handle_sec_fault(unsigned int irq, struct irq_desc *desc) | |||
494 | 489 | ||
495 | 490 | ||
496 | } | 491 | } |
497 | |||
498 | raw_spin_unlock(&desc->lock); | ||
499 | |||
500 | handle_fasteoi_irq(irq, desc); | ||
501 | } | 492 | } |
502 | 493 | ||
503 | void handle_core_fault(unsigned int irq, struct irq_desc *desc) | 494 | static struct irqaction bfin_fault_irq = { |
495 | .name = "Blackfin fault", | ||
496 | }; | ||
497 | |||
498 | static irqreturn_t bfin_fault_routine(int irq, void *data) | ||
504 | { | 499 | { |
505 | struct pt_regs *fp = get_irq_regs(); | 500 | struct pt_regs *fp = get_irq_regs(); |
506 | 501 | ||
507 | raw_spin_lock(&desc->lock); | ||
508 | |||
509 | switch (irq) { | 502 | switch (irq) { |
510 | case IRQ_C0_DBL_FAULT: | 503 | case IRQ_C0_DBL_FAULT: |
511 | double_fault_c(fp); | 504 | double_fault_c(fp); |
@@ -522,11 +515,15 @@ void handle_core_fault(unsigned int irq, struct irq_desc *desc) | |||
522 | case IRQ_C0_NMI_L1_PARITY_ERR: | 515 | case IRQ_C0_NMI_L1_PARITY_ERR: |
523 | panic("Core 0 NMI L1 parity error"); | 516 | panic("Core 0 NMI L1 parity error"); |
524 | break; | 517 | break; |
518 | case IRQ_SEC_ERR: | ||
519 | pr_err("SEC error\n"); | ||
520 | handle_sec_fault(bfin_read32(SEC_GSTAT)); | ||
521 | break; | ||
525 | default: | 522 | default: |
526 | panic("Core 1 fault %d occurs unexpectedly", irq); | 523 | panic("Unknown fault %d", irq); |
527 | } | 524 | } |
528 | 525 | ||
529 | raw_spin_unlock(&desc->lock); | 526 | return IRQ_HANDLED; |
530 | } | 527 | } |
531 | #endif /* SEC_GCTL */ | 528 | #endif /* SEC_GCTL */ |
532 | 529 | ||
@@ -1195,12 +1192,7 @@ int __init init_arch_irq(void) | |||
1195 | handle_percpu_irq); | 1192 | handle_percpu_irq); |
1196 | } else { | 1193 | } else { |
1197 | irq_set_chip(irq, &bfin_sec_irqchip); | 1194 | irq_set_chip(irq, &bfin_sec_irqchip); |
1198 | if (irq == IRQ_SEC_ERR) | 1195 | irq_set_handler(irq, handle_fasteoi_irq); |
1199 | irq_set_handler(irq, handle_sec_fault); | ||
1200 | else if (irq >= IRQ_C0_DBL_FAULT && irq < CORE_IRQS) | ||
1201 | irq_set_handler(irq, handle_core_fault); | ||
1202 | else | ||
1203 | irq_set_handler(irq, handle_fasteoi_irq); | ||
1204 | __irq_set_preflow_handler(irq, bfin_sec_preflow_handler); | 1196 | __irq_set_preflow_handler(irq, bfin_sec_preflow_handler); |
1205 | } | 1197 | } |
1206 | } | 1198 | } |
@@ -1239,6 +1231,13 @@ int __init init_arch_irq(void) | |||
1239 | register_syscore_ops(&sec_pm_syscore_ops); | 1231 | register_syscore_ops(&sec_pm_syscore_ops); |
1240 | #endif | 1232 | #endif |
1241 | 1233 | ||
1234 | bfin_fault_irq.handler = bfin_fault_routine; | ||
1235 | #ifdef CONFIG_L1_PARITY_CHECK | ||
1236 | setup_irq(IRQ_C0_NMI_L1_PARITY_ERR, &bfin_fault_irq); | ||
1237 | #endif | ||
1238 | setup_irq(IRQ_C0_DBL_FAULT, &bfin_fault_irq); | ||
1239 | setup_irq(IRQ_SEC_ERR, &bfin_fault_irq); | ||
1240 | |||
1242 | return 0; | 1241 | return 0; |
1243 | } | 1242 | } |
1244 | 1243 | ||