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