Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sh/boards/mach-se/7724/irq.c
15162 views
1
/*
2
* linux/arch/sh/boards/se/7724/irq.c
3
*
4
* Copyright (C) 2009 Renesas Solutions Corp.
5
*
6
* Kuninori Morimoto <[email protected]>
7
*
8
* Based on linux/arch/sh/boards/se/7722/irq.c
9
* Copyright (C) 2007 Nobuhiro Iwamatsu
10
*
11
* Hitachi UL SolutionEngine 7724 Support.
12
*
13
* This file is subject to the terms and conditions of the GNU General Public
14
* License. See the file "COPYING" in the main directory of this archive
15
* for more details.
16
*/
17
#include <linux/init.h>
18
#include <linux/irq.h>
19
#include <linux/interrupt.h>
20
#include <asm/irq.h>
21
#include <asm/io.h>
22
#include <mach-se/mach/se7724.h>
23
24
struct fpga_irq {
25
unsigned long sraddr;
26
unsigned long mraddr;
27
unsigned short mask;
28
unsigned int base;
29
};
30
31
static unsigned int fpga2irq(unsigned int irq)
32
{
33
if (irq >= IRQ0_BASE &&
34
irq <= IRQ0_END)
35
return IRQ0_IRQ;
36
else if (irq >= IRQ1_BASE &&
37
irq <= IRQ1_END)
38
return IRQ1_IRQ;
39
else
40
return IRQ2_IRQ;
41
}
42
43
static struct fpga_irq get_fpga_irq(unsigned int irq)
44
{
45
struct fpga_irq set;
46
47
switch (irq) {
48
case IRQ0_IRQ:
49
set.sraddr = IRQ0_SR;
50
set.mraddr = IRQ0_MR;
51
set.mask = IRQ0_MASK;
52
set.base = IRQ0_BASE;
53
break;
54
case IRQ1_IRQ:
55
set.sraddr = IRQ1_SR;
56
set.mraddr = IRQ1_MR;
57
set.mask = IRQ1_MASK;
58
set.base = IRQ1_BASE;
59
break;
60
default:
61
set.sraddr = IRQ2_SR;
62
set.mraddr = IRQ2_MR;
63
set.mask = IRQ2_MASK;
64
set.base = IRQ2_BASE;
65
break;
66
}
67
68
return set;
69
}
70
71
static void disable_se7724_irq(struct irq_data *data)
72
{
73
unsigned int irq = data->irq;
74
struct fpga_irq set = get_fpga_irq(fpga2irq(irq));
75
unsigned int bit = irq - set.base;
76
__raw_writew(__raw_readw(set.mraddr) | 0x0001 << bit, set.mraddr);
77
}
78
79
static void enable_se7724_irq(struct irq_data *data)
80
{
81
unsigned int irq = data->irq;
82
struct fpga_irq set = get_fpga_irq(fpga2irq(irq));
83
unsigned int bit = irq - set.base;
84
__raw_writew(__raw_readw(set.mraddr) & ~(0x0001 << bit), set.mraddr);
85
}
86
87
static struct irq_chip se7724_irq_chip __read_mostly = {
88
.name = "SE7724-FPGA",
89
.irq_mask = disable_se7724_irq,
90
.irq_unmask = enable_se7724_irq,
91
};
92
93
static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)
94
{
95
struct fpga_irq set = get_fpga_irq(irq);
96
unsigned short intv = __raw_readw(set.sraddr);
97
unsigned int ext_irq = set.base;
98
99
intv &= set.mask;
100
101
for (; intv; intv >>= 1, ext_irq++) {
102
if (!(intv & 1))
103
continue;
104
105
generic_handle_irq(ext_irq);
106
}
107
}
108
109
/*
110
* Initialize IRQ setting
111
*/
112
void __init init_se7724_IRQ(void)
113
{
114
int i, nid = cpu_to_node(boot_cpu_data);
115
116
__raw_writew(0xffff, IRQ0_MR); /* mask all */
117
__raw_writew(0xffff, IRQ1_MR); /* mask all */
118
__raw_writew(0xffff, IRQ2_MR); /* mask all */
119
__raw_writew(0x0000, IRQ0_SR); /* clear irq */
120
__raw_writew(0x0000, IRQ1_SR); /* clear irq */
121
__raw_writew(0x0000, IRQ2_SR); /* clear irq */
122
__raw_writew(0x002a, IRQ_MODE); /* set irq type */
123
124
for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) {
125
int irq, wanted;
126
127
wanted = SE7724_FPGA_IRQ_BASE + i;
128
129
irq = create_irq_nr(wanted, nid);
130
if (unlikely(irq == 0)) {
131
pr_err("%s: failed hooking irq %d for FPGA\n",
132
__func__, wanted);
133
return;
134
}
135
136
if (unlikely(irq != wanted)) {
137
pr_err("%s: got irq %d but wanted %d, bailing.\n",
138
__func__, irq, wanted);
139
destroy_irq(irq);
140
return;
141
}
142
143
irq_set_chip_and_handler_name(irq, &se7724_irq_chip,
144
handle_level_irq, "level");
145
}
146
147
irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux);
148
irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
149
150
irq_set_chained_handler(IRQ1_IRQ, se7724_irq_demux);
151
irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
152
153
irq_set_chained_handler(IRQ2_IRQ, se7724_irq_demux);
154
irq_set_irq_type(IRQ2_IRQ, IRQ_TYPE_LEVEL_LOW);
155
}
156
157