diff options
author | Jayachandran C <jchandra@broadcom.com> | 2012-10-31 08:01:39 -0400 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2012-11-09 05:37:19 -0500 |
commit | 77ae798f5b736dfdc692b86b393d9699052ac77a (patch) | |
tree | 040a68a1c544167364e4ca2b78e69179c397e4b2 /arch/mips/netlogic/common/irq.c | |
parent | 2a37b1ae443f20470a789b12a45cbc249c9e50a6 (diff) |
MIPS: Netlogic: Support for multi-chip configuration
Upto 4 Netlogic XLP SoCs can be connected over ICI links to form a
coherent multi-node system. Each SoC has its own set of on-chip
devices including PIC. To support this, add a per SoC stucture and
use it for the PIC and SYS block addresses instead of using global
variables.
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Patchwork: http://patchwork.linux-mips.org/patch/4469
Signed-off-by: John Crispin <blogic@openwrt.org>
Diffstat (limited to 'arch/mips/netlogic/common/irq.c')
-rw-r--r-- | arch/mips/netlogic/common/irq.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index e52bfcbce093..4d6bd8f6ee29 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c | |||
@@ -70,33 +70,34 @@ | |||
70 | */ | 70 | */ |
71 | 71 | ||
72 | /* Globals */ | 72 | /* Globals */ |
73 | static uint64_t nlm_irq_mask; | ||
74 | static DEFINE_SPINLOCK(nlm_pic_lock); | ||
75 | |||
76 | static void xlp_pic_enable(struct irq_data *d) | 73 | static void xlp_pic_enable(struct irq_data *d) |
77 | { | 74 | { |
78 | unsigned long flags; | 75 | unsigned long flags; |
76 | struct nlm_soc_info *nodep; | ||
79 | int irt; | 77 | int irt; |
80 | 78 | ||
79 | nodep = nlm_current_node(); | ||
81 | irt = nlm_irq_to_irt(d->irq); | 80 | irt = nlm_irq_to_irt(d->irq); |
82 | if (irt == -1) | 81 | if (irt == -1) |
83 | return; | 82 | return; |
84 | spin_lock_irqsave(&nlm_pic_lock, flags); | 83 | spin_lock_irqsave(&nodep->piclock, flags); |
85 | nlm_pic_enable_irt(nlm_pic_base, irt); | 84 | nlm_pic_enable_irt(nodep->picbase, irt); |
86 | spin_unlock_irqrestore(&nlm_pic_lock, flags); | 85 | spin_unlock_irqrestore(&nodep->piclock, flags); |
87 | } | 86 | } |
88 | 87 | ||
89 | static void xlp_pic_disable(struct irq_data *d) | 88 | static void xlp_pic_disable(struct irq_data *d) |
90 | { | 89 | { |
90 | struct nlm_soc_info *nodep; | ||
91 | unsigned long flags; | 91 | unsigned long flags; |
92 | int irt; | 92 | int irt; |
93 | 93 | ||
94 | nodep = nlm_current_node(); | ||
94 | irt = nlm_irq_to_irt(d->irq); | 95 | irt = nlm_irq_to_irt(d->irq); |
95 | if (irt == -1) | 96 | if (irt == -1) |
96 | return; | 97 | return; |
97 | spin_lock_irqsave(&nlm_pic_lock, flags); | 98 | spin_lock_irqsave(&nodep->piclock, flags); |
98 | nlm_pic_disable_irt(nlm_pic_base, irt); | 99 | nlm_pic_disable_irt(nodep->picbase, irt); |
99 | spin_unlock_irqrestore(&nlm_pic_lock, flags); | 100 | spin_unlock_irqrestore(&nodep->piclock, flags); |
100 | } | 101 | } |
101 | 102 | ||
102 | static void xlp_pic_mask_ack(struct irq_data *d) | 103 | static void xlp_pic_mask_ack(struct irq_data *d) |
@@ -109,8 +110,10 @@ static void xlp_pic_mask_ack(struct irq_data *d) | |||
109 | static void xlp_pic_unmask(struct irq_data *d) | 110 | static void xlp_pic_unmask(struct irq_data *d) |
110 | { | 111 | { |
111 | void *hd = irq_data_get_irq_handler_data(d); | 112 | void *hd = irq_data_get_irq_handler_data(d); |
113 | struct nlm_soc_info *nodep; | ||
112 | int irt; | 114 | int irt; |
113 | 115 | ||
116 | nodep = nlm_current_node(); | ||
114 | irt = nlm_irq_to_irt(d->irq); | 117 | irt = nlm_irq_to_irt(d->irq); |
115 | if (irt == -1) | 118 | if (irt == -1) |
116 | return; | 119 | return; |
@@ -120,7 +123,7 @@ static void xlp_pic_unmask(struct irq_data *d) | |||
120 | extra_ack(d); | 123 | extra_ack(d); |
121 | } | 124 | } |
122 | /* Ack is a single write, no need to lock */ | 125 | /* Ack is a single write, no need to lock */ |
123 | nlm_pic_ack(nlm_pic_base, irt); | 126 | nlm_pic_ack(nodep->picbase, irt); |
124 | } | 127 | } |
125 | 128 | ||
126 | static struct irq_chip xlp_pic = { | 129 | static struct irq_chip xlp_pic = { |
@@ -177,7 +180,11 @@ struct irq_chip nlm_cpu_intr = { | |||
177 | void __init init_nlm_common_irqs(void) | 180 | void __init init_nlm_common_irqs(void) |
178 | { | 181 | { |
179 | int i, irq, irt; | 182 | int i, irq, irt; |
183 | uint64_t irqmask; | ||
184 | struct nlm_soc_info *nodep; | ||
180 | 185 | ||
186 | nodep = nlm_current_node(); | ||
187 | irqmask = (1ULL << IRQ_TIMER); | ||
181 | for (i = 0; i < PIC_IRT_FIRST_IRQ; i++) | 188 | for (i = 0; i < PIC_IRT_FIRST_IRQ; i++) |
182 | irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq); | 189 | irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq); |
183 | 190 | ||
@@ -189,7 +196,7 @@ void __init init_nlm_common_irqs(void) | |||
189 | nlm_smp_function_ipi_handler); | 196 | nlm_smp_function_ipi_handler); |
190 | irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr, | 197 | irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr, |
191 | nlm_smp_resched_ipi_handler); | 198 | nlm_smp_resched_ipi_handler); |
192 | nlm_irq_mask |= | 199 | irqmask |= |
193 | ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE)); | 200 | ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE)); |
194 | #endif | 201 | #endif |
195 | 202 | ||
@@ -197,11 +204,11 @@ void __init init_nlm_common_irqs(void) | |||
197 | irt = nlm_irq_to_irt(irq); | 204 | irt = nlm_irq_to_irt(irq); |
198 | if (irt == -1) | 205 | if (irt == -1) |
199 | continue; | 206 | continue; |
200 | nlm_irq_mask |= (1ULL << irq); | 207 | irqmask |= (1ULL << irq); |
201 | nlm_pic_init_irt(nlm_pic_base, irt, irq, 0); | 208 | nlm_pic_init_irt(nodep->picbase, irt, irq, 0); |
202 | } | 209 | } |
203 | 210 | ||
204 | nlm_irq_mask |= (1ULL << IRQ_TIMER); | 211 | nodep->irqmask = irqmask; |
205 | } | 212 | } |
206 | 213 | ||
207 | void __init arch_init_irq(void) | 214 | void __init arch_init_irq(void) |
@@ -209,29 +216,39 @@ void __init arch_init_irq(void) | |||
209 | /* Initialize the irq descriptors */ | 216 | /* Initialize the irq descriptors */ |
210 | init_nlm_common_irqs(); | 217 | init_nlm_common_irqs(); |
211 | 218 | ||
212 | write_c0_eimr(nlm_irq_mask); | 219 | write_c0_eimr(nlm_current_node()->irqmask); |
213 | } | 220 | } |
214 | 221 | ||
215 | void __cpuinit nlm_smp_irq_init(void) | 222 | void __cpuinit nlm_smp_irq_init(void) |
216 | { | 223 | { |
217 | /* set interrupt mask for non-zero cpus */ | 224 | /* set interrupt mask for non-zero cpus */ |
218 | write_c0_eimr(nlm_irq_mask); | 225 | write_c0_eimr(nlm_current_node()->irqmask); |
219 | } | 226 | } |
220 | 227 | ||
221 | asmlinkage void plat_irq_dispatch(void) | 228 | asmlinkage void plat_irq_dispatch(void) |
222 | { | 229 | { |
223 | uint64_t eirr; | 230 | uint64_t eirr; |
224 | int i; | 231 | int i, node; |
225 | 232 | ||
233 | node = nlm_nodeid(); | ||
226 | eirr = read_c0_eirr() & read_c0_eimr(); | 234 | eirr = read_c0_eirr() & read_c0_eimr(); |
227 | if (eirr & (1 << IRQ_TIMER)) { | 235 | if (eirr & (1 << IRQ_TIMER)) { |
228 | do_IRQ(IRQ_TIMER); | 236 | do_IRQ(IRQ_TIMER); |
229 | return; | 237 | return; |
230 | } | 238 | } |
231 | 239 | #ifdef CONFIG_SMP | |
240 | if (eirr & IRQ_IPI_SMP_FUNCTION) { | ||
241 | do_IRQ(IRQ_IPI_SMP_FUNCTION); | ||
242 | return; | ||
243 | } | ||
244 | if (eirr & IRQ_IPI_SMP_RESCHEDULE) { | ||
245 | do_IRQ(IRQ_IPI_SMP_RESCHEDULE); | ||
246 | return; | ||
247 | } | ||
248 | #endif | ||
232 | i = __ilog2_u64(eirr); | 249 | i = __ilog2_u64(eirr); |
233 | if (i == -1) | 250 | if (i == -1) |
234 | return; | 251 | return; |
235 | 252 | ||
236 | do_IRQ(i); | 253 | do_IRQ(nlm_irq_to_xirq(node, i)); |
237 | } | 254 | } |