aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorJayachandran C <jchandra@broadcom.com>2012-10-31 08:01:41 -0400
committerJohn Crispin <blogic@openwrt.org>2012-11-09 05:37:20 -0500
commit38541742da05f65d77e514a70bae9b84251c4bc4 (patch)
treee7d6ebdb191f3da42009ec614c6b6bb006a7139b /arch/mips
parentbb1e4bc5cdc9dce7680317a4ebf87a12fc8c6a13 (diff)
MIPS: Netlogic: PIC IRQ handling update for multi-chip
Create struct nlm_pic_irq for interrupts handled by the PIC. This simplifies IRQ handling for multi-SoC as well as the single SoC cases. Also split the setup of percpu and PIC interrupts so that we can configure the PIC interrupts for every node. Signed-off-by: Jayachandran C <jchandra@broadcom.com> Patchwork: http://patchwork.linux-mips.org/patch/4467 Signed-off-by: John Crispin <blogic@openwrt.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/include/asm/netlogic/common.h2
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/pic.h1
-rw-r--r--arch/mips/netlogic/common/irq.c170
-rw-r--r--arch/mips/netlogic/common/smp.c7
-rw-r--r--arch/mips/netlogic/xlp/nlm_hal.c38
5 files changed, 103 insertions, 115 deletions
diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h
index 3c6814eb612b..1fee7eff64aa 100644
--- a/arch/mips/include/asm/netlogic/common.h
+++ b/arch/mips/include/asm/netlogic/common.h
@@ -53,7 +53,7 @@
53struct irq_desc; 53struct irq_desc;
54void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc); 54void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc);
55void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc); 55void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc);
56void nlm_smp_irq_init(void); 56void nlm_smp_irq_init(int hwcpuid);
57void nlm_boot_secondary_cpus(void); 57void nlm_boot_secondary_cpus(void);
58int nlm_wakeup_secondary_cpus(void); 58int nlm_wakeup_secondary_cpus(void);
59void nlm_rmiboot_preboot(void); 59void nlm_rmiboot_preboot(void);
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
index 857a967e4530..b2e53a5383ab 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
@@ -382,7 +382,6 @@ nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
382} 382}
383 383
384int nlm_irq_to_irt(int irq); 384int nlm_irq_to_irt(int irq);
385int nlm_irt_to_irq(int irt);
386 385
387#endif /* __ASSEMBLY__ */ 386#endif /* __ASSEMBLY__ */
388#endif /* _NLM_HAL_PIC_H */ 387#endif /* _NLM_HAL_PIC_H */
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index 4d6bd8f6ee29..b89d5a6b62cc 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -36,7 +36,6 @@
36#include <linux/init.h> 36#include <linux/init.h>
37#include <linux/linkage.h> 37#include <linux/linkage.h>
38#include <linux/interrupt.h> 38#include <linux/interrupt.h>
39#include <linux/spinlock.h>
40#include <linux/mm.h> 39#include <linux/mm.h>
41#include <linux/slab.h> 40#include <linux/slab.h>
42#include <linux/irq.h> 41#include <linux/irq.h>
@@ -62,68 +61,66 @@
62#else 61#else
63#error "Unknown CPU" 62#error "Unknown CPU"
64#endif 63#endif
65/*
66 * These are the routines that handle all the low level interrupt stuff.
67 * Actions handled here are: initialization of the interrupt map, requesting of
68 * interrupt lines by handlers, dispatching if interrupts to handlers, probing
69 * for interrupt lines
70 */
71 64
72/* Globals */ 65#ifdef CONFIG_SMP
66#define SMP_IRQ_MASK ((1ULL << IRQ_IPI_SMP_FUNCTION) | \
67 (1ULL << IRQ_IPI_SMP_RESCHEDULE))
68#else
69#define SMP_IRQ_MASK 0
70#endif
71#define PERCPU_IRQ_MASK (SMP_IRQ_MASK | (1ull << IRQ_TIMER))
72
73
74struct nlm_pic_irq {
75 void (*extra_ack)(struct irq_data *);
76 struct nlm_soc_info *node;
77 int picirq;
78 int irt;
79 int flags;
80};
81
73static void xlp_pic_enable(struct irq_data *d) 82static void xlp_pic_enable(struct irq_data *d)
74{ 83{
75 unsigned long flags; 84 unsigned long flags;
76 struct nlm_soc_info *nodep; 85 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
77 int irt;
78 86
79 nodep = nlm_current_node(); 87 BUG_ON(!pd);
80 irt = nlm_irq_to_irt(d->irq); 88 spin_lock_irqsave(&pd->node->piclock, flags);
81 if (irt == -1) 89 nlm_pic_enable_irt(pd->node->picbase, pd->irt);
82 return; 90 spin_unlock_irqrestore(&pd->node->piclock, flags);
83 spin_lock_irqsave(&nodep->piclock, flags);
84 nlm_pic_enable_irt(nodep->picbase, irt);
85 spin_unlock_irqrestore(&nodep->piclock, flags);
86} 91}
87 92
88static void xlp_pic_disable(struct irq_data *d) 93static void xlp_pic_disable(struct irq_data *d)
89{ 94{
90 struct nlm_soc_info *nodep; 95 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
91 unsigned long flags; 96 unsigned long flags;
92 int irt;
93 97
94 nodep = nlm_current_node(); 98 BUG_ON(!pd);
95 irt = nlm_irq_to_irt(d->irq); 99 spin_lock_irqsave(&pd->node->piclock, flags);
96 if (irt == -1) 100 nlm_pic_disable_irt(pd->node->picbase, pd->irt);
97 return; 101 spin_unlock_irqrestore(&pd->node->piclock, flags);
98 spin_lock_irqsave(&nodep->piclock, flags);
99 nlm_pic_disable_irt(nodep->picbase, irt);
100 spin_unlock_irqrestore(&nodep->piclock, flags);
101} 102}
102 103
103static void xlp_pic_mask_ack(struct irq_data *d) 104static void xlp_pic_mask_ack(struct irq_data *d)
104{ 105{
105 uint64_t mask = 1ull << d->irq; 106 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
107 uint64_t mask = 1ull << pd->picirq;
106 108
107 write_c0_eirr(mask); /* ack by writing EIRR */ 109 write_c0_eirr(mask); /* ack by writing EIRR */
108} 110}
109 111
110static void xlp_pic_unmask(struct irq_data *d) 112static void xlp_pic_unmask(struct irq_data *d)
111{ 113{
112 void *hd = irq_data_get_irq_handler_data(d); 114 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
113 struct nlm_soc_info *nodep;
114 int irt;
115 115
116 nodep = nlm_current_node(); 116 if (!pd)
117 irt = nlm_irq_to_irt(d->irq);
118 if (irt == -1)
119 return; 117 return;
120 118
121 if (hd) { 119 if (pd->extra_ack)
122 void (*extra_ack)(void *) = hd; 120 pd->extra_ack(d);
123 extra_ack(d); 121
124 }
125 /* Ack is a single write, no need to lock */ 122 /* Ack is a single write, no need to lock */
126 nlm_pic_ack(nodep->picbase, irt); 123 nlm_pic_ack(pd->node->picbase, pd->irt);
127} 124}
128 125
129static struct irq_chip xlp_pic = { 126static struct irq_chip xlp_pic = {
@@ -177,51 +174,84 @@ struct irq_chip nlm_cpu_intr = {
177 .irq_eoi = cpuintr_ack, 174 .irq_eoi = cpuintr_ack,
178}; 175};
179 176
180void __init init_nlm_common_irqs(void) 177static void __init nlm_init_percpu_irqs(void)
181{ 178{
182 int i, irq, irt; 179 int i;
183 uint64_t irqmask;
184 struct nlm_soc_info *nodep;
185 180
186 nodep = nlm_current_node();
187 irqmask = (1ULL << IRQ_TIMER);
188 for (i = 0; i < PIC_IRT_FIRST_IRQ; i++) 181 for (i = 0; i < PIC_IRT_FIRST_IRQ; i++)
189 irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq); 182 irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq);
190
191 for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ ; i++)
192 irq_set_chip_and_handler(i, &xlp_pic, handle_level_irq);
193
194#ifdef CONFIG_SMP 183#ifdef CONFIG_SMP
195 irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr, 184 irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
196 nlm_smp_function_ipi_handler); 185 nlm_smp_function_ipi_handler);
197 irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr, 186 irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr,
198 nlm_smp_resched_ipi_handler); 187 nlm_smp_resched_ipi_handler);
199 irqmask |=
200 ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE));
201#endif 188#endif
189}
190
191void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
192{
193 struct nlm_pic_irq *pic_data;
194 int xirq;
195
196 xirq = nlm_irq_to_xirq(node, irq);
197 pic_data = kzalloc(sizeof(*pic_data), GFP_KERNEL);
198 BUG_ON(pic_data == NULL);
199 pic_data->irt = irt;
200 pic_data->picirq = picirq;
201 pic_data->node = nlm_get_node(node);
202 irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
203 irq_set_handler_data(xirq, pic_data);
204}
202 205
203 for (irq = PIC_IRT_FIRST_IRQ; irq <= PIC_IRT_LAST_IRQ; irq++) { 206void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
204 irt = nlm_irq_to_irt(irq); 207{
208 struct nlm_pic_irq *pic_data;
209 int xirq;
210
211 xirq = nlm_irq_to_xirq(node, irq);
212 pic_data = irq_get_handler_data(xirq);
213 pic_data->extra_ack = xack;
214}
215
216static void nlm_init_node_irqs(int node)
217{
218 int i, irt;
219 uint64_t irqmask;
220 struct nlm_soc_info *nodep;
221
222 pr_info("Init IRQ for node %d\n", node);
223 nodep = nlm_get_node(node);
224 irqmask = PERCPU_IRQ_MASK;
225 for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
226 irt = nlm_irq_to_irt(i);
205 if (irt == -1) 227 if (irt == -1)
206 continue; 228 continue;
207 irqmask |= (1ULL << irq); 229 nlm_setup_pic_irq(node, i, i, irt);
208 nlm_pic_init_irt(nodep->picbase, irt, irq, 0); 230 /* set interrupts to first cpu in node */
231 nlm_pic_init_irt(nodep->picbase, irt, i,
232 node * NLM_CPUS_PER_NODE);
233 irqmask |= (1ull << i);
209 } 234 }
210
211 nodep->irqmask = irqmask; 235 nodep->irqmask = irqmask;
212} 236}
213 237
214void __init arch_init_irq(void) 238void __init arch_init_irq(void)
215{ 239{
216 /* Initialize the irq descriptors */ 240 /* Initialize the irq descriptors */
217 init_nlm_common_irqs(); 241 nlm_init_percpu_irqs();
218 242 nlm_init_node_irqs(0);
219 write_c0_eimr(nlm_current_node()->irqmask); 243 write_c0_eimr(nlm_current_node()->irqmask);
220} 244}
221 245
222void __cpuinit nlm_smp_irq_init(void) 246void nlm_smp_irq_init(int hwcpuid)
223{ 247{
224 /* set interrupt mask for non-zero cpus */ 248 int node, cpu;
249
250 node = hwcpuid / NLM_CPUS_PER_NODE;
251 cpu = hwcpuid % NLM_CPUS_PER_NODE;
252
253 if (cpu == 0 && node != 0)
254 nlm_init_node_irqs(node);
225 write_c0_eimr(nlm_current_node()->irqmask); 255 write_c0_eimr(nlm_current_node()->irqmask);
226} 256}
227 257
@@ -232,23 +262,17 @@ asmlinkage void plat_irq_dispatch(void)
232 262
233 node = nlm_nodeid(); 263 node = nlm_nodeid();
234 eirr = read_c0_eirr() & read_c0_eimr(); 264 eirr = read_c0_eirr() & read_c0_eimr();
235 if (eirr & (1 << IRQ_TIMER)) { 265
236 do_IRQ(IRQ_TIMER);
237 return;
238 }
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
249 i = __ilog2_u64(eirr); 266 i = __ilog2_u64(eirr);
250 if (i == -1) 267 if (i == -1)
251 return; 268 return;
252 269
270 /* per-CPU IRQs don't need translation */
271 if (eirr & PERCPU_IRQ_MASK) {
272 do_IRQ(i);
273 return;
274 }
275
276 /* top level irq handling */
253 do_IRQ(nlm_irq_to_xirq(node, i)); 277 do_IRQ(nlm_irq_to_xirq(node, i));
254} 278}
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index e40b467f6184..0315b298a648 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -114,8 +114,11 @@ void nlm_early_init_secondary(int cpu)
114 */ 114 */
115static void __cpuinit nlm_init_secondary(void) 115static void __cpuinit nlm_init_secondary(void)
116{ 116{
117 current_cpu_data.core = hard_smp_processor_id() / NLM_THREADS_PER_CORE; 117 int hwtid;
118 nlm_smp_irq_init(); 118
119 hwtid = hard_smp_processor_id();
120 current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE;
121 nlm_smp_irq_init(hwtid);
119} 122}
120 123
121void nlm_prepare_cpus(unsigned int max_cpus) 124void nlm_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index d3a26e740acb..529e74742d9f 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -100,44 +100,6 @@ int nlm_irq_to_irt(int irq)
100 } 100 }
101} 101}
102 102
103int nlm_irt_to_irq(int irt)
104{
105 switch (irt) {
106 case PIC_IRT_UART_0_INDEX:
107 return PIC_UART_0_IRQ;
108 case PIC_IRT_UART_1_INDEX:
109 return PIC_UART_1_IRQ;
110 case PIC_IRT_PCIE_LINK_0_INDEX:
111 return PIC_PCIE_LINK_0_IRQ;
112 case PIC_IRT_PCIE_LINK_1_INDEX:
113 return PIC_PCIE_LINK_1_IRQ;
114 case PIC_IRT_PCIE_LINK_2_INDEX:
115 return PIC_PCIE_LINK_2_IRQ;
116 case PIC_IRT_PCIE_LINK_3_INDEX:
117 return PIC_PCIE_LINK_3_IRQ;
118 case PIC_IRT_EHCI_0_INDEX:
119 return PIC_EHCI_0_IRQ;
120 case PIC_IRT_EHCI_1_INDEX:
121 return PIC_EHCI_1_IRQ;
122 case PIC_IRT_OHCI_0_INDEX:
123 return PIC_OHCI_0_IRQ;
124 case PIC_IRT_OHCI_1_INDEX:
125 return PIC_OHCI_1_IRQ;
126 case PIC_IRT_OHCI_2_INDEX:
127 return PIC_OHCI_2_IRQ;
128 case PIC_IRT_OHCI_3_INDEX:
129 return PIC_OHCI_3_IRQ;
130 case PIC_IRT_MMC_INDEX:
131 return PIC_MMC_IRQ;
132 case PIC_IRT_I2C_0_INDEX:
133 return PIC_I2C_0_IRQ;
134 case PIC_IRT_I2C_1_INDEX:
135 return PIC_I2C_1_IRQ;
136 default:
137 return -1;
138 }
139}
140
141unsigned int nlm_get_core_frequency(int node, int core) 103unsigned int nlm_get_core_frequency(int node, int core)
142{ 104{
143 unsigned int pll_divf, pll_divr, dfs_div, ext_div; 105 unsigned int pll_divf, pll_divr, dfs_div, ext_div;