Skip to content

Commit 44b10f2

Browse files
committed
Merge branch 'at91-5.4-trunk/wilc' into linux-5.4-at91
2 parents 8c5e380 + 7ef779c commit 44b10f2

3 files changed

Lines changed: 317 additions & 314 deletions

File tree

drivers/staging/wilc1000/debugfs.c

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

16331
#if defined(WILC_DEBUGFS)
17332
static struct dentry *wilc_dir;

0 commit comments

Comments
 (0)