diff options
author | Jayachandran C <jchandra@broadcom.com> | 2012-10-31 08:01:41 -0400 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2012-11-09 05:37:20 -0500 |
commit | 38541742da05f65d77e514a70bae9b84251c4bc4 (patch) | |
tree | e7d6ebdb191f3da42009ec614c6b6bb006a7139b /arch/mips | |
parent | bb1e4bc5cdc9dce7680317a4ebf87a12fc8c6a13 (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.h | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/netlogic/xlp-hal/pic.h | 1 | ||||
-rw-r--r-- | arch/mips/netlogic/common/irq.c | 170 | ||||
-rw-r--r-- | arch/mips/netlogic/common/smp.c | 7 | ||||
-rw-r--r-- | arch/mips/netlogic/xlp/nlm_hal.c | 38 |
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 @@ | |||
53 | struct irq_desc; | 53 | struct irq_desc; |
54 | void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc); | 54 | void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc); |
55 | void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc); | 55 | void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc); |
56 | void nlm_smp_irq_init(void); | 56 | void nlm_smp_irq_init(int hwcpuid); |
57 | void nlm_boot_secondary_cpus(void); | 57 | void nlm_boot_secondary_cpus(void); |
58 | int nlm_wakeup_secondary_cpus(void); | 58 | int nlm_wakeup_secondary_cpus(void); |
59 | void nlm_rmiboot_preboot(void); | 59 | void 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 | ||
384 | int nlm_irq_to_irt(int irq); | 384 | int nlm_irq_to_irt(int irq); |
385 | int 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 | |||
74 | struct 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 | |||
73 | static void xlp_pic_enable(struct irq_data *d) | 82 | static 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 | ||
88 | static void xlp_pic_disable(struct irq_data *d) | 93 | static 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 | ||
103 | static void xlp_pic_mask_ack(struct irq_data *d) | 104 | static 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 | ||
110 | static void xlp_pic_unmask(struct irq_data *d) | 112 | static 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 | ||
129 | static struct irq_chip xlp_pic = { | 126 | static 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 | ||
180 | void __init init_nlm_common_irqs(void) | 177 | static 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 | |||
191 | void 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++) { | 206 | void 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 | |||
216 | static 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 | ||
214 | void __init arch_init_irq(void) | 238 | void __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 | ||
222 | void __cpuinit nlm_smp_irq_init(void) | 246 | void 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 | */ |
115 | static void __cpuinit nlm_init_secondary(void) | 115 | static 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 | ||
121 | void nlm_prepare_cpus(unsigned int max_cpus) | 124 | void 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 | ||
103 | int 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 | |||
141 | unsigned int nlm_get_core_frequency(int node, int core) | 103 | unsigned 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; |