Skip to content

Commit 7f31784

Browse files
ajaykathatclaudiubeznea
authored andcommitted
staging: wilc1000: fix compilation error for linux kernel 3.10
Added the missing API's required for interrupt property for kernel 3.10. These API' were available after 3.15 kernel version so added these change to support compilation on earlier version. Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
1 parent ab4e0e1 commit 7f31784

1 file changed

Lines changed: 321 additions & 0 deletions

File tree

drivers/staging/wilc1000/debugfs.h

Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#define WILC_DEBUGFS_H
99

1010
#include <linux/kern_levels.h>
11+
#include <linux/version.h>
12+
#if KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE
13+
#include <linux/of_irq.h>
14+
#endif
1115

1216
#define GENERIC_DBG BIT(0)
1317
#define HOSTAPD_DBG BIT(1)
@@ -47,4 +51,321 @@ extern atomic_t WILC_DEBUG_REGION;
4751

4852
int wilc_debugfs_init(void);
4953
void wilc_debugfs_remove(void);
54+
55+
#if KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE
56+
/**
57+
* of_irq_parse_raw - Low level interrupt tree parsing
58+
* @parent: the device interrupt parent
59+
* @addr: address specifier (start of "reg" property of the device)
60+
* in be32 format
61+
* @out_irq: structure of_irq updated by this function
62+
*
63+
* Returns 0 on success and a negative number on error
64+
*
65+
* This function is a low-level interrupt tree walking function. It
66+
* can be used to do a partial walk with synthetized reg and interrupts
67+
* properties, for example when resolving PCI interrupts when no device
68+
* node exist for the parent. It takes an interrupt specifier structure as
69+
* input, walks the tree looking for any interrupt-map properties, translates
70+
* the specifier for each map, and then returns the translated map.
71+
*/
72+
int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
73+
{
74+
struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
75+
__be32 initial_match_array[MAX_PHANDLE_ARGS];
76+
const __be32 *match_array = initial_match_array;
77+
const __be32 *tmp, *imap, *imask;
78+
const __be32 dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
79+
u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
80+
int imaplen, match, i;
81+
82+
#ifdef DEBUG
83+
of_print_phandle_args("of_irq_parse_raw: ", out_irq);
84+
#endif
85+
86+
ipar = of_node_get(out_irq->np);
87+
88+
/* First get the #interrupt-cells property of the current cursor
89+
* that tells us how to interpret the passed-in intspec. If there
90+
* is none, we are nice and just walk up the tree
91+
*/
92+
do {
93+
tmp = of_get_property(ipar, "#interrupt-cells", NULL);
94+
if (tmp != NULL) {
95+
intsize = be32_to_cpu(*tmp);
96+
break;
97+
}
98+
tnode = ipar;
99+
ipar = of_irq_find_parent(ipar);
100+
of_node_put(tnode);
101+
} while (ipar);
102+
if (ipar == NULL) {
103+
pr_debug(" -> no parent found !\n");
104+
goto fail;
105+
}
106+
107+
pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n",
108+
of_node_full_name(ipar), intsize);
109+
110+
if (out_irq->args_count != intsize)
111+
return -EINVAL;
112+
113+
/* Look for this #address-cells. We have to implement the old linux
114+
* trick of looking for the parent here as some device-trees rely on it
115+
*/
116+
old = of_node_get(ipar);
117+
do {
118+
tmp = of_get_property(old, "#address-cells", NULL);
119+
tnode = of_get_parent(old);
120+
of_node_put(old);
121+
old = tnode;
122+
} while (old && tmp == NULL);
123+
of_node_put(old);
124+
old = NULL;
125+
addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
126+
127+
pr_debug(" -> addrsize=%d\n", addrsize);
128+
129+
/* Range check so that the temporary buffer doesn't overflow */
130+
if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS))
131+
goto fail;
132+
133+
/* Precalculate the match array - this simplifies match loop */
134+
for (i = 0; i < addrsize; i++)
135+
initial_match_array[i] = addr ? addr[i] : 0;
136+
for (i = 0; i < intsize; i++)
137+
initial_match_array[addrsize + i] =
138+
cpu_to_be32(out_irq->args[i]);
139+
140+
/* Now start the actual "proper" walk of the interrupt tree */
141+
while (ipar != NULL) {
142+
/* Now check if cursor is an interrupt-controller and if it is
143+
* then we are done
144+
*/
145+
if (of_get_property(ipar, "interrupt-controller", NULL) !=
146+
NULL) {
147+
pr_debug(" -> got it !\n");
148+
return 0;
149+
}
150+
151+
/*
152+
* interrupt-map parsing does not work without a reg
153+
* property when #address-cells != 0
154+
*/
155+
if (addrsize && !addr) {
156+
pr_debug(" -> no reg passed in when needed !\n");
157+
goto fail;
158+
}
159+
160+
/* Now look for an interrupt-map */
161+
imap = of_get_property(ipar, "interrupt-map", &imaplen);
162+
/* No interrupt map, check for an interrupt parent */
163+
if (imap == NULL) {
164+
pr_debug(" -> no map, getting parent\n");
165+
newpar = of_irq_find_parent(ipar);
166+
goto skiplevel;
167+
}
168+
imaplen /= sizeof(u32);
169+
170+
/* Look for a mask */
171+
imask = of_get_property(ipar, "interrupt-map-mask", NULL);
172+
if (!imask)
173+
imask = dummy_imask;
174+
175+
/* Parse interrupt-map */
176+
match = 0;
177+
while (imaplen > (addrsize + intsize + 1) && !match) {
178+
/* Compare specifiers */
179+
match = 1;
180+
for (i = 0; i < (addrsize + intsize); i++, imaplen--)
181+
match &= !((match_array[i] ^ *imap++) &
182+
imask[i]);
183+
184+
pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
185+
186+
/* Get the interrupt parent */
187+
if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
188+
newpar = of_node_get(of_irq_dflt_pic);
189+
else
190+
newpar =
191+
of_find_node_by_phandle(be32_to_cpup(imap));
192+
imap++;
193+
--imaplen;
194+
195+
/* Check if not found */
196+
if (newpar == NULL) {
197+
pr_debug(" -> imap parent not found !\n");
198+
goto fail;
199+
}
200+
201+
if (!of_device_is_available(newpar))
202+
match = 0;
203+
204+
/* Get #interrupt-cells and #address-cells of new
205+
* parent
206+
*/
207+
tmp = of_get_property(newpar, "#interrupt-cells", NULL);
208+
if (tmp == NULL) {
209+
pr_debug(" -> parent lacks #interrupt-cells!\n");
210+
goto fail;
211+
}
212+
newintsize = be32_to_cpu(*tmp);
213+
tmp = of_get_property(newpar, "#address-cells", NULL);
214+
newaddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp);
215+
216+
pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
217+
newintsize, newaddrsize);
218+
219+
/* Check for malformed properties */
220+
if (WARN_ON(newaddrsize + newintsize >
221+
MAX_PHANDLE_ARGS))
222+
goto fail;
223+
if (imaplen < (newaddrsize + newintsize))
224+
goto fail;
225+
226+
imap += newaddrsize + newintsize;
227+
imaplen -= newaddrsize + newintsize;
228+
229+
pr_debug(" -> imaplen=%d\n", imaplen);
230+
}
231+
if (!match)
232+
goto fail;
233+
234+
/*
235+
* Successfully parsed an interrrupt-map translation; copy new
236+
* interrupt specifier into the out_irq structure
237+
*/
238+
out_irq->np = newpar;
239+
240+
match_array = imap - newaddrsize - newintsize;
241+
for (i = 0; i < newintsize; i++)
242+
out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
243+
out_irq->args_count = intsize = newintsize;
244+
addrsize = newaddrsize;
245+
246+
skiplevel:
247+
/* Iterate again with new parent */
248+
pr_debug(" -> new parent: %s\n", of_node_full_name(newpar));
249+
of_node_put(ipar);
250+
ipar = newpar;
251+
newpar = NULL;
252+
}
253+
fail:
254+
of_node_put(ipar);
255+
of_node_put(newpar);
256+
257+
return -EINVAL;
258+
}
259+
260+
static inline int of_irq_parse_oldworld(struct device_node *device, int index,
261+
struct of_phandle_args *out_irq)
262+
{
263+
return -EINVAL;
264+
}
265+
/**
266+
* of_irq_parse_one - Resolve an interrupt for a device
267+
* @device: the device whose interrupt is to be resolved
268+
* @index: index of the interrupt to resolve
269+
* @out_irq: structure of_irq filled by this function
270+
*
271+
* This function resolves an interrupt for a node by walking the interrupt tree,
272+
* finding which interrupt controller node it is attached to, and returning the
273+
* interrupt specifier that can be used to retrieve a Linux IRQ number.
274+
*/
275+
int of_irq_parse_one(struct device_node *device, int index,
276+
struct of_phandle_args *out_irq)
277+
{
278+
struct device_node *p;
279+
const __be32 *intspec, *tmp, *addr;
280+
u32 intsize, intlen;
281+
int i, res;
282+
283+
pr_debug("of_irq_parse_one: dev=%s, index=%d\n",
284+
of_node_full_name(device), index);
285+
286+
/* OldWorld mac stuff is "special", handle out of line */
287+
if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
288+
return of_irq_parse_oldworld(device, index, out_irq);
289+
290+
/* Get the reg property (if any) */
291+
addr = of_get_property(device, "reg", NULL);
292+
293+
/* Try the new-style interrupts-extended first */
294+
res = of_parse_phandle_with_args(device, "interrupts-extended",
295+
"#interrupt-cells", index, out_irq);
296+
if (!res)
297+
return of_irq_parse_raw(addr, out_irq);
298+
299+
/* Get the interrupts property */
300+
intspec = of_get_property(device, "interrupts", &intlen);
301+
if (intspec == NULL)
302+
return -EINVAL;
303+
304+
intlen /= sizeof(*intspec);
305+
306+
pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
307+
308+
/* Look for the interrupt parent. */
309+
p = of_irq_find_parent(device);
310+
if (p == NULL)
311+
return -EINVAL;
312+
313+
/* Get size of interrupt specifier */
314+
tmp = of_get_property(p, "#interrupt-cells", NULL);
315+
if (tmp == NULL) {
316+
res = -EINVAL;
317+
goto out;
318+
}
319+
intsize = be32_to_cpu(*tmp);
320+
321+
pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
322+
323+
/* Check index */
324+
if ((index + 1) * intsize > intlen) {
325+
res = -EINVAL;
326+
goto out;
327+
}
328+
329+
/* Copy intspec into irq structure */
330+
intspec += index * intsize;
331+
out_irq->np = p;
332+
out_irq->args_count = intsize;
333+
for (i = 0; i < intsize; i++)
334+
out_irq->args[i] = be32_to_cpup(intspec++);
335+
336+
/* Check if there are any interrupt-map translations to process */
337+
res = of_irq_parse_raw(addr, out_irq);
338+
out:
339+
of_node_put(p);
340+
return res;
341+
}
342+
EXPORT_SYMBOL_GPL(of_irq_parse_one);
343+
344+
/**
345+
* of_irq_get - Decode a node's IRQ and return it as a Linux IRQ number
346+
* @dev: pointer to device tree node
347+
* @index: zero-based index of the IRQ
348+
*
349+
* Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
350+
* -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
351+
* of any other failure.
352+
*/
353+
int of_irq_get(struct device_node *dev, int index)
354+
{
355+
int rc;
356+
struct of_phandle_args oirq;
357+
struct irq_domain *domain;
358+
359+
rc = of_irq_parse_one(dev, index, &oirq);
360+
if (rc)
361+
return rc;
362+
363+
domain = irq_find_host(oirq.np);
364+
if (!domain)
365+
return -EPROBE_DEFER;
366+
367+
return irq_create_of_mapping(oirq.np, (const u32 *)&oirq.args,
368+
oirq.args_count);
369+
}
370+
#endif
50371
#endif /* WILC_DEBUGFS_H */

0 commit comments

Comments
 (0)