Skip to content

Commit 6267999

Browse files
committed
Merge branch 'at91-5.4-trunk/wilc' into linux-5.4-at91
2 parents 438d9a7 + 7f31784 commit 6267999

4 files changed

Lines changed: 392 additions & 129 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)