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/fiq.h>
46#include <asm/irq.h>
47#include <asm/system.h>
48#include <asm/traps.h>
49
50static unsigned long no_fiq_insn;
51
52
53
54
55
56static int fiq_def_op(void *ref, int relinquish)
57{
58 if (!relinquish)
59 set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn));
60
61 return 0;
62}
63
64static struct fiq_handler default_owner = {
65 .name = "default",
66 .fiq_op = fiq_def_op,
67};
68
69static struct fiq_handler *current_fiq = &default_owner;
70
71int show_fiq_list(struct seq_file *p, int prec)
72{
73 if (current_fiq != &default_owner)
74 seq_printf(p, "%*s: %s\n", prec, "FIQ",
75 current_fiq->name);
76
77 return 0;
78}
79
80void set_fiq_handler(void *start, unsigned int length)
81{
82#if defined(CONFIG_CPU_USE_DOMAINS)
83 memcpy((void *)0xffff001c, start, length);
84#else
85 memcpy(vectors_page + 0x1c, start, length);
86#endif
87 flush_icache_range(0xffff001c, 0xffff001c + length);
88 if (!vectors_high())
89 flush_icache_range(0x1c, 0x1c + length);
90}
91
92int claim_fiq(struct fiq_handler *f)
93{
94 int ret = 0;
95
96 if (current_fiq) {
97 ret = -EBUSY;
98
99 if (current_fiq->fiq_op != NULL)
100 ret = current_fiq->fiq_op(current_fiq->dev_id, 1);
101 }
102
103 if (!ret) {
104 f->next = current_fiq;
105 current_fiq = f;
106 }
107
108 return ret;
109}
110
111void release_fiq(struct fiq_handler *f)
112{
113 if (current_fiq != f) {
114 printk(KERN_ERR "%s FIQ trying to release %s FIQ\n",
115 f->name, current_fiq->name);
116 dump_stack();
117 return;
118 }
119
120 do
121 current_fiq = current_fiq->next;
122 while (current_fiq->fiq_op(current_fiq->dev_id, 0));
123}
124
125void enable_fiq(int fiq)
126{
127 enable_irq(fiq + FIQ_START);
128}
129
130void disable_fiq(int fiq)
131{
132 disable_irq(fiq + FIQ_START);
133}
134
135EXPORT_SYMBOL(set_fiq_handler);
136EXPORT_SYMBOL(__set_fiq_regs);
137EXPORT_SYMBOL(__get_fiq_regs);
138EXPORT_SYMBOL(claim_fiq);
139EXPORT_SYMBOL(release_fiq);
140EXPORT_SYMBOL(enable_fiq);
141EXPORT_SYMBOL(disable_fiq);
142
143void __init init_FIQ(void)
144{
145 no_fiq_insn = *(unsigned long *)0xffff001c;
146}
147