diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/cputable.h | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/dbell.h | 43 | ||||
-rw-r--r-- | arch/powerpc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/dbell.c | 44 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_fsl_booke.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 21 |
6 files changed, 117 insertions, 3 deletions
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 4911104791c3..fca161190db4 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -145,6 +145,7 @@ extern const char *powerpc_base_platform; | |||
145 | #define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) | 145 | #define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) |
146 | #define CPU_FTR_L2CSR ASM_CONST(0x0000000000000080) | 146 | #define CPU_FTR_L2CSR ASM_CONST(0x0000000000000080) |
147 | #define CPU_FTR_601 ASM_CONST(0x0000000000000100) | 147 | #define CPU_FTR_601 ASM_CONST(0x0000000000000100) |
148 | #define CPU_FTR_DBELL ASM_CONST(0x0000000000000200) | ||
148 | #define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) | 149 | #define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) |
149 | #define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) | 150 | #define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) |
150 | #define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) | 151 | #define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) |
@@ -373,7 +374,8 @@ extern const char *powerpc_base_platform; | |||
373 | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE) | 374 | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE) |
374 | #define CPU_FTRS_E500MC (CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \ | 375 | #define CPU_FTRS_E500MC (CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \ |
375 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \ | 376 | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \ |
376 | CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE) | 377 | CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \ |
378 | CPU_FTR_DBELL) | ||
377 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) | 379 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) |
378 | 380 | ||
379 | /* 64-bit CPUs */ | 381 | /* 64-bit CPUs */ |
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h new file mode 100644 index 000000000000..501189a543d1 --- /dev/null +++ b/arch/powerpc/include/asm/dbell.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Freescale Semicondutor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * provides masks and opcode images for use by code generation, emulation | ||
10 | * and for instructions that older assemblers might not know about | ||
11 | */ | ||
12 | #ifndef _ASM_POWERPC_DBELL_H | ||
13 | #define _ASM_POWERPC_DBELL_H | ||
14 | |||
15 | #include <linux/smp.h> | ||
16 | #include <linux/threads.h> | ||
17 | |||
18 | #include <asm/ppc-opcode.h> | ||
19 | |||
20 | #define PPC_DBELL_MSG_BRDCAST (0x04000000) | ||
21 | #define PPC_DBELL_TYPE(x) (((x) & 0xf) << 28) | ||
22 | enum ppc_dbell { | ||
23 | PPC_DBELL = 0, /* doorbell */ | ||
24 | PPC_DBELL_CRIT = 1, /* critical doorbell */ | ||
25 | PPC_G_DBELL = 2, /* guest doorbell */ | ||
26 | PPC_G_DBELL_CRIT = 3, /* guest critical doorbell */ | ||
27 | PPC_G_DBELL_MC = 4, /* guest mcheck doorbell */ | ||
28 | }; | ||
29 | |||
30 | #ifdef CONFIG_SMP | ||
31 | extern unsigned long dbell_smp_message[NR_CPUS]; | ||
32 | extern void smp_dbell_message_pass(int target, int msg); | ||
33 | #endif | ||
34 | |||
35 | static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag) | ||
36 | { | ||
37 | u32 msg = PPC_DBELL_TYPE(type) | (flags & PPC_DBELL_MSG_BRDCAST) | | ||
38 | (tag & 0x07ffffff); | ||
39 | |||
40 | __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg)); | ||
41 | } | ||
42 | |||
43 | #endif /* _ASM_POWERPC_DBELL_H */ | ||
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 583ba6493a62..dfec3d2790b2 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -59,7 +59,7 @@ obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \ | |||
59 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o | 59 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o |
60 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o | 60 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o |
61 | obj-$(CONFIG_44x) += cpu_setup_44x.o | 61 | obj-$(CONFIG_44x) += cpu_setup_44x.o |
62 | obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o | 62 | obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o |
63 | 63 | ||
64 | extra-$(CONFIG_PPC_STD_MMU) := head_32.o | 64 | extra-$(CONFIG_PPC_STD_MMU) := head_32.o |
65 | extra-$(CONFIG_PPC64) := head_64.o | 65 | extra-$(CONFIG_PPC64) := head_64.o |
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c new file mode 100644 index 000000000000..1493734cd871 --- /dev/null +++ b/arch/powerpc/kernel/dbell.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Author: Kumar Gala <galak@kernel.crashing.org> | ||
3 | * | ||
4 | * Copyright 2009 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/threads.h> | ||
16 | |||
17 | #include <asm/dbell.h> | ||
18 | |||
19 | #ifdef CONFIG_SMP | ||
20 | unsigned long dbell_smp_message[NR_CPUS]; | ||
21 | |||
22 | void smp_dbell_message_pass(int target, int msg) | ||
23 | { | ||
24 | int i; | ||
25 | |||
26 | if(target < NR_CPUS) { | ||
27 | set_bit(msg, &dbell_smp_message[target]); | ||
28 | ppc_msgsnd(PPC_DBELL, 0, target); | ||
29 | } | ||
30 | else if(target == MSG_ALL_BUT_SELF) { | ||
31 | for_each_online_cpu(i) { | ||
32 | if (i == smp_processor_id()) | ||
33 | continue; | ||
34 | set_bit(msg, &dbell_smp_message[i]); | ||
35 | ppc_msgsnd(PPC_DBELL, 0, i); | ||
36 | } | ||
37 | } | ||
38 | else { /* target == MSG_ALL */ | ||
39 | for_each_online_cpu(i) | ||
40 | set_bit(msg, &dbell_smp_message[i]); | ||
41 | ppc_msgsnd(PPC_DBELL, PPC_DBELL_MSG_BRDCAST, 0); | ||
42 | } | ||
43 | } | ||
44 | #endif | ||
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 4ea6e1a7e4b9..4c22620d009b 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -698,7 +698,9 @@ interrupt_base: | |||
698 | /* Performance Monitor */ | 698 | /* Performance Monitor */ |
699 | EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD) | 699 | EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD) |
700 | 700 | ||
701 | EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_STD) | 701 | EXCEPTION(0x2070, Doorbell, doorbell_exception, EXC_XFER_STD) |
702 | |||
703 | CRITICAL_EXCEPTION(0x2080, CriticalDoorbell, unknown_exception) | ||
702 | 704 | ||
703 | /* Debug Interrupt */ | 705 | /* Debug Interrupt */ |
704 | DEBUG_DEBUG_EXCEPTION | 706 | DEBUG_DEBUG_EXCEPTION |
@@ -921,6 +923,8 @@ _GLOBAL(__setup_e500mc_ivors) | |||
921 | mtspr SPRN_IVOR35,r3 | 923 | mtspr SPRN_IVOR35,r3 |
922 | li r3,Doorbell@l | 924 | li r3,Doorbell@l |
923 | mtspr SPRN_IVOR36,r3 | 925 | mtspr SPRN_IVOR36,r3 |
926 | li r3,CriticalDoorbell@l | ||
927 | mtspr SPRN_IVOR37,r3 | ||
924 | sync | 928 | sync |
925 | blr | 929 | blr |
926 | 930 | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 970d66ec4657..678fbff0d206 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -53,6 +53,9 @@ | |||
53 | #endif | 53 | #endif |
54 | #include <asm/kexec.h> | 54 | #include <asm/kexec.h> |
55 | #include <asm/ppc-opcode.h> | 55 | #include <asm/ppc-opcode.h> |
56 | #ifdef CONFIG_FSL_BOOKE | ||
57 | #include <asm/dbell.h> | ||
58 | #endif | ||
56 | 59 | ||
57 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) | 60 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) |
58 | int (*__debugger)(struct pt_regs *regs); | 61 | int (*__debugger)(struct pt_regs *regs); |
@@ -1122,6 +1125,24 @@ void vsx_assist_exception(struct pt_regs *regs) | |||
1122 | #endif /* CONFIG_VSX */ | 1125 | #endif /* CONFIG_VSX */ |
1123 | 1126 | ||
1124 | #ifdef CONFIG_FSL_BOOKE | 1127 | #ifdef CONFIG_FSL_BOOKE |
1128 | |||
1129 | void doorbell_exception(struct pt_regs *regs) | ||
1130 | { | ||
1131 | #ifdef CONFIG_SMP | ||
1132 | int cpu = smp_processor_id(); | ||
1133 | int msg; | ||
1134 | |||
1135 | if (num_online_cpus() < 2) | ||
1136 | return; | ||
1137 | |||
1138 | for (msg = 0; msg < 4; msg++) | ||
1139 | if (test_and_clear_bit(msg, &dbell_smp_message[cpu])) | ||
1140 | smp_message_recv(msg); | ||
1141 | #else | ||
1142 | printk(KERN_WARNING "Received doorbell on non-smp system\n"); | ||
1143 | #endif | ||
1144 | } | ||
1145 | |||
1125 | void CacheLockingException(struct pt_regs *regs, unsigned long address, | 1146 | void CacheLockingException(struct pt_regs *regs, unsigned long address, |
1126 | unsigned long error_code) | 1147 | unsigned long error_code) |
1127 | { | 1148 | { |