Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.4-rc6 237 lines 6.1 kB view raw
1/* 2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights 3 * reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the NetLogic 9 * license below: 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35#include <linux/kernel.h> 36#include <linux/init.h> 37#include <linux/linkage.h> 38#include <linux/interrupt.h> 39#include <linux/spinlock.h> 40#include <linux/mm.h> 41#include <linux/slab.h> 42#include <linux/irq.h> 43 44#include <asm/errno.h> 45#include <asm/signal.h> 46#include <asm/ptrace.h> 47#include <asm/mipsregs.h> 48#include <asm/thread_info.h> 49 50#include <asm/netlogic/mips-extns.h> 51#include <asm/netlogic/interrupt.h> 52#include <asm/netlogic/haldefs.h> 53#include <asm/netlogic/common.h> 54 55#if defined(CONFIG_CPU_XLP) 56#include <asm/netlogic/xlp-hal/iomap.h> 57#include <asm/netlogic/xlp-hal/xlp.h> 58#include <asm/netlogic/xlp-hal/pic.h> 59#elif defined(CONFIG_CPU_XLR) 60#include <asm/netlogic/xlr/iomap.h> 61#include <asm/netlogic/xlr/pic.h> 62#else 63#error "Unknown CPU" 64#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 72/* Globals */ 73static uint64_t nlm_irq_mask; 74static DEFINE_SPINLOCK(nlm_pic_lock); 75 76static void xlp_pic_enable(struct irq_data *d) 77{ 78 unsigned long flags; 79 int irt; 80 81 irt = nlm_irq_to_irt(d->irq); 82 if (irt == -1) 83 return; 84 spin_lock_irqsave(&nlm_pic_lock, flags); 85 nlm_pic_enable_irt(nlm_pic_base, irt); 86 spin_unlock_irqrestore(&nlm_pic_lock, flags); 87} 88 89static void xlp_pic_disable(struct irq_data *d) 90{ 91 unsigned long flags; 92 int irt; 93 94 irt = nlm_irq_to_irt(d->irq); 95 if (irt == -1) 96 return; 97 spin_lock_irqsave(&nlm_pic_lock, flags); 98 nlm_pic_disable_irt(nlm_pic_base, irt); 99 spin_unlock_irqrestore(&nlm_pic_lock, flags); 100} 101 102static void xlp_pic_mask_ack(struct irq_data *d) 103{ 104 uint64_t mask = 1ull << d->irq; 105 106 write_c0_eirr(mask); /* ack by writing EIRR */ 107} 108 109static void xlp_pic_unmask(struct irq_data *d) 110{ 111 void *hd = irq_data_get_irq_handler_data(d); 112 int irt; 113 114 irt = nlm_irq_to_irt(d->irq); 115 if (irt == -1) 116 return; 117 118 if (hd) { 119 void (*extra_ack)(void *) = hd; 120 extra_ack(d); 121 } 122 /* Ack is a single write, no need to lock */ 123 nlm_pic_ack(nlm_pic_base, irt); 124} 125 126static struct irq_chip xlp_pic = { 127 .name = "XLP-PIC", 128 .irq_enable = xlp_pic_enable, 129 .irq_disable = xlp_pic_disable, 130 .irq_mask_ack = xlp_pic_mask_ack, 131 .irq_unmask = xlp_pic_unmask, 132}; 133 134static void cpuintr_disable(struct irq_data *d) 135{ 136 uint64_t eimr; 137 uint64_t mask = 1ull << d->irq; 138 139 eimr = read_c0_eimr(); 140 write_c0_eimr(eimr & ~mask); 141} 142 143static void cpuintr_enable(struct irq_data *d) 144{ 145 uint64_t eimr; 146 uint64_t mask = 1ull << d->irq; 147 148 eimr = read_c0_eimr(); 149 write_c0_eimr(eimr | mask); 150} 151 152static void cpuintr_ack(struct irq_data *d) 153{ 154 uint64_t mask = 1ull << d->irq; 155 156 write_c0_eirr(mask); 157} 158 159static void cpuintr_nop(struct irq_data *d) 160{ 161 WARN(d->irq >= PIC_IRQ_BASE, "Bad irq %d", d->irq); 162} 163 164/* 165 * Chip definition for CPU originated interrupts(timer, msg) and 166 * IPIs 167 */ 168struct irq_chip nlm_cpu_intr = { 169 .name = "XLP-CPU-INTR", 170 .irq_enable = cpuintr_enable, 171 .irq_disable = cpuintr_disable, 172 .irq_mask = cpuintr_nop, 173 .irq_ack = cpuintr_nop, 174 .irq_eoi = cpuintr_ack, 175}; 176 177void __init init_nlm_common_irqs(void) 178{ 179 int i, irq, irt; 180 181 for (i = 0; i < PIC_IRT_FIRST_IRQ; i++) 182 irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq); 183 184 for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ ; i++) 185 irq_set_chip_and_handler(i, &xlp_pic, handle_level_irq); 186 187#ifdef CONFIG_SMP 188 irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr, 189 nlm_smp_function_ipi_handler); 190 irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr, 191 nlm_smp_resched_ipi_handler); 192 nlm_irq_mask |= 193 ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE)); 194#endif 195 196 for (irq = PIC_IRT_FIRST_IRQ; irq <= PIC_IRT_LAST_IRQ; irq++) { 197 irt = nlm_irq_to_irt(irq); 198 if (irt == -1) 199 continue; 200 nlm_irq_mask |= (1ULL << irq); 201 nlm_pic_init_irt(nlm_pic_base, irt, irq, 0); 202 } 203 204 nlm_irq_mask |= (1ULL << IRQ_TIMER); 205} 206 207void __init arch_init_irq(void) 208{ 209 /* Initialize the irq descriptors */ 210 init_nlm_common_irqs(); 211 212 write_c0_eimr(nlm_irq_mask); 213} 214 215void __cpuinit nlm_smp_irq_init(void) 216{ 217 /* set interrupt mask for non-zero cpus */ 218 write_c0_eimr(nlm_irq_mask); 219} 220 221asmlinkage void plat_irq_dispatch(void) 222{ 223 uint64_t eirr; 224 int i; 225 226 eirr = read_c0_eirr() & read_c0_eimr(); 227 if (eirr & (1 << IRQ_TIMER)) { 228 do_IRQ(IRQ_TIMER); 229 return; 230 } 231 232 i = __ilog2_u64(eirr); 233 if (i == -1) 234 return; 235 236 do_IRQ(i); 237}