1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 2013 Cavium, Inc. 7 */ 8 9#include <linux/interrupt.h> 10#include <linux/cpumask.h> 11#include <linux/kernel.h> 12#include <linux/mutex.h> 13 14#include <asm/io.h> 15 16#define MBOX_BITS_PER_CPU 2 17 18static int cpunum_for_cpu(int cpu) 19{ 20#ifdef CONFIG_SMP 21 return cpu_logical_map(cpu); 22#else 23 return get_ebase_cpunum(); 24#endif 25} 26 27struct core_chip_data { 28 struct mutex core_irq_mutex; 29 bool current_en; 30 bool desired_en; 31 u8 bit; 32}; 33 34static struct core_chip_data irq_core_chip_data[8]; 35 36static void irq_core_ack(struct irq_data *data) 37{ 38 struct core_chip_data *cd = irq_data_get_irq_chip_data(data); 39 unsigned int bit = cd->bit; 40 41 /* 42 * We don't need to disable IRQs to make these atomic since 43 * they are already disabled earlier in the low level 44 * interrupt code. 45 */ 46 clear_c0_status(0x100 << bit); 47 /* The two user interrupts must be cleared manually. */ 48 if (bit < 2) 49 clear_c0_cause(0x100 << bit); 50} 51 52static void irq_core_eoi(struct irq_data *data) 53{ 54 struct core_chip_data *cd = irq_data_get_irq_chip_data(data); 55 56 /* 57 * We don't need to disable IRQs to make these atomic since 58 * they are already disabled earlier in the low level 59 * interrupt code. 60 */ 61 set_c0_status(0x100 << cd->bit); 62} 63 64static void irq_core_set_enable_local(void *arg) 65{ 66 struct irq_data *data = arg; 67 struct core_chip_data *cd = irq_data_get_irq_chip_data(data); 68 unsigned int mask = 0x100 << cd->bit; 69 70 /* 71 * Interrupts are already disabled, so these are atomic. 72 */ 73 if (cd->desired_en) 74 set_c0_status(mask); 75 else 76 clear_c0_status(mask); 77 78} 79 80static void irq_core_disable(struct irq_data *data) 81{ 82 struct core_chip_data *cd = irq_data_get_irq_chip_data(data); 83 cd->desired_en = false; 84} 85 86static void irq_core_enable(struct irq_data *data) 87{ 88 struct core_chip_data *cd = irq_data_get_irq_chip_data(data); 89 cd->desired_en = true; 90} 91 92static void irq_core_bus_lock(struct irq_data *data) 93{ 94 struct core_chip_data *cd = irq_data_get_irq_chip_data(data); 95 96 mutex_lock(&cd->core_irq_mutex); 97} 98 99static void irq_core_bus_sync_unlock(struct irq_data *data) 100{ 101 struct core_chip_data *cd = irq_data_get_irq_chip_data(data); 102 103 if (cd->desired_en != cd->current_en) { 104 on_each_cpu(irq_core_set_enable_local, data, 1); 105 cd->current_en = cd->desired_en; 106 } 107 108 mutex_unlock(&cd->core_irq_mutex); 109} 110 111static struct irq_chip irq_chip_core = { 112 .name = "Core", 113 .irq_enable = irq_core_enable, 114 .irq_disable = irq_core_disable, 115 .irq_ack = irq_core_ack, 116 .irq_eoi = irq_core_eoi, 117 .irq_bus_lock = irq_core_bus_lock, 118 .irq_bus_sync_unlock = irq_core_bus_sync_unlock, 119 120 .irq_cpu_online = irq_core_eoi, 121 .irq_cpu_offline = irq_core_ack, 122 .flags = IRQCHIP_ONOFFLINE_ENABLED, 123}; 124 125static void __init irq_init_core(void) 126{ 127 int i; 128 int irq; 129 struct core_chip_data *cd; 130 131 /* Start with a clean slate */ 132 clear_c0_status(ST0_IM); 133 clear_c0_cause(CAUSEF_IP0 | CAUSEF_IP1); 134 135 for (i = 0; i < ARRAY_SIZE(irq_core_chip_data); i++) { 136 cd = irq_core_chip_data + i; 137 cd->current_en = false; 138 cd->desired_en = false; 139 cd->bit = i; 140 mutex_init(&cd->core_irq_mutex); 141 142 irq = MIPS_CPU_IRQ_BASE + i; 143 144 switch (i) { 145 case 0: /* SW0 */ 146 case 1: /* SW1 */ 147 case 5: /* IP5 */ 148 case 6: /* IP6 */ 149 case 7: /* IP7 */ 150 irq_set_chip_data(irq, cd); 151 irq_set_chip_and_handler(irq, &irq_chip_core, 152 handle_percpu_irq); 153 break; 154 default: 155 break; 156 } 157 } 158} 159 160static void __iomem *mips_irq_chip; 161#define MIPS_IRQ_CHIP_NUM_BITS 0 162#define MIPS_IRQ_CHIP_REGS 8 163 164static int mips_irq_cpu_stride; 165static int mips_irq_chip_reg_raw; 166static int mips_irq_chip_reg_src; 167static int mips_irq_chip_reg_en; 168static int mips_irq_chip_reg_raw_w1s; 169static int mips_irq_chip_reg_raw_w1c; 170static int mips_irq_chip_reg_en_w1s; 171static int mips_irq_chip_reg_en_w1c; 172 173static void irq_pci_enable(struct irq_data *data) 174{ 175 u32 mask = 1u << data->irq; 176 177 __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1s); 178} 179 180static void irq_pci_disable(struct irq_data *data) 181{ 182 u32 mask = 1u << data->irq; 183 184 __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1c); 185} 186 187static void irq_pci_ack(struct irq_data *data) 188{ 189} 190 191static void irq_pci_mask(struct irq_data *data) 192{ 193 u32 mask = 1u << data->irq; 194 195 __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1c); 196} 197 198static void irq_pci_unmask(struct irq_data *data) 199{ 200 u32 mask = 1u << data->irq; 201 202 __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1s); 203} 204 205static struct irq_chip irq_chip_pci = { 206 .name = "PCI", 207 .irq_enable = irq_pci_enable, 208 .irq_disable = irq_pci_disable, 209 .irq_ack = irq_pci_ack, 210 .irq_mask = irq_pci_mask, 211 .irq_unmask = irq_pci_unmask, 212}; 213 214static void irq_mbox_all(struct irq_data *data, void __iomem *base) 215{ 216 int cpu; 217 unsigned int mbox = data->irq - MIPS_IRQ_MBOX0; 218 u32 mask; 219 220 WARN_ON(mbox >= MBOX_BITS_PER_CPU); 221 222 for_each_online_cpu(cpu) { 223 unsigned int cpuid = cpunum_for_cpu(cpu); 224 mask = 1 << (cpuid * MBOX_BITS_PER_CPU + mbox); 225 __raw_writel(mask, base + (cpuid * mips_irq_cpu_stride)); 226 } 227} 228 229static void irq_mbox_enable(struct irq_data *data) 230{ 231 irq_mbox_all(data, mips_irq_chip + mips_irq_chip_reg_en_w1s + sizeof(u32)); 232} 233 234static void irq_mbox_disable(struct irq_data *data) 235{ 236 irq_mbox_all(data, mips_irq_chip + mips_irq_chip_reg_en_w1c + sizeof(u32)); 237} 238 239static void irq_mbox_ack(struct irq_data *data) 240{ 241 u32 mask; 242 unsigned int mbox = data->irq - MIPS_IRQ_MBOX0; 243 244 WARN_ON(mbox >= MBOX_BITS_PER_CPU); 245 246 mask = 1 << (get_ebase_cpunum() * MBOX_BITS_PER_CPU + mbox); 247 __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_raw_w1c + sizeof(u32)); 248} 249 250void irq_mbox_ipi(int cpu, unsigned int actions) 251{ 252 unsigned int cpuid = cpunum_for_cpu(cpu); 253 u32 mask; 254 255 WARN_ON(actions >= (1 << MBOX_BITS_PER_CPU)); 256 257 mask = actions << (cpuid * MBOX_BITS_PER_CPU); 258 __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_raw_w1s + sizeof(u32)); 259} 260 261static void irq_mbox_cpu_onoffline(struct irq_data *data, void __iomem *base) 262{ 263 unsigned int mbox = data->irq - MIPS_IRQ_MBOX0; 264 unsigned int cpuid = get_ebase_cpunum(); 265 u32 mask; 266 267 WARN_ON(mbox >= MBOX_BITS_PER_CPU); 268 269 mask = 1 << (cpuid * MBOX_BITS_PER_CPU + mbox); 270 __raw_writel(mask, base + (cpuid * mips_irq_cpu_stride)); 271 272} 273 274static void irq_mbox_cpu_online(struct irq_data *data) 275{ 276 irq_mbox_cpu_onoffline(data, mips_irq_chip + mips_irq_chip_reg_en_w1s + sizeof(u32)); 277} 278 279static void irq_mbox_cpu_offline(struct irq_data *data) 280{ 281 irq_mbox_cpu_onoffline(data, mips_irq_chip + mips_irq_chip_reg_en_w1c + sizeof(u32)); 282} 283 284static struct irq_chip irq_chip_mbox = { 285 .name = "MBOX", 286 .irq_enable = irq_mbox_enable, 287 .irq_disable = irq_mbox_disable, 288 .irq_ack = irq_mbox_ack, 289 .irq_cpu_online = irq_mbox_cpu_online, 290 .irq_cpu_offline = irq_mbox_cpu_offline, 291 .flags = IRQCHIP_ONOFFLINE_ENABLED, 292}; 293 294static void __init irq_pci_init(void) 295{ 296 int i, stride; 297 u32 num_bits; 298 299 mips_irq_chip = ioremap(0x1e010000, 4096); 300 301 num_bits = __raw_readl(mips_irq_chip + MIPS_IRQ_CHIP_NUM_BITS); 302 stride = 8 * (1 + ((num_bits - 1) / 64)); 303 304 305 pr_notice("mips_irq_chip: %u bits, reg stride: %d\n", num_bits, stride); 306 mips_irq_chip_reg_raw = MIPS_IRQ_CHIP_REGS + 0 * stride; 307 mips_irq_chip_reg_raw_w1s = MIPS_IRQ_CHIP_REGS + 1 * stride; 308 mips_irq_chip_reg_raw_w1c = MIPS_IRQ_CHIP_REGS + 2 * stride; 309 mips_irq_chip_reg_src = MIPS_IRQ_CHIP_REGS + 3 * stride; 310 mips_irq_chip_reg_en = MIPS_IRQ_CHIP_REGS + 4 * stride; 311 mips_irq_chip_reg_en_w1s = MIPS_IRQ_CHIP_REGS + 5 * stride; 312 mips_irq_chip_reg_en_w1c = MIPS_IRQ_CHIP_REGS + 6 * stride; 313 mips_irq_cpu_stride = stride * 4; 314 315 for (i = 0; i < 4; i++) 316 irq_set_chip_and_handler(i + MIPS_IRQ_PCIA, &irq_chip_pci, handle_level_irq); 317 318 for (i = 0; i < 2; i++) 319 irq_set_chip_and_handler(i + MIPS_IRQ_MBOX0, &irq_chip_mbox, handle_percpu_irq); 320 321 322 set_c0_status(STATUSF_IP2); 323} 324 325static void irq_pci_dispatch(void) 326{ 327 unsigned int cpuid = get_ebase_cpunum(); 328 u32 en; 329 330 en = __raw_readl(mips_irq_chip + mips_irq_chip_reg_src + 331 (cpuid * mips_irq_cpu_stride)); 332 333 if (!en) { 334 en = __raw_readl(mips_irq_chip + mips_irq_chip_reg_src + (cpuid * mips_irq_cpu_stride) + sizeof(u32)); 335 en = (en >> (2 * cpuid)) & 3; 336 337 if (!en) 338 spurious_interrupt(); 339 else 340 do_IRQ(__ffs(en) + MIPS_IRQ_MBOX0); /* MBOX type */ 341 } else { 342 do_IRQ(__ffs(en)); 343 } 344} 345 346 347void __init arch_init_irq(void) 348{ 349 irq_init_core(); 350 irq_pci_init(); 351} 352 353asmlinkage void plat_irq_dispatch(void) 354{ 355 unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; 356 int ip; 357 358 if (unlikely(!pending)) { 359 spurious_interrupt(); 360 return; 361 } 362 363 ip = ffs(pending) - 1 - STATUSB_IP0; 364 if (ip == 2) 365 irq_pci_dispatch(); 366 else 367 do_IRQ(MIPS_CPU_IRQ_BASE + ip); 368} 369