Blame view
drivers/irqchip/irq-mips-cpu.c
4.35 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 |
/* * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * Copyright (C) 2001 Ralf Baechle |
703422879 MIPS: Whitespace ... |
6 7 |
* Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. * Author: Maciej W. Rozycki <macro@mips.com> |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 |
* * This file define the irq handler for MIPS CPU interrupts. * |
703422879 MIPS: Whitespace ... |
11 12 |
* This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
* Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ /* * Almost all MIPS CPUs define 8 interrupt sources. They are typically * level triggered (i.e., cannot be cleared from CPU; must be cleared from * device). The first two are software interrupts which we don't really * use or support. The last one is usually the CPU timer interrupt if * counter register is present or, for CPUs with an external FPU, by * convention it's the FPU exception interrupt. * * Don't even think about using this on SMP. You have been warned. * * This file exports one global function: |
97dcb82de [MIPS] Define MIP... |
28 |
* void mips_cpu_irq_init(void); |
1da177e4c Linux-2.6.12-rc2 |
29 30 31 32 |
*/ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/kernel.h> |
ca4d3e674 MIPS: Add missing... |
33 |
#include <linux/irq.h> |
41a83e06e irqchip: Prepare ... |
34 |
#include <linux/irqchip.h> |
0916b4696 MIPS: add irqdoma... |
35 |
#include <linux/irqdomain.h> |
1da177e4c Linux-2.6.12-rc2 |
36 37 38 |
#include <asm/irq_cpu.h> #include <asm/mipsregs.h> |
d03d0a577 MT bulletproofing. |
39 |
#include <asm/mipsmtregs.h> |
f64e55dcb MIPS: Set vint ha... |
40 |
#include <asm/setup.h> |
1da177e4c Linux-2.6.12-rc2 |
41 |
|
a93951c45 MIPS: irq_cpu: Co... |
42 |
static inline void unmask_mips_irq(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
43 |
{ |
a93951c45 MIPS: irq_cpu: Co... |
44 |
set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); |
569f75bd0 Use an irq_enable... |
45 |
irq_enable_hazard(); |
1da177e4c Linux-2.6.12-rc2 |
46 |
} |
a93951c45 MIPS: irq_cpu: Co... |
47 |
static inline void mask_mips_irq(struct irq_data *d) |
1da177e4c Linux-2.6.12-rc2 |
48 |
{ |
a93951c45 MIPS: irq_cpu: Co... |
49 |
clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); |
569f75bd0 Use an irq_enable... |
50 |
irq_disable_hazard(); |
1da177e4c Linux-2.6.12-rc2 |
51 |
} |
94dee171d [MIPS] Eleminate ... |
52 |
static struct irq_chip mips_cpu_irq_controller = { |
70d21cdee [MIPS] use name i... |
53 |
.name = "MIPS", |
a93951c45 MIPS: irq_cpu: Co... |
54 55 56 57 58 |
.irq_ack = mask_mips_irq, .irq_mask = mask_mips_irq, .irq_mask_ack = mask_mips_irq, .irq_unmask = unmask_mips_irq, .irq_eoi = unmask_mips_irq, |
a3e6c1eff MIPS: IRQ: Fix di... |
59 60 |
.irq_disable = mask_mips_irq, .irq_enable = unmask_mips_irq, |
1da177e4c Linux-2.6.12-rc2 |
61 |
}; |
d03d0a577 MT bulletproofing. |
62 63 64 |
/* * Basically the same as above but taking care of all the MT stuff */ |
a93951c45 MIPS: irq_cpu: Co... |
65 |
static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d) |
d03d0a577 MT bulletproofing. |
66 67 |
{ unsigned int vpflags = dvpe(); |
a93951c45 MIPS: irq_cpu: Co... |
68 |
clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); |
d03d0a577 MT bulletproofing. |
69 |
evpe(vpflags); |
a93951c45 MIPS: irq_cpu: Co... |
70 |
unmask_mips_irq(d); |
d03d0a577 MT bulletproofing. |
71 72 |
return 0; } |
d03d0a577 MT bulletproofing. |
73 74 75 76 |
/* * While we ack the interrupt interrupts are disabled and thus we don't need * to deal with concurrency issues. Same for mips_cpu_irq_end. */ |
a93951c45 MIPS: irq_cpu: Co... |
77 |
static void mips_mt_cpu_irq_ack(struct irq_data *d) |
d03d0a577 MT bulletproofing. |
78 79 |
{ unsigned int vpflags = dvpe(); |
a93951c45 MIPS: irq_cpu: Co... |
80 |
clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); |
d03d0a577 MT bulletproofing. |
81 |
evpe(vpflags); |
a93951c45 MIPS: irq_cpu: Co... |
82 |
mask_mips_irq(d); |
d03d0a577 MT bulletproofing. |
83 |
} |
94dee171d [MIPS] Eleminate ... |
84 |
static struct irq_chip mips_mt_cpu_irq_controller = { |
70d21cdee [MIPS] use name i... |
85 |
.name = "MIPS", |
a93951c45 MIPS: irq_cpu: Co... |
86 87 88 89 90 91 |
.irq_startup = mips_mt_cpu_irq_startup, .irq_ack = mips_mt_cpu_irq_ack, .irq_mask = mask_mips_irq, .irq_mask_ack = mips_mt_cpu_irq_ack, .irq_unmask = unmask_mips_irq, .irq_eoi = unmask_mips_irq, |
a3e6c1eff MIPS: IRQ: Fix di... |
92 93 |
.irq_disable = mask_mips_irq, .irq_enable = unmask_mips_irq, |
d03d0a577 MT bulletproofing. |
94 |
}; |
1da177e4c Linux-2.6.12-rc2 |
95 |
|
85f7cdacb MIPS: Provide a g... |
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
asmlinkage void __weak plat_irq_dispatch(void) { unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; if (!pending) { spurious_interrupt(); return; } pending >>= CAUSEB_IP; while (pending) { irq = fls(pending) - 1; do_IRQ(MIPS_CPU_IRQ_BASE + irq); pending &= ~BIT(irq); } } |
0916b4696 MIPS: add irqdoma... |
113 114 115 116 117 118 119 120 121 122 123 |
static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { static struct irq_chip *chip; if (hw < 2 && cpu_has_mipsmt) { /* Software interrupts are used for MT/CMT IPI */ chip = &mips_mt_cpu_irq_controller; } else { chip = &mips_cpu_irq_controller; } |
f64e55dcb MIPS: Set vint ha... |
124 125 |
if (cpu_has_vint) set_vi_handler(hw, plat_irq_dispatch); |
0916b4696 MIPS: add irqdoma... |
126 127 128 129 130 131 132 133 134 |
irq_set_chip_and_handler(irq, chip, handle_percpu_irq); return 0; } static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = { .map = mips_cpu_intc_map, .xlate = irq_domain_xlate_onecell, }; |
0f84c3053 MIPS: Always use ... |
135 |
static void __init __mips_cpu_irq_init(struct device_node *of_node) |
0916b4696 MIPS: add irqdoma... |
136 137 138 139 140 141 142 143 144 145 |
{ struct irq_domain *domain; /* Mask interrupts. */ clear_c0_status(ST0_IM); clear_c0_cause(CAUSEF_IP); domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0, &mips_cpu_intc_irq_domain_ops, NULL); if (!domain) |
f7777dcc7 MIPS: Panic messa... |
146 |
panic("Failed to add irqdomain for MIPS CPU"); |
0f84c3053 MIPS: Always use ... |
147 148 149 150 151 152 |
} void __init mips_cpu_irq_init(void) { __mips_cpu_irq_init(NULL); } |
0916b4696 MIPS: add irqdoma... |
153 |
|
afe8dc254 MIPS: Rename mips... |
154 155 |
int __init mips_cpu_irq_of_init(struct device_node *of_node, struct device_node *parent) |
0f84c3053 MIPS: Always use ... |
156 157 |
{ __mips_cpu_irq_init(of_node); |
0916b4696 MIPS: add irqdoma... |
158 159 |
return 0; } |
892b8cf06 IRQCHIP: irq_cpu:... |
160 |
IRQCHIP_DECLARE(cpu_intc, "mti,cpu-interrupt-controller", mips_cpu_irq_of_init); |