aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh/intc/internals.h
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-10-05 09:10:30 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-10-05 09:10:30 -0400
commit2be6bb0c79c7fbda3425b65ee51c558bbaf4cf91 (patch)
treedb0dafd7e7f83945edc2c50c358a3d81fca960c3 /drivers/sh/intc/internals.h
parentd74310d3b18aabbb7d0549ea9e3fd3259c1dce00 (diff)
sh: intc: Split up the INTC code.
This splits up the sh intc core in to something more vaguely resembling a subsystem. Most of the functionality was alread fairly well compartmentalized, and there were only a handful of interdependencies that needed to be resolved in the process. This also serves as future-proofing for the genirq and sparseirq rework, which will make some of the split out functionality wholly generic, allowing things to be killed off in place with minimal migration pain. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/sh/intc/internals.h')
-rw-r--r--drivers/sh/intc/internals.h185
1 files changed, 185 insertions, 0 deletions
diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h
new file mode 100644
index 000000000000..f02a47f74930
--- /dev/null
+++ b/drivers/sh/intc/internals.h
@@ -0,0 +1,185 @@
1#include <linux/sh_intc.h>
2#include <linux/irq.h>
3#include <linux/list.h>
4#include <linux/kernel.h>
5#include <linux/types.h>
6#include <linux/radix-tree.h>
7#include <linux/sysdev.h>
8
9#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
10 ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
11 ((addr_e) << 16) | ((addr_d << 24)))
12
13#define _INTC_SHIFT(h) (h & 0x1f)
14#define _INTC_WIDTH(h) ((h >> 5) & 0xf)
15#define _INTC_FN(h) ((h >> 9) & 0xf)
16#define _INTC_MODE(h) ((h >> 13) & 0x7)
17#define _INTC_ADDR_E(h) ((h >> 16) & 0xff)
18#define _INTC_ADDR_D(h) ((h >> 24) & 0xff)
19
20#ifdef CONFIG_SMP
21#define IS_SMP(x) (x.smp)
22#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
23#define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
24#else
25#define IS_SMP(x) 0
26#define INTC_REG(d, x, c) (d->reg[(x)])
27#define SMP_NR(d, x) 1
28#endif
29
30struct intc_handle_int {
31 unsigned int irq;
32 unsigned long handle;
33};
34
35struct intc_window {
36 phys_addr_t phys;
37 void __iomem *virt;
38 unsigned long size;
39};
40
41struct intc_map_entry {
42 intc_enum enum_id;
43 struct intc_desc_int *desc;
44};
45
46struct intc_subgroup_entry {
47 unsigned int pirq;
48 intc_enum enum_id;
49 unsigned long handle;
50};
51
52struct intc_desc_int {
53 struct list_head list;
54 struct sys_device sysdev;
55 struct radix_tree_root tree;
56 pm_message_t state;
57 raw_spinlock_t lock;
58 unsigned int index;
59 unsigned long *reg;
60#ifdef CONFIG_SMP
61 unsigned long *smp;
62#endif
63 unsigned int nr_reg;
64 struct intc_handle_int *prio;
65 unsigned int nr_prio;
66 struct intc_handle_int *sense;
67 unsigned int nr_sense;
68 struct intc_window *window;
69 unsigned int nr_windows;
70 struct irq_chip chip;
71};
72
73
74enum {
75 REG_FN_ERR = 0,
76 REG_FN_TEST_BASE = 1,
77 REG_FN_WRITE_BASE = 5,
78 REG_FN_MODIFY_BASE = 9
79};
80
81enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
82 MODE_MASK_REG, /* Bit(s) set -> interrupt disabled */
83 MODE_DUAL_REG, /* Two registers, set bit to enable / disable */
84 MODE_PRIO_REG, /* Priority value written to enable interrupt */
85 MODE_PCLR_REG, /* Above plus all bits set to disable interrupt */
86};
87
88static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
89{
90 struct irq_chip *chip = get_irq_chip(irq);
91
92 return container_of(chip, struct intc_desc_int, chip);
93}
94
95/*
96 * Grumble.
97 */
98static inline void activate_irq(int irq)
99{
100#ifdef CONFIG_ARM
101 /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
102 * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE.
103 */
104 set_irq_flags(irq, IRQF_VALID);
105#else
106 /* same effect on other architectures */
107 set_irq_noprobe(irq);
108#endif
109}
110
111/* access.c */
112extern unsigned long
113(*intc_reg_fns[])(unsigned long addr, unsigned long h, unsigned long data);
114
115extern unsigned long
116(*intc_enable_fns[])(unsigned long addr, unsigned long handle,
117 unsigned long (*fn)(unsigned long,
118 unsigned long, unsigned long),
119 unsigned int irq);
120extern unsigned long
121(*intc_disable_fns[])(unsigned long addr, unsigned long handle,
122 unsigned long (*fn)(unsigned long,
123 unsigned long, unsigned long),
124 unsigned int irq);
125extern unsigned long
126(*intc_enable_noprio_fns[])(unsigned long addr, unsigned long handle,
127 unsigned long (*fn)(unsigned long,
128 unsigned long, unsigned long),
129 unsigned int irq);
130
131unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address);
132unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address);
133unsigned int intc_set_field_from_handle(unsigned int value,
134 unsigned int field_value,
135 unsigned int handle);
136unsigned long intc_get_field_from_handle(unsigned int value,
137 unsigned int handle);
138
139/* balancing.c */
140#ifdef CONFIG_INTC_BALANCING
141void intc_balancing_enable(unsigned int irq);
142void intc_balancing_disable(unsigned int irq);
143void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
144 struct intc_desc_int *d, intc_enum id);
145#else
146void intc_balancing_enable(unsigned int irq) { }
147void intc_balancing_disable(unsigned int irq) { }
148void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
149 struct intc_desc_int *d, intc_enum id) { }
150#endif
151
152/* chip.c */
153extern struct irq_chip intc_irq_chip;
154void _intc_enable(unsigned int irq, unsigned long handle);
155
156/* core.c */
157extern struct list_head intc_list;
158extern raw_spinlock_t intc_big_lock;
159extern unsigned int nr_intc_controllers;
160extern struct sysdev_class intc_sysdev_class;
161
162unsigned int intc_get_dfl_prio_level(void);
163unsigned int intc_get_prio_level(unsigned int irq);
164void intc_set_prio_level(unsigned int irq, unsigned int level);
165
166/* handle.c */
167unsigned int intc_get_mask_handle(struct intc_desc *desc,
168 struct intc_desc_int *d,
169 intc_enum enum_id, int do_grps);
170unsigned int intc_get_prio_handle(struct intc_desc *desc,
171 struct intc_desc_int *d,
172 intc_enum enum_id, int do_grps);
173unsigned int intc_get_sense_handle(struct intc_desc *desc,
174 struct intc_desc_int *d,
175 intc_enum enum_id);
176void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc,
177 struct intc_desc_int *d, intc_enum id);
178unsigned long intc_get_ack_handle(unsigned int irq);
179void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d,
180 intc_enum enum_id, int enable);
181
182/* virq.c */
183void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d);
184void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d);
185struct intc_map_entry *intc_irq_xlate_get(unsigned int irq);