base-files: define yes/no as valid boolean options
[openwrt.git] / target / linux / mvebu / patches-3.10 / 0186-of-irq-Refactor-interrupt-map-parsing.patch
1 From 44ad702902e9e274f57edce8944e46540b978f9a Mon Sep 17 00:00:00 2001
2 From: Grant Likely <grant.likely@linaro.org>
3 Date: Thu, 19 Dec 2013 09:30:57 -0300
4 Subject: [PATCH 186/203] of/irq: Refactor interrupt-map parsing
5
6 All the users of of_irq_parse_raw pass in a raw interrupt specifier from
7 the device tree and expect it to be returned (possibly modified) in an
8 of_phandle_args structure. However, the primary function of
9 of_irq_parse_raw() is to check for translations due to the presence of
10 one or more interrupt-map properties. The actual placing of the data
11 into an of_phandle_args structure is trivial. If it is refactored to
12 accept an of_phandle_args structure directly, then it becomes possible
13 to consume of_phandle_args from other sources. This is important for an
14 upcoming patch that allows a device to be connected to more than one
15 interrupt parent. It also simplifies the code a bit.
16
17 The biggest complication with this patch is that the old version works
18 on the interrupt specifiers in __be32 form, but the of_phandle_args
19 structure is intended to carry it in the cpu-native version. A bit of
20 churn was required to make this work. In the end it results in tighter
21 code, so the churn is worth it.
22
23 Signed-off-by: Grant Likely <grant.likely@linaro.org>
24 Acked-by: Tony Lindgren <tony@atomide.com>
25 Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
26 ---
27  arch/powerpc/platforms/fsl_uli1575.c |   6 +-
28  drivers/of/irq.c                     | 108 ++++++++++++++++++-----------------
29  drivers/of/of_pci_irq.c              |   7 ++-
30  include/linux/of_irq.h               |   5 +-
31  4 files changed, 67 insertions(+), 59 deletions(-)
32
33 --- a/arch/powerpc/platforms/fsl_uli1575.c
34 +++ b/arch/powerpc/platforms/fsl_uli1575.c
35 @@ -322,7 +322,6 @@ static void hpcd_final_uli5288(struct pc
36         struct pci_controller *hose = pci_bus_to_host(dev->bus);
37         struct device_node *hosenode = hose ? hose->dn : NULL;
38         struct of_phandle_args oirq;
39 -       int pin = 2;
40         u32 laddr[3];
41  
42         if (!machine_is(mpc86xx_hpcd))
43 @@ -331,9 +330,12 @@ static void hpcd_final_uli5288(struct pc
44         if (!hosenode)
45                 return;
46  
47 +       oirq.np = hosenode;
48 +       oirq.args[0] = 2;
49 +       oirq.args_count = 1;
50         laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
51         laddr[1] = laddr[2] = 0;
52 -       of_irq_parse_raw(hosenode, &pin, 1, laddr, &oirq);
53 +       of_irq_parse_raw(laddr, &oirq);
54         dev->irq = irq_create_of_mapping(&oirq);
55  }
56  
57 --- a/drivers/of/irq.c
58 +++ b/drivers/of/irq.c
59 @@ -80,31 +80,32 @@ struct device_node *of_irq_find_parent(s
60  /**
61   * of_irq_parse_raw - Low level interrupt tree parsing
62   * @parent:    the device interrupt parent
63 - * @intspec:   interrupt specifier ("interrupts" property of the device)
64 - * @ointsize:   size of the passed in interrupt specifier
65 - * @addr:      address specifier (start of "reg" property of the device)
66 - * @out_irq:   structure of_irq filled by this function
67 + * @addr:      address specifier (start of "reg" property of the device) in be32 format
68 + * @out_irq:   structure of_irq updated by this function
69   *
70   * Returns 0 on success and a negative number on error
71   *
72   * This function is a low-level interrupt tree walking function. It
73   * can be used to do a partial walk with synthetized reg and interrupts
74   * properties, for example when resolving PCI interrupts when no device
75 - * node exist for the parent.
76 + * node exist for the parent. It takes an interrupt specifier structure as
77 + * input, walks the tree looking for any interrupt-map properties, translates
78 + * the specifier for each map, and then returns the translated map.
79   */
80 -int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec,
81 -                  u32 ointsize, const __be32 *addr, struct of_phandle_args *out_irq)
82 +int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
83  {
84         struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
85 -       const __be32 *tmp, *imap, *imask;
86 +       __be32 initial_match_array[8];
87 +       const __be32 *match_array = initial_match_array;
88 +       const __be32 *tmp, *imap, *imask, dummy_imask[] = { ~0, ~0, ~0, ~0, ~0 };
89         u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
90         int imaplen, match, i;
91  
92         pr_debug("of_irq_parse_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
93 -                of_node_full_name(parent), be32_to_cpup(intspec),
94 -                be32_to_cpup(intspec + 1), ointsize);
95 +                of_node_full_name(out_irq->np), out_irq->args[0], out_irq->args[1],
96 +                out_irq->args_count);
97  
98 -       ipar = of_node_get(parent);
99 +       ipar = of_node_get(out_irq->np);
100  
101         /* First get the #interrupt-cells property of the current cursor
102          * that tells us how to interpret the passed-in intspec. If there
103 @@ -127,7 +128,7 @@ int of_irq_parse_raw(struct device_node
104  
105         pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize);
106  
107 -       if (ointsize != intsize)
108 +       if (out_irq->args_count != intsize)
109                 return -EINVAL;
110  
111         /* Look for this #address-cells. We have to implement the old linux
112 @@ -146,6 +147,21 @@ int of_irq_parse_raw(struct device_node
113  
114         pr_debug(" -> addrsize=%d\n", addrsize);
115  
116 +       /* If we were passed no "reg" property and we attempt to parse
117 +        * an interrupt-map, then #address-cells must be 0.
118 +        * Fail if it's not.
119 +        */
120 +       if (addr == NULL && addrsize != 0) {
121 +               pr_debug(" -> no reg passed in when needed !\n");
122 +               return -EINVAL;
123 +       }
124 +
125 +       /* Precalculate the match array - this simplifies match loop */
126 +       for (i = 0; i < addrsize; i++)
127 +               initial_match_array[i] = addr[i];
128 +       for (i = 0; i < intsize; i++)
129 +               initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
130 +
131         /* Now start the actual "proper" walk of the interrupt tree */
132         while (ipar != NULL) {
133                 /* Now check if cursor is an interrupt-controller and if it is
134 @@ -154,11 +170,6 @@ int of_irq_parse_raw(struct device_node
135                 if (of_get_property(ipar, "interrupt-controller", NULL) !=
136                                 NULL) {
137                         pr_debug(" -> got it !\n");
138 -                       for (i = 0; i < intsize; i++)
139 -                               out_irq->args[i] =
140 -                                               of_read_number(intspec +i, 1);
141 -                       out_irq->args_count = intsize;
142 -                       out_irq->np = ipar;
143                         of_node_put(old);
144                         return 0;
145                 }
146 @@ -175,34 +186,16 @@ int of_irq_parse_raw(struct device_node
147  
148                 /* Look for a mask */
149                 imask = of_get_property(ipar, "interrupt-map-mask", NULL);
150 -
151 -               /* If we were passed no "reg" property and we attempt to parse
152 -                * an interrupt-map, then #address-cells must be 0.
153 -                * Fail if it's not.
154 -                */
155 -               if (addr == NULL && addrsize != 0) {
156 -                       pr_debug(" -> no reg passed in when needed !\n");
157 -                       goto fail;
158 -               }
159 +               if (!imask)
160 +                       imask = dummy_imask;
161  
162                 /* Parse interrupt-map */
163                 match = 0;
164                 while (imaplen > (addrsize + intsize + 1) && !match) {
165                         /* Compare specifiers */
166                         match = 1;
167 -                       for (i = 0; i < addrsize && match; ++i) {
168 -                               __be32 mask = imask ? imask[i]
169 -                                                   : cpu_to_be32(0xffffffffu);
170 -                               match = ((addr[i] ^ imap[i]) & mask) == 0;
171 -                       }
172 -                       for (; i < (addrsize + intsize) && match; ++i) {
173 -                               __be32 mask = imask ? imask[i]
174 -                                                   : cpu_to_be32(0xffffffffu);
175 -                               match =
176 -                                  ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
177 -                       }
178 -                       imap += addrsize + intsize;
179 -                       imaplen -= addrsize + intsize;
180 +                       for (i = 0; i < (addrsize + intsize); i++, imaplen--)
181 +                               match = !((match_array[i] ^ *imap++) & imask[i]);
182  
183                         pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
184  
185 @@ -247,12 +240,18 @@ int of_irq_parse_raw(struct device_node
186                 if (!match)
187                         goto fail;
188  
189 -               of_node_put(old);
190 -               old = of_node_get(newpar);
191 +               /*
192 +                * Successfully parsed an interrrupt-map translation; copy new
193 +                * interrupt specifier into the out_irq structure
194 +                */
195 +               of_node_put(out_irq->np);
196 +               out_irq->np = of_node_get(newpar);
197 +
198 +               match_array = imap - newaddrsize - newintsize;
199 +               for (i = 0; i < newintsize; i++)
200 +                       out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
201 +               out_irq->args_count = intsize = newintsize;
202                 addrsize = newaddrsize;
203 -               intsize = newintsize;
204 -               intspec = imap - intsize;
205 -               addr = intspec - addrsize;
206  
207         skiplevel:
208                 /* Iterate again with new parent */
209 @@ -263,7 +262,7 @@ int of_irq_parse_raw(struct device_node
210         }
211   fail:
212         of_node_put(ipar);
213 -       of_node_put(old);
214 +       of_node_put(out_irq->np);
215         of_node_put(newpar);
216  
217         return -EINVAL;
218 @@ -276,15 +275,16 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw);
219   * @index: index of the interrupt to resolve
220   * @out_irq: structure of_irq filled by this function
221   *
222 - * This function resolves an interrupt, walking the tree, for a given
223 - * device-tree node. It's the high level pendant to of_irq_parse_raw().
224 + * This function resolves an interrupt for a node by walking the interrupt tree,
225 + * finding which interrupt controller node it is attached to, and returning the
226 + * interrupt specifier that can be used to retrieve a Linux IRQ number.
227   */
228  int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
229  {
230         struct device_node *p;
231         const __be32 *intspec, *tmp, *addr;
232         u32 intsize, intlen;
233 -       int res = -EINVAL;
234 +       int i, res = -EINVAL;
235  
236         pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
237  
238 @@ -326,9 +326,15 @@ int of_irq_parse_one(struct device_node
239         if ((index + 1) * intsize > intlen)
240                 goto out;
241  
242 -       /* Get new specifier and map it */
243 -       res = of_irq_parse_raw(p, intspec + index * intsize, intsize,
244 -                            addr, out_irq);
245 +       /* Copy intspec into irq structure */
246 +       intspec += index * intsize;
247 +       out_irq->np = p;
248 +       out_irq->args_count = intsize;
249 +       for (i = 0; i < intsize; i++)
250 +               out_irq->args[i] = be32_to_cpup(intspec++);
251 +
252 +       /* Check if there are any interrupt-map translations to process */
253 +       res = of_irq_parse_raw(addr, out_irq);
254   out:
255         of_node_put(p);
256         return res;
257 --- a/drivers/of/of_pci_irq.c
258 +++ b/drivers/of/of_pci_irq.c
259 @@ -85,9 +85,12 @@ int of_irq_parse_pci(const struct pci_de
260                 pdev = ppdev;
261         }
262  
263 +       out_irq->np = ppnode;
264 +       out_irq->args_count = 1;
265 +       out_irq->args[0] = lspec;
266         lspec_be = cpu_to_be32(lspec);
267         laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
268 -       laddr[1]  = laddr[2] = cpu_to_be32(0);
269 -       return of_irq_parse_raw(ppnode, &lspec_be, 1, laddr, out_irq);
270 +       laddr[1] = laddr[2] = cpu_to_be32(0);
271 +       return of_irq_parse_raw(laddr, out_irq);
272  }
273  EXPORT_SYMBOL_GPL(of_irq_parse_pci);
274 --- a/include/linux/of_irq.h
275 +++ b/include/linux/of_irq.h
276 @@ -31,10 +31,7 @@ static inline int of_irq_parse_oldworld(
277  }
278  #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
279  
280 -
281 -extern int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec,
282 -                         u32 ointsize, const __be32 *addr,
283 -                         struct of_phandle_args *out_irq);
284 +extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq);
285  extern int of_irq_parse_one(struct device_node *device, int index,
286                           struct of_phandle_args *out_irq);
287  extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);