From 5b5ad5ba01cebe6a749bcf5c9fc9637876fe0b1f Mon Sep 17 00:00:00 2001 From: Luka Perkov Date: Tue, 11 Feb 2014 02:07:44 +0000 Subject: mvebu: backport mainline patches from kernel 3.13 This is a backport of the patches accepted to the Linux mainline related to mvebu SoC (Armada XP and Armada 370) between Linux v3.12, and Linux v3.13. This work mainly covers: * Finishes work for sharing the pxa nand driver(drivers/mtd/nand/pxa3xx_nand.c) between the PXA family, and the Armada family. * timer initialization update, and access function for the Armada family. * Generic IRQ handling backporting. * Some bug fixes. Signed-off-by: Seif Mazareeb CC: Luka Perkov git-svn-id: svn://svn.openwrt.org/openwrt/trunk@39566 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...186-of-irq-Refactor-interrupt-map-parsing.patch | 287 +++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 target/linux/mvebu/patches-3.10/0186-of-irq-Refactor-interrupt-map-parsing.patch (limited to 'target/linux/mvebu/patches-3.10/0186-of-irq-Refactor-interrupt-map-parsing.patch') diff --git a/target/linux/mvebu/patches-3.10/0186-of-irq-Refactor-interrupt-map-parsing.patch b/target/linux/mvebu/patches-3.10/0186-of-irq-Refactor-interrupt-map-parsing.patch new file mode 100644 index 0000000000..7f17bb737b --- /dev/null +++ b/target/linux/mvebu/patches-3.10/0186-of-irq-Refactor-interrupt-map-parsing.patch @@ -0,0 +1,287 @@ +From 44ad702902e9e274f57edce8944e46540b978f9a Mon Sep 17 00:00:00 2001 +From: Grant Likely +Date: Thu, 19 Dec 2013 09:30:57 -0300 +Subject: [PATCH 186/203] of/irq: Refactor interrupt-map parsing + +All the users of of_irq_parse_raw pass in a raw interrupt specifier from +the device tree and expect it to be returned (possibly modified) in an +of_phandle_args structure. However, the primary function of +of_irq_parse_raw() is to check for translations due to the presence of +one or more interrupt-map properties. The actual placing of the data +into an of_phandle_args structure is trivial. If it is refactored to +accept an of_phandle_args structure directly, then it becomes possible +to consume of_phandle_args from other sources. This is important for an +upcoming patch that allows a device to be connected to more than one +interrupt parent. It also simplifies the code a bit. + +The biggest complication with this patch is that the old version works +on the interrupt specifiers in __be32 form, but the of_phandle_args +structure is intended to carry it in the cpu-native version. A bit of +churn was required to make this work. In the end it results in tighter +code, so the churn is worth it. + +Signed-off-by: Grant Likely +Acked-by: Tony Lindgren +Cc: Benjamin Herrenschmidt +--- + arch/powerpc/platforms/fsl_uli1575.c | 6 +- + drivers/of/irq.c | 108 ++++++++++++++++++----------------- + drivers/of/of_pci_irq.c | 7 ++- + include/linux/of_irq.h | 5 +- + 4 files changed, 67 insertions(+), 59 deletions(-) + +--- a/arch/powerpc/platforms/fsl_uli1575.c ++++ b/arch/powerpc/platforms/fsl_uli1575.c +@@ -322,7 +322,6 @@ static void hpcd_final_uli5288(struct pc + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct device_node *hosenode = hose ? hose->dn : NULL; + struct of_phandle_args oirq; +- int pin = 2; + u32 laddr[3]; + + if (!machine_is(mpc86xx_hpcd)) +@@ -331,9 +330,12 @@ static void hpcd_final_uli5288(struct pc + if (!hosenode) + return; + ++ oirq.np = hosenode; ++ oirq.args[0] = 2; ++ oirq.args_count = 1; + laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8); + laddr[1] = laddr[2] = 0; +- of_irq_parse_raw(hosenode, &pin, 1, laddr, &oirq); ++ of_irq_parse_raw(laddr, &oirq); + dev->irq = irq_create_of_mapping(&oirq); + } + +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -80,31 +80,32 @@ struct device_node *of_irq_find_parent(s + /** + * of_irq_parse_raw - Low level interrupt tree parsing + * @parent: the device interrupt parent +- * @intspec: interrupt specifier ("interrupts" property of the device) +- * @ointsize: size of the passed in interrupt specifier +- * @addr: address specifier (start of "reg" property of the device) +- * @out_irq: structure of_irq filled by this function ++ * @addr: address specifier (start of "reg" property of the device) in be32 format ++ * @out_irq: structure of_irq updated by this function + * + * Returns 0 on success and a negative number on error + * + * This function is a low-level interrupt tree walking function. It + * can be used to do a partial walk with synthetized reg and interrupts + * properties, for example when resolving PCI interrupts when no device +- * node exist for the parent. ++ * node exist for the parent. It takes an interrupt specifier structure as ++ * input, walks the tree looking for any interrupt-map properties, translates ++ * the specifier for each map, and then returns the translated map. + */ +-int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, +- u32 ointsize, const __be32 *addr, struct of_phandle_args *out_irq) ++int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + { + struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; +- const __be32 *tmp, *imap, *imask; ++ __be32 initial_match_array[8]; ++ const __be32 *match_array = initial_match_array; ++ const __be32 *tmp, *imap, *imask, dummy_imask[] = { ~0, ~0, ~0, ~0, ~0 }; + u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; + int imaplen, match, i; + + pr_debug("of_irq_parse_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", +- of_node_full_name(parent), be32_to_cpup(intspec), +- be32_to_cpup(intspec + 1), ointsize); ++ of_node_full_name(out_irq->np), out_irq->args[0], out_irq->args[1], ++ out_irq->args_count); + +- ipar = of_node_get(parent); ++ ipar = of_node_get(out_irq->np); + + /* First get the #interrupt-cells property of the current cursor + * that tells us how to interpret the passed-in intspec. If there +@@ -127,7 +128,7 @@ int of_irq_parse_raw(struct device_node + + pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize); + +- if (ointsize != intsize) ++ if (out_irq->args_count != intsize) + return -EINVAL; + + /* Look for this #address-cells. We have to implement the old linux +@@ -146,6 +147,21 @@ int of_irq_parse_raw(struct device_node + + pr_debug(" -> addrsize=%d\n", addrsize); + ++ /* If we were passed no "reg" property and we attempt to parse ++ * an interrupt-map, then #address-cells must be 0. ++ * Fail if it's not. ++ */ ++ if (addr == NULL && addrsize != 0) { ++ pr_debug(" -> no reg passed in when needed !\n"); ++ return -EINVAL; ++ } ++ ++ /* Precalculate the match array - this simplifies match loop */ ++ for (i = 0; i < addrsize; i++) ++ initial_match_array[i] = addr[i]; ++ for (i = 0; i < intsize; i++) ++ initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]); ++ + /* Now start the actual "proper" walk of the interrupt tree */ + while (ipar != NULL) { + /* Now check if cursor is an interrupt-controller and if it is +@@ -154,11 +170,6 @@ int of_irq_parse_raw(struct device_node + if (of_get_property(ipar, "interrupt-controller", NULL) != + NULL) { + pr_debug(" -> got it !\n"); +- for (i = 0; i < intsize; i++) +- out_irq->args[i] = +- of_read_number(intspec +i, 1); +- out_irq->args_count = intsize; +- out_irq->np = ipar; + of_node_put(old); + return 0; + } +@@ -175,34 +186,16 @@ int of_irq_parse_raw(struct device_node + + /* Look for a mask */ + imask = of_get_property(ipar, "interrupt-map-mask", NULL); +- +- /* If we were passed no "reg" property and we attempt to parse +- * an interrupt-map, then #address-cells must be 0. +- * Fail if it's not. +- */ +- if (addr == NULL && addrsize != 0) { +- pr_debug(" -> no reg passed in when needed !\n"); +- goto fail; +- } ++ if (!imask) ++ imask = dummy_imask; + + /* Parse interrupt-map */ + match = 0; + while (imaplen > (addrsize + intsize + 1) && !match) { + /* Compare specifiers */ + match = 1; +- for (i = 0; i < addrsize && match; ++i) { +- __be32 mask = imask ? imask[i] +- : cpu_to_be32(0xffffffffu); +- match = ((addr[i] ^ imap[i]) & mask) == 0; +- } +- for (; i < (addrsize + intsize) && match; ++i) { +- __be32 mask = imask ? imask[i] +- : cpu_to_be32(0xffffffffu); +- match = +- ((intspec[i-addrsize] ^ imap[i]) & mask) == 0; +- } +- imap += addrsize + intsize; +- imaplen -= addrsize + intsize; ++ for (i = 0; i < (addrsize + intsize); i++, imaplen--) ++ match = !((match_array[i] ^ *imap++) & imask[i]); + + pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); + +@@ -247,12 +240,18 @@ int of_irq_parse_raw(struct device_node + if (!match) + goto fail; + +- of_node_put(old); +- old = of_node_get(newpar); ++ /* ++ * Successfully parsed an interrrupt-map translation; copy new ++ * interrupt specifier into the out_irq structure ++ */ ++ of_node_put(out_irq->np); ++ out_irq->np = of_node_get(newpar); ++ ++ match_array = imap - newaddrsize - newintsize; ++ for (i = 0; i < newintsize; i++) ++ out_irq->args[i] = be32_to_cpup(imap - newintsize + i); ++ out_irq->args_count = intsize = newintsize; + addrsize = newaddrsize; +- intsize = newintsize; +- intspec = imap - intsize; +- addr = intspec - addrsize; + + skiplevel: + /* Iterate again with new parent */ +@@ -263,7 +262,7 @@ int of_irq_parse_raw(struct device_node + } + fail: + of_node_put(ipar); +- of_node_put(old); ++ of_node_put(out_irq->np); + of_node_put(newpar); + + return -EINVAL; +@@ -276,15 +275,16 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw); + * @index: index of the interrupt to resolve + * @out_irq: structure of_irq filled by this function + * +- * This function resolves an interrupt, walking the tree, for a given +- * device-tree node. It's the high level pendant to of_irq_parse_raw(). ++ * This function resolves an interrupt for a node by walking the interrupt tree, ++ * finding which interrupt controller node it is attached to, and returning the ++ * interrupt specifier that can be used to retrieve a Linux IRQ number. + */ + int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq) + { + struct device_node *p; + const __be32 *intspec, *tmp, *addr; + u32 intsize, intlen; +- int res = -EINVAL; ++ int i, res = -EINVAL; + + pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index); + +@@ -326,9 +326,15 @@ int of_irq_parse_one(struct device_node + if ((index + 1) * intsize > intlen) + goto out; + +- /* Get new specifier and map it */ +- res = of_irq_parse_raw(p, intspec + index * intsize, intsize, +- addr, out_irq); ++ /* Copy intspec into irq structure */ ++ intspec += index * intsize; ++ out_irq->np = p; ++ out_irq->args_count = intsize; ++ for (i = 0; i < intsize; i++) ++ out_irq->args[i] = be32_to_cpup(intspec++); ++ ++ /* Check if there are any interrupt-map translations to process */ ++ res = of_irq_parse_raw(addr, out_irq); + out: + of_node_put(p); + return res; +--- a/drivers/of/of_pci_irq.c ++++ b/drivers/of/of_pci_irq.c +@@ -85,9 +85,12 @@ int of_irq_parse_pci(const struct pci_de + pdev = ppdev; + } + ++ out_irq->np = ppnode; ++ out_irq->args_count = 1; ++ out_irq->args[0] = lspec; + lspec_be = cpu_to_be32(lspec); + laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); +- laddr[1] = laddr[2] = cpu_to_be32(0); +- return of_irq_parse_raw(ppnode, &lspec_be, 1, laddr, out_irq); ++ laddr[1] = laddr[2] = cpu_to_be32(0); ++ return of_irq_parse_raw(laddr, out_irq); + } + EXPORT_SYMBOL_GPL(of_irq_parse_pci); +--- a/include/linux/of_irq.h ++++ b/include/linux/of_irq.h +@@ -31,10 +31,7 @@ static inline int of_irq_parse_oldworld( + } + #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */ + +- +-extern int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, +- u32 ointsize, const __be32 *addr, +- struct of_phandle_args *out_irq); ++extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq); + extern int of_irq_parse_one(struct device_node *device, int index, + struct of_phandle_args *out_irq); + extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data); -- cgit v1.2.3