summaryrefslogtreecommitdiff
path: root/include/linux/of_irq.h
blob: 2a64d8cecaaeb6859e826350d09f92cf77a11282 (plain)
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __OF_IRQ_H
#define __OF_IRQ_H

#include <linux/types.h>
#include <linux/errno.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/ioport.h>
#include <linux/of.h>

typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);

struct of_imap_parser {
	struct device_node *node;
	const __be32 *imap;
	const __be32 *imap_end;
	u32 parent_offset;
};

struct of_imap_item {
	struct of_phandle_args parent_args;
	u32 child_imap_count;
	u32 child_imap[16]; /* Arbitrary size.
			     * Should be #address-cells + #interrupt-cells but
			     * avoid using allocation and so, expect that 16
			     * should be enough
			     */
};

/*
 * If the iterator is exited prematurely (break, goto, return) of_node_put() has
 * to be called on item.parent_args.np
 */
#define for_each_of_imap_item(parser, item) \
	for (; of_imap_parser_one(parser, item);)

/*
 * Workarounds only applied to 32bit powermac machines
 */
#define OF_IMAP_OLDWORLD_MAC	0x00000001
#define OF_IMAP_NO_PHANDLE	0x00000002

#if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
extern unsigned int of_irq_workarounds;
extern struct device_node *of_irq_dflt_pic;
int of_irq_parse_oldworld(const struct device_node *device, int index,
			  struct of_phandle_args *out_irq);
#else /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
#define of_irq_workarounds (0)
#define of_irq_dflt_pic (NULL)
static inline int of_irq_parse_oldworld(const struct device_node *device, int index,
				      struct of_phandle_args *out_irq)
{
	return -EINVAL;
}
#endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */

extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq);
extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);
extern int of_irq_to_resource(struct device_node *dev, int index,
			      struct resource *r);

#ifdef CONFIG_OF_IRQ
extern void of_irq_init(const struct of_device_id *matches);
extern int of_irq_parse_one(struct device_node *device, int index,
			  struct of_phandle_args *out_irq);
extern int of_irq_count(struct device_node *dev);
extern int of_irq_get(struct device_node *dev, int index);
extern const struct cpumask *of_irq_get_affinity(struct device_node *dev,
						      int index);
extern int of_irq_get_byname(struct device_node *dev, const char *name);
extern int of_irq_to_resource_table(struct device_node *dev,
		struct resource *res, int nr_irqs);
extern struct device_node *of_irq_find_parent(struct device_node *child);
extern int of_imap_parser_init(struct of_imap_parser *parser,
			       struct device_node *node,
			       struct of_imap_item *item);
extern struct of_imap_item *of_imap_parser_one(struct of_imap_parser *parser,
					       struct of_imap_item *item);
extern struct irq_domain *of_msi_get_domain(struct device *dev,
					    const struct device_node *np,
					    enum irq_domain_bus_token token);
extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev,
							u32 id,
							u32 bus_token);
extern void of_msi_configure(struct device *dev, const struct device_node *np);
extern u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in);
#else
static inline void of_irq_init(const struct of_device_id *matches)
{
}
static inline int of_irq_parse_one(struct device_node *device, int index,
				   struct of_phandle_args *out_irq)
{
	return -EINVAL;
}
static inline int of_irq_count(struct device_node *dev)
{
	return 0;
}
static inline int of_irq_get(struct device_node *dev, int index)
{
	return 0;
}
static inline int of_irq_get_byname(struct device_node *dev, const char *name)
{
	return 0;
}
static inline const struct cpumask *of_irq_get_affinity(struct device_node *dev,
							int index)
{
	return NULL;
}
static inline int of_irq_to_resource_table(struct device_node *dev,
					   struct resource *res, int nr_irqs)
{
	return 0;
}
static inline void *of_irq_find_parent(struct device_node *child)
{
	return NULL;
}
static inline int of_imap_parser_init(struct of_imap_parser *parser,
				      struct device_node *node,
				      struct of_imap_item *item)
{
	return -ENOSYS;
}
static inline struct of_imap_item *of_imap_parser_one(struct of_imap_parser *parser,
						      struct of_imap_item *item)
{
	return NULL;
}
static inline struct irq_domain *of_msi_get_domain(struct device *dev,
						   struct device_node *np,
						   enum irq_domain_bus_token token)
{
	return NULL;
}
static inline struct irq_domain *of_msi_map_get_device_domain(struct device *dev,
						u32 id, u32 bus_token)
{
	return NULL;
}
static inline void of_msi_configure(struct device *dev, struct device_node *np)
{
}
static inline u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in)
{
	return id_in;
}
#endif

#if defined(CONFIG_OF_IRQ) || defined(CONFIG_SPARC)
/*
 * irq_of_parse_and_map() is used by all OF enabled platforms; but SPARC
 * implements it differently.  However, the prototype is the same for all,
 * so declare it here regardless of the CONFIG_OF_IRQ setting.
 */
extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);

#else /* !CONFIG_OF && !CONFIG_SPARC */
static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
						int index)
{
	return 0;
}
#endif /* !CONFIG_OF */

#endif /* __OF_IRQ_H */