1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#include <linux/module.h>
39#include <linux/kernel.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/seq_file.h>
43
44#include <asm/cacheflush.h>
45#include <asm/cp15.h>
46#include <asm/fiq.h>
47#include <asm/irq.h>
48#include <asm/traps.h>
49
50#define FIQ_OFFSET ({ \
51 extern void *vector_fiq_offset; \
52 (unsigned)&vector_fiq_offset; \
53 })
54
55static unsigned long no_fiq_insn;
56
57
58
59
60
61static int fiq_def_op(void *ref, int relinquish)
62{
63 if (!relinquish)
64 set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn));
65
66 return 0;
67}
68
69static struct fiq_handler default_owner = {
70 .name = "default",
71 .fiq_op = fiq_def_op,
72};
73
74static struct fiq_handler *current_fiq = &default_owner;
75
76int show_fiq_list(struct seq_file *p, int prec)
77{
78 if (current_fiq != &default_owner)
79 seq_printf(p, "%*s: %s\n", prec, "FIQ",
80 current_fiq->name);
81
82 return 0;
83}
84
85void set_fiq_handler(void *start, unsigned int length)
86{
87 void *base = vectors_page;
88 unsigned offset = FIQ_OFFSET;
89
90 memcpy(base + offset, start, length);
91 if (!cache_is_vipt_nonaliasing())
92 flush_icache_range((unsigned long)base + offset, offset +
93 length);
94 flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
95}
96
97int claim_fiq(struct fiq_handler *f)
98{
99 int ret = 0;
100
101 if (current_fiq) {
102 ret = -EBUSY;
103
104 if (current_fiq->fiq_op != NULL)
105 ret = current_fiq->fiq_op(current_fiq->dev_id, 1);
106 }
107
108 if (!ret) {
109 f->next = current_fiq;
110 current_fiq = f;
111 }
112
113 return ret;
114}
115
116void release_fiq(struct fiq_handler *f)
117{
118 if (current_fiq != f) {
119 printk(KERN_ERR "%s FIQ trying to release %s FIQ\n",
120 f->name, current_fiq->name);
121 dump_stack();
122 return;
123 }
124
125 do
126 current_fiq = current_fiq->next;
127 while (current_fiq->fiq_op(current_fiq->dev_id, 0));
128}
129
130static int fiq_start;
131
132void enable_fiq(int fiq)
133{
134 enable_irq(fiq + fiq_start);
135}
136
137void disable_fiq(int fiq)
138{
139 disable_irq(fiq + fiq_start);
140}
141
142EXPORT_SYMBOL(set_fiq_handler);
143EXPORT_SYMBOL(__set_fiq_regs);
144EXPORT_SYMBOL(__get_fiq_regs);
145EXPORT_SYMBOL(claim_fiq);
146EXPORT_SYMBOL(release_fiq);
147EXPORT_SYMBOL(enable_fiq);
148EXPORT_SYMBOL(disable_fiq);
149
150void __init init_FIQ(int start)
151{
152 unsigned offset = FIQ_OFFSET;
153 no_fiq_insn = *(unsigned long *)(0xffff0000 + offset);
154 fiq_start = start;
155}
156