11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for more details. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994 by Waldorf GMBH, written by Ralf Baechle 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02, 03 by Ralf Baechle 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef _ASM_IRQ_H 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _ASM_IRQ_H 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/linkage.h> 13631330f5847b3f8a7ea67d689e9f7c56833ccaa6Ralf Baechle#include <linux/smp.h> 14abd2363f6a5f1030b935e0bdc15cf917313b3b10Grant Likely#include <linux/irqdomain.h> 1541c594ab65fc89573af296d192aa5235d09717abRalf Baechle 1641c594ab65fc89573af296d192aa5235d09717abRalf Baechle#include <asm/mipsmtregs.h> 1741c594ab65fc89573af296d192aa5235d09717abRalf Baechle 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <irq.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_I8259 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int irq_canonicalize(int irq) 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 232fa7937bd8922e1fe4aae6a45e7e787fa45d6043Atsushi Nemoto return ((irq == I8259A_IRQ_BASE + 2) ? I8259A_IRQ_BASE + 9 : irq); 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle#ifdef CONFIG_MIPS_MT_SMTC 301146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 311146fe30504a1edd8a434f500e1be139492570c9Ralf Baechlestruct irqaction; 321146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 331146fe30504a1edd8a434f500e1be139492570c9Ralf Baechleextern unsigned long irq_hwmask[]; 341146fe30504a1edd8a434f500e1be139492570c9Ralf Baechleextern int setup_irq_smtc(unsigned int irq, struct irqaction * new, 351146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle unsigned long hwmask); 361146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 371146fe30504a1edd8a434f500e1be139492570c9Ralf Baechlestatic inline void smtc_im_ack_irq(unsigned int irq) 381146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle{ 391146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle if (irq_hwmask[irq] & ST0_IM) 401146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle set_c0_status(irq_hwmask[irq] & ST0_IM); 411146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle} 421146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 431146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle#else 441146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 451146fe30504a1edd8a434f500e1be139492570c9Ralf Baechlestatic inline void smtc_im_ack_irq(unsigned int irq) 461146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle{ 471146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle} 481146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 491146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle#endif /* CONFIG_MIPS_MT_SMTC */ 501146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 51f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF 52f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell#include <linux/cpumask.h> 53f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 547c8d948f1633da5ff81e4f5b31ef237d74c40127Thomas Gleixnerextern int plat_set_irq_affinity(struct irq_data *d, 557c8d948f1633da5ff81e4f5b31ef237d74c40127Thomas Gleixner const struct cpumask *affinity, bool force); 56930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixnerextern void smtc_forward_irq(struct irq_data *d); 57f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 58f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell/* 59f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * IRQ affinity hook invoked at the beginning of interrupt dispatch 60f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * if option is enabled. 61f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * 62f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * Up through Linux 2.6.22 (at least) cpumask operations are very 63f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * inefficient on MIPS. Initial prototypes of SMTC IRQ affinity 64f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * used a "fast path" per-IRQ-descriptor cache of affinity information 65f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * to reduce latency. As there is a project afoot to optimize the 66f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * cpumask implementations, this version is optimistically assuming 67f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell * that cpumask.h macro overhead is reasonable during interrupt dispatch. 68f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell */ 69930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixnerstatic inline int handle_on_other_cpu(unsigned int irq) 70930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner{ 71930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner struct irq_data *d = irq_get_irq_data(irq); 72930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner 73930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner if (cpumask_test_cpu(smp_processor_id(), d->affinity)) 74930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner return 0; 75930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner smtc_forward_irq(d); 76930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner return 1; 77930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner} 78f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 79f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell#else /* Not doing SMTC affinity */ 80f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 81930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixnerstatic inline int handle_on_other_cpu(unsigned int irq) { return 0; } 82f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 83f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ 84f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 850db34215c7e0ef618e7b29fbf271194ca5434f8eKevin D. Kissell#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP 861146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 87930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixnerstatic inline void smtc_im_backstop(unsigned int irq) 88930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner{ 89930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner if (irq_hwmask[irq] & 0x0000ff00) 90930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner write_c0_tccontext(read_c0_tccontext() & 91930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner ~(irq_hwmask[irq] & 0x0000ff00)); 92930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner} 93930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner 9441c594ab65fc89573af296d192aa5235d09717abRalf Baechle/* 9541c594ab65fc89573af296d192aa5235d09717abRalf Baechle * Clear interrupt mask handling "backstop" if irq_hwmask 9641c594ab65fc89573af296d192aa5235d09717abRalf Baechle * entry so indicates. This implies that the ack() or end() 9741c594ab65fc89573af296d192aa5235d09717abRalf Baechle * functions will take over re-enabling the low-level mask. 9841c594ab65fc89573af296d192aa5235d09717abRalf Baechle * Otherwise it will be done on return from exception. 9941c594ab65fc89573af296d192aa5235d09717abRalf Baechle */ 100930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixnerstatic inline int smtc_handle_on_other_cpu(unsigned int irq) 101930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner{ 102930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner int ret = handle_on_other_cpu(irq); 103930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner 104930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner if (!ret) 105930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner smtc_im_backstop(irq); 106930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner return ret; 107930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner} 108f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 10941c594ab65fc89573af296d192aa5235d09717abRalf Baechle#else 1101146fe30504a1edd8a434f500e1be139492570c9Ralf Baechle 111930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixnerstatic inline void smtc_im_backstop(unsigned int irq) { } 112930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixnerstatic inline int smtc_handle_on_other_cpu(unsigned int irq) 113930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner{ 114930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner return handle_on_other_cpu(irq); 115930cd54b3bd78e52991a89b39b5ef58355ad2b6dThomas Gleixner} 116f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 11741c594ab65fc89573af296d192aa5235d09717abRalf Baechle#endif 11841c594ab65fc89573af296d192aa5235d09717abRalf Baechle 1198f99a162653531ef25a3dd0f92bfb6332cd2b295Wu Zhangjinextern void do_IRQ(unsigned int irq); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF 122f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 1238f99a162653531ef25a3dd0f92bfb6332cd2b295Wu Zhangjinextern void do_IRQ_no_affinity(unsigned int irq); 124f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 125f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ 126f571eff0a24ed97a919f2b61bb4afdeab4b43002Kevin D. Kissell 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void arch_init_irq(void); 128937a801576f954bd030d7c4a5a94571710d87c0bRalf Baechleextern void spurious_interrupt(void); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1304a4cf77923eeb3cec40a302656d6ab5ced04ba48Ralf Baechleextern int allocate_irqno(void); 1314a4cf77923eeb3cec40a302656d6ab5ced04ba48Ralf Baechleextern void alloc_legacy_irqno(void); 1324a4cf77923eeb3cec40a302656d6ab5ced04ba48Ralf Baechleextern void free_irqno(unsigned int irq); 1334a4cf77923eeb3cec40a302656d6ab5ced04ba48Ralf Baechle 1343b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechle/* 1353b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechle * Before R2 the timer and performance counter interrupts were both fixed to 1363b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechle * IE7. Since R2 their number has to be read from the c0_intctl register. 1373b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechle */ 1383b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechle#define CP0_LEGACY_COMPARE_IRQ 7 1393b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechle 1403b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechleextern int cp0_compare_irq; 141010c108d7af708d9e09b83724a058a76803fbc66David VomLehnextern int cp0_compare_irq_shift; 1423b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechleextern int cp0_perfcount_irq; 1433b1d4ed5353af04d6aa20be2701727b9cdb2ac61Ralf Baechle 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* _ASM_IRQ_H */ 145