internals.h 5.5 KB
Newer Older
P
Paul Mundt 已提交
1 2 3 4 5 6
#include <linux/sh_intc.h>
#include <linux/irq.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/radix-tree.h>
7
#include <linux/device.h>
P
Paul Mundt 已提交
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
	((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
	 ((addr_e) << 16) | ((addr_d << 24)))

#define _INTC_SHIFT(h)		(h & 0x1f)
#define _INTC_WIDTH(h)		((h >> 5) & 0xf)
#define _INTC_FN(h)		((h >> 9) & 0xf)
#define _INTC_MODE(h)		((h >> 13) & 0x7)
#define _INTC_ADDR_E(h)		((h >> 16) & 0xff)
#define _INTC_ADDR_D(h)		((h >> 24) & 0xff)

#ifdef CONFIG_SMP
#define IS_SMP(x)		(x.smp)
#define INTC_REG(d, x, c)	(d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
#define SMP_NR(d, x)		((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
#else
#define IS_SMP(x)		0
#define INTC_REG(d, x, c)	(d->reg[(x)])
#define SMP_NR(d, x)		1
#endif

struct intc_handle_int {
	unsigned int irq;
	unsigned long handle;
};

struct intc_window {
	phys_addr_t phys;
	void __iomem *virt;
	unsigned long size;
};

struct intc_map_entry {
	intc_enum enum_id;
	struct intc_desc_int *desc;
};

struct intc_subgroup_entry {
	unsigned int pirq;
	intc_enum enum_id;
	unsigned long handle;
};

struct intc_desc_int {
	struct list_head list;
54
	struct device dev;
P
Paul Mundt 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
	struct radix_tree_root tree;
	raw_spinlock_t lock;
	unsigned int index;
	unsigned long *reg;
#ifdef CONFIG_SMP
	unsigned long *smp;
#endif
	unsigned int nr_reg;
	struct intc_handle_int *prio;
	unsigned int nr_prio;
	struct intc_handle_int *sense;
	unsigned int nr_sense;
	struct intc_window *window;
	unsigned int nr_windows;
	struct irq_chip chip;
70
	bool skip_suspend;
P
Paul Mundt 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
};


enum {
	REG_FN_ERR = 0,
	REG_FN_TEST_BASE = 1,
	REG_FN_WRITE_BASE = 5,
	REG_FN_MODIFY_BASE = 9
};

enum {	MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
	MODE_MASK_REG,       /* Bit(s) set -> interrupt disabled */
	MODE_DUAL_REG,       /* Two registers, set bit to enable / disable */
	MODE_PRIO_REG,       /* Priority value written to enable interrupt */
	MODE_PCLR_REG,       /* Above plus all bits set to disable interrupt */
};

static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
{
T
Thomas Gleixner 已提交
90
	struct irq_chip *chip = irq_get_chip(irq);
P
Paul Mundt 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

	return container_of(chip, struct intc_desc_int, chip);
}

/*
 * Grumble.
 */
static inline void activate_irq(int irq)
{
#ifdef CONFIG_ARM
	/* ARM requires an extra step to clear IRQ_NOREQUEST, which it
	 * sets on behalf of every irq_chip.  Also sets IRQ_NOPROBE.
	 */
	set_irq_flags(irq, IRQF_VALID);
#else
	/* same effect on other architectures */
T
Thomas Gleixner 已提交
107
	irq_set_noprobe(irq);
P
Paul Mundt 已提交
108 109 110
#endif
}

P
Paul Mundt 已提交
111 112 113 114 115 116 117 118
static inline int intc_handle_int_cmp(const void *a, const void *b)
{
	const struct intc_handle_int *_a = a;
	const struct intc_handle_int *_b = b;

	return _a->irq - _b->irq;
}

P
Paul Mundt 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
/* access.c */
extern unsigned long
(*intc_reg_fns[])(unsigned long addr, unsigned long h, unsigned long data);

extern unsigned long
(*intc_enable_fns[])(unsigned long addr, unsigned long handle,
		     unsigned long (*fn)(unsigned long,
				unsigned long, unsigned long),
		     unsigned int irq);
extern unsigned long
(*intc_disable_fns[])(unsigned long addr, unsigned long handle,
		      unsigned long (*fn)(unsigned long,
				unsigned long, unsigned long),
		      unsigned int irq);
extern unsigned long
(*intc_enable_noprio_fns[])(unsigned long addr, unsigned long handle,
		            unsigned long (*fn)(unsigned long,
				unsigned long, unsigned long),
			    unsigned int irq);

unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address);
unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address);
unsigned int intc_set_field_from_handle(unsigned int value,
			    unsigned int field_value,
			    unsigned int handle);
unsigned long intc_get_field_from_handle(unsigned int value,
					 unsigned int handle);

/* balancing.c */
#ifdef CONFIG_INTC_BALANCING
void intc_balancing_enable(unsigned int irq);
void intc_balancing_disable(unsigned int irq);
void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
			  struct intc_desc_int *d, intc_enum id);
#else
154 155 156 157 158
static inline void intc_balancing_enable(unsigned int irq) { }
static inline void intc_balancing_disable(unsigned int irq) { }
static inline void
intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
		     struct intc_desc_int *d, intc_enum id) { }
P
Paul Mundt 已提交
159 160 161 162
#endif

/* chip.c */
extern struct irq_chip intc_irq_chip;
P
Paul Mundt 已提交
163
void _intc_enable(struct irq_data *data, unsigned long handle);
P
Paul Mundt 已提交
164 165 166 167

/* core.c */
extern struct list_head intc_list;
extern raw_spinlock_t intc_big_lock;
168
extern struct bus_type intc_subsys;
P
Paul Mundt 已提交
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

unsigned int intc_get_dfl_prio_level(void);
unsigned int intc_get_prio_level(unsigned int irq);
void intc_set_prio_level(unsigned int irq, unsigned int level);

/* handle.c */
unsigned int intc_get_mask_handle(struct intc_desc *desc,
				  struct intc_desc_int *d,
				  intc_enum enum_id, int do_grps);
unsigned int intc_get_prio_handle(struct intc_desc *desc,
				  struct intc_desc_int *d,
				  intc_enum enum_id, int do_grps);
unsigned int intc_get_sense_handle(struct intc_desc *desc,
				   struct intc_desc_int *d,
				   intc_enum enum_id);
void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc,
			 struct intc_desc_int *d, intc_enum id);
unsigned long intc_get_ack_handle(unsigned int irq);
void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d,
			      intc_enum enum_id, int enable);

/* virq.c */
void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d);
void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d);
struct intc_map_entry *intc_irq_xlate_get(unsigned int irq);