From dc71bcf1b99c265fffdb1e8c60e7933612f3bca7 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Sat, 19 Jan 2013 10:20:42 -0800 Subject: of: fix incorrect return value of of_find_matching_node_and_match() The of_find_matching_node_and_match() function incorrectly sets the matched entry to 'matches' when the compatible value of a node matches one of the possible values. This results in incorrectly selecting the the first entry in the 'matches' list as the matched entry. Fix this by noting down the result of the call to of_match_node() and setting that as the matched entry. Signed-off-by: Thomas Abraham Signed-off-by: Rob Herring diff --git a/drivers/of/base.c b/drivers/of/base.c index 2390ddb..960ae5b 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -612,6 +612,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, const struct of_device_id **match) { struct device_node *np; + const struct of_device_id *m; if (match) *match = NULL; @@ -619,9 +620,10 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, read_lock(&devtree_lock); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { - if (of_match_node(matches, np) && of_node_get(np)) { + m = of_match_node(matches, np); + if (m && of_node_get(np)) { if (match) - *match = matches; + *match = m; break; } } -- cgit v0.10.2 From 425140af9e7040adc84a1b3f2c198eaf6eebc5aa Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Thu, 24 Jan 2013 08:18:35 +0400 Subject: of: Add vendor prefix for Cirrus Logic This patch adds a device tree vendor prefix for Cirrus Logic, Inc. Signed-off-by: Alexander Shiyan diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 902b1b1..723bd8d 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -14,6 +14,7 @@ bosch Bosch Sensortec GmbH brcm Broadcom Corporation cavium Cavium, Inc. chrp Common Hardware Reference Platform +cirrus Cirrus Logic, Inc. cortina Cortina Systems, Inc. dallas Maxim Integrated Products (formerly Dallas Semiconductor) denx Denx Software Engineering -- cgit v0.10.2 From 28d0e36bf96863df1195f8f7b9fd559142873389 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 25 Jan 2013 13:21:47 -0500 Subject: OF: Fixup resursive locking code paths There is no real reason to use a rwlock for devtree_lock. It even could be a mutex, but unfortunately it's locked from cpu hotplug paths which can't schedule :( So it needs to become a raw lock on rt as well. The devtree_lock would be the only user of a raw_rw_lock, so we are better off cleaning up the recursive locking paths which allows us to convert devtree_lock to a read_lock. Here we do the standard thing of introducing __foo() as the "raw" version of foo(), so that we can take better control of the locking. The "raw" versions are not exported and are for internal use within the file itself. Signed-off-by: Thomas Gleixner Signed-off-by: Paul Gortmaker Signed-off-by: Rob Herring diff --git a/drivers/of/base.c b/drivers/of/base.c index 960ae5b..16ee7a0 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -164,16 +164,14 @@ void of_node_put(struct device_node *node) EXPORT_SYMBOL(of_node_put); #endif /* CONFIG_OF_DYNAMIC */ -struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp) +static struct property *__of_find_property(const struct device_node *np, + const char *name, int *lenp) { struct property *pp; if (!np) return NULL; - read_lock(&devtree_lock); for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, name) == 0) { if (lenp) @@ -181,6 +179,18 @@ struct property *of_find_property(const struct device_node *np, break; } } + + return pp; +} + +struct property *of_find_property(const struct device_node *np, + const char *name, + int *lenp) +{ + struct property *pp; + + read_lock(&devtree_lock); + pp = __of_find_property(np, name, lenp); read_unlock(&devtree_lock); return pp; @@ -214,8 +224,20 @@ EXPORT_SYMBOL(of_find_all_nodes); * Find a property with a given name for a given node * and return the value. */ +static const void *__of_get_property(const struct device_node *np, + const char *name, int *lenp) +{ + struct property *pp = __of_find_property(np, name, lenp); + + return pp ? pp->value : NULL; +} + +/* + * Find a property with a given name for a given node + * and return the value. + */ const void *of_get_property(const struct device_node *np, const char *name, - int *lenp) + int *lenp) { struct property *pp = of_find_property(np, name, lenp); @@ -226,13 +248,13 @@ EXPORT_SYMBOL(of_get_property); /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ -int of_device_is_compatible(const struct device_node *device, - const char *compat) +static int __of_device_is_compatible(const struct device_node *device, + const char *compat) { const char* cp; int cplen, l; - cp = of_get_property(device, "compatible", &cplen); + cp = __of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { @@ -245,6 +267,20 @@ int of_device_is_compatible(const struct device_node *device, return 0; } + +/** Checks if the given "compat" string matches one of the strings in + * the device's "compatible" property + */ +int of_device_is_compatible(const struct device_node *device, + const char *compat) +{ + int res; + + read_lock(&devtree_lock); + res = __of_device_is_compatible(device, compat); + read_unlock(&devtree_lock); + return res; +} EXPORT_SYMBOL(of_device_is_compatible); /** @@ -518,7 +554,8 @@ struct device_node *of_find_compatible_node(struct device_node *from, if (type && !(np->type && (of_node_cmp(np->type, type) == 0))) continue; - if (of_device_is_compatible(np, compatible) && of_node_get(np)) + if (__of_device_is_compatible(np, compatible) && + of_node_get(np)) break; } of_node_put(from); @@ -562,15 +599,9 @@ out: } EXPORT_SYMBOL(of_find_node_with_property); -/** - * of_match_node - Tell if an device_node has a matching of_match structure - * @matches: array of of device match structures to search in - * @node: the of device structure to match against - * - * Low level utility function used by device matching. - */ -const struct of_device_id *of_match_node(const struct of_device_id *matches, - const struct device_node *node) +static +const struct of_device_id *__of_match_node(const struct of_device_id *matches, + const struct device_node *node) { if (!matches) return NULL; @@ -584,14 +615,32 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, match &= node->type && !strcmp(matches->type, node->type); if (matches->compatible[0]) - match &= of_device_is_compatible(node, - matches->compatible); + match &= __of_device_is_compatible(node, + matches->compatible); if (match) return matches; matches++; } return NULL; } + +/** + * of_match_node - Tell if an device_node has a matching of_match structure + * @matches: array of of device match structures to search in + * @node: the of device structure to match against + * + * Low level utility function used by device matching. + */ +const struct of_device_id *of_match_node(const struct of_device_id *matches, + const struct device_node *node) +{ + const struct of_device_id *match; + + read_lock(&devtree_lock); + match = __of_match_node(matches, node); + read_unlock(&devtree_lock); + return match; +} EXPORT_SYMBOL(of_match_node); /** @@ -620,7 +669,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, read_lock(&devtree_lock); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { - m = of_match_node(matches, np); + m = __of_match_node(matches, np); if (m && of_node_get(np)) { if (match) *match = m; -- cgit v0.10.2 From eb7ccb8184ab36b61fb596bd8d573e22e04d6266 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 24 Jan 2013 17:09:45 +0100 Subject: DT: add vendor prefixes for Renesas and Toshiba Signed-off-by: Guennadi Liakhovetski Signed-off-by: Rob Herring diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 723bd8d..4519dff 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -43,6 +43,7 @@ powervr PowerVR (deprecated, use img) qcom Qualcomm, Inc. ramtron Ramtron International realtek Realtek Semiconductor Corp. +renesas Renesas Electronics Corporation samsung Samsung Semiconductor sbs Smart Battery System schindler Schindler @@ -53,6 +54,7 @@ snps Synopsys, Inc. st STMicroelectronics stericsson ST-Ericsson ti Texas Instruments +toshiba Toshiba Corporation via VIA Technologies, Inc. wlf Wolfson Microelectronics wm Wondermedia Technologies, Inc. -- cgit v0.10.2 From ced4eec900850627409d7ff566b009471162b56b Mon Sep 17 00:00:00 2001 From: Stepan Moskovchenko Date: Thu, 6 Dec 2012 14:55:41 -0800 Subject: of: Output devicetree alias names in uevent In some situations, userspace may want to resolve a device by function and logical number (ie, "serial0") rather than by the base address or full device path. Being able to resolve a device by alias frees userspace from the burden of otherwise having to maintain a mapping between device addresses and their logical assignments on each platform when multiple instances of the same hardware block are present in the system. Although the uevent device attribute contains devicetree compatible information and the full device path, the uevent does not list the alises that may have been defined for the device. Signed-off-by: Stepan Moskovchenko [grant.likely: Removed OF_ALIAS_N field; I don't think it's needed] [grant.likely: Added #ifndef _LINUX_OF_PRIVATE_H wrapper] Signed-off-by: Grant Likely diff --git a/drivers/of/base.c b/drivers/of/base.c index 2390ddb..d1bb507 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -24,33 +24,16 @@ #include #include -/** - * struct alias_prop - Alias property in 'aliases' node - * @link: List node to link the structure in aliases_lookup list - * @alias: Alias property name - * @np: Pointer to device_node that the alias stands for - * @id: Index value from end of alias name - * @stem: Alias string without the index - * - * The structure represents one alias property of 'aliases' node as - * an entry in aliases_lookup list. - */ -struct alias_prop { - struct list_head link; - const char *alias; - struct device_node *np; - int id; - char stem[0]; -}; +#include "of_private.h" -static LIST_HEAD(aliases_lookup); +LIST_HEAD(aliases_lookup); struct device_node *of_allnodes; EXPORT_SYMBOL(of_allnodes); struct device_node *of_chosen; struct device_node *of_aliases; -static DEFINE_MUTEX(of_aliases_mutex); +DEFINE_MUTEX(of_aliases_mutex); /* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. diff --git a/drivers/of/device.c b/drivers/of/device.c index 4c74e4f..f685e55 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -8,6 +8,7 @@ #include #include +#include "of_private.h" /** * of_match_device - Tell if a struct device matches an of_device_id list @@ -131,6 +132,7 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) { const char *compat; + struct alias_prop *app; int seen = 0, cplen, sl; if ((!dev) || (!dev->of_node)) @@ -153,6 +155,17 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) seen++; } add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); + + seen = 0; + mutex_lock(&of_aliases_mutex); + list_for_each_entry(app, &aliases_lookup, link) { + if (dev->of_node == app->np) { + add_uevent_var(env, "OF_ALIAS_%d=%s", seen, + app->alias); + seen++; + } + } + mutex_unlock(&of_aliases_mutex); } int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h new file mode 100644 index 0000000..ff350c8 --- /dev/null +++ b/drivers/of/of_private.h @@ -0,0 +1,36 @@ +#ifndef _LINUX_OF_PRIVATE_H +#define _LINUX_OF_PRIVATE_H +/* + * Private symbols used by OF support code + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/** + * struct alias_prop - Alias property in 'aliases' node + * @link: List node to link the structure in aliases_lookup list + * @alias: Alias property name + * @np: Pointer to device_node that the alias stands for + * @id: Index value from end of alias name + * @stem: Alias string without the index + * + * The structure represents one alias property of 'aliases' node as + * an entry in aliases_lookup list. + */ +struct alias_prop { + struct list_head link; + const char *alias; + struct device_node *np; + int id; + char stem[0]; +}; + +extern struct mutex of_aliases_mutex; +extern struct list_head aliases_lookup; +#endif /* _LINUX_OF_PRIVATE_H */ -- cgit v0.10.2 From c0a05bf0182efdf7cd1fd8aa327e7a602360b67e Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 18 Dec 2012 11:32:03 +0100 Subject: of: add 'const' to of_node_full_name parameter As the function just returns the np->full_name or the string "", the passed device_node pointer is not changed in any way. The passed parameter can therefore be a const pointer. Also, fix the following error from checkpatch.pl: ERROR: "foo* bar" should be "foo *bar" +static inline const char* of_node_full_name(const struct device_node *np) Signed-off-by: Steffen Trumtrar Signed-off-by: Grant Likely diff --git a/include/linux/of.h b/include/linux/of.h index 5ebcc5c..1e0d0c1 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -160,7 +160,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size) #define OF_BAD_ADDR ((u64)-1) -static inline const char* of_node_full_name(struct device_node *np) +static inline const char *of_node_full_name(const struct device_node *np) { return np ? np->full_name : ""; } -- cgit v0.10.2 From f21ccfa07070228e0c32dad05d1cb0d19128517c Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Mon, 14 Jan 2013 15:14:56 +0900 Subject: documentation/devicetree: Fix typos Correct spelling typos within Documentation/devicetree Signed-off-by: Masanari Iida Signed-off-by: Grant Likely diff --git a/Documentation/devicetree/bindings/arm/atmel-aic.txt b/Documentation/devicetree/bindings/arm/atmel-aic.txt index 19078bf..ad03121 100644 --- a/Documentation/devicetree/bindings/arm/atmel-aic.txt +++ b/Documentation/devicetree/bindings/arm/atmel-aic.txt @@ -4,7 +4,7 @@ Required properties: - compatible: Should be "atmel,-aic" - interrupt-controller: Identifies the node as an interrupt controller. - interrupt-parent: For single AIC system, it is an empty property. -- #interrupt-cells: The number of cells to define the interrupts. It sould be 3. +- #interrupt-cells: The number of cells to define the interrupts. It should be 3. The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet). The second cell is used to specify flags: bits[3:0] trigger type and level flags: diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt index 62eb8df..3dfb0c0 100644 --- a/Documentation/devicetree/bindings/arm/gic.txt +++ b/Documentation/devicetree/bindings/arm/gic.txt @@ -42,7 +42,7 @@ Main node required properties: Optional - interrupts : Interrupt source of the parent interrupt controller on - secondary GICs, or VGIC maintainance interrupt on primary GIC (see + secondary GICs, or VGIC maintenance interrupt on primary GIC (see below). - cpu-offset : per-cpu offset within the distributor and cpu interface @@ -74,7 +74,7 @@ Required properties: virtual interface control register base and size. The 2nd additional region is the GIC virtual cpu interface register base and size. -- interrupts : VGIC maintainance interrupt. +- interrupts : VGIC maintenance interrupt. Example: diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt index d0051a7..f8288ea 100644 --- a/Documentation/devicetree/bindings/arm/omap/omap.txt +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt @@ -39,16 +39,16 @@ Boards: - OMAP3 Tobi with Overo : Commercial expansion board with daughter board compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3" -- OMAP4 SDP : Software Developement Board +- OMAP4 SDP : Software Development Board compatible = "ti,omap4-sdp", "ti,omap4430" - OMAP4 PandaBoard : Low cost community board compatible = "ti,omap4-panda", "ti,omap4430" -- OMAP3 EVM : Software Developement Board for OMAP35x, AM/DM37x +- OMAP3 EVM : Software Development Board for OMAP35x, AM/DM37x compatible = "ti,omap3-evm", "ti,omap3" -- AM335X EVM : Software Developement Board for AM335x +- AM335X EVM : Software Development Board for AM335x compatible = "ti,am335x-evm", "ti,am33xx", "ti,omap3" - AM335X Bone : Low cost community board diff --git a/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt b/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt index cb4291e..a5bdff4 100644 --- a/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt +++ b/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt @@ -1,7 +1,7 @@ * DMA Engine. The Octeon DMA Engine transfers between the Boot Bus and main memory. -The DMA Engine will be refered to by phandle by any device that is +The DMA Engine will be referred to by phandle by any device that is connected to it. Properties: diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt index 7927689..898b222 100644 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -11,11 +11,11 @@ Required Properties: * compatible: should be - "samsung,exynos4210-dw-mshc": for controllers with Samsung Exynos4210 - specific extentions. + specific extensions. - "samsung,exynos4412-dw-mshc": for controllers with Samsung Exynos4412 - specific extentions. + specific extensions. - "samsung,exynos5250-dw-mshc": for controllers with Samsung Exynos5250 - specific extentions. + specific extensions. * samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface unit (ciu) clock. This property is applicable only for Exynos5 SoC's and diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt index 97e9e31..3b3a1ee 100644 --- a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt +++ b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt @@ -55,5 +55,5 @@ Example: }; Note: This example shows both SoC specific and board specific properties - in a single device node. The properties can be actually be seperated + in a single device node. The properties can be actually be separated into SoC specific node and board specific node. diff --git a/Documentation/devicetree/bindings/powerpc/fsl/srio.txt b/Documentation/devicetree/bindings/powerpc/fsl/srio.txt index b039bcb..07abf0f 100644 --- a/Documentation/devicetree/bindings/powerpc/fsl/srio.txt +++ b/Documentation/devicetree/bindings/powerpc/fsl/srio.txt @@ -8,9 +8,9 @@ Properties: Definition: Must include "fsl,srio" for IP blocks with IP Block Revision Register (SRIO IPBRR1) Major ID equal to 0x01c0. - Optionally, a compatiable string of "fsl,srio-vX.Y" where X is Major + Optionally, a compatible string of "fsl,srio-vX.Y" where X is Major version in IP Block Revision Register and Y is Minor version. If this - compatiable is provided it should be ordered before "fsl,srio". + compatible is provided it should be ordered before "fsl,srio". - reg Usage: required diff --git a/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt index c8ca6b8..1b20c3d 100644 --- a/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt @@ -17,9 +17,9 @@ Optional properties: - ti,vsel1-gpio: Gpio for controlling VSEL1 line. If this property is missing, then assume that there is no GPIO for vsel1 control. -- ti,vsel0-state-high: Inital state of vsel0 input is high. +- ti,vsel0-state-high: Initial state of vsel0 input is high. If this property is missing, then assume the state as low (0). -- ti,vsel1-state-high: Inital state of vsel1 input is high. +- ti,vsel1-state-high: Initial state of vsel1 input is high. If this property is missing, then assume the state as low (0). Any property defined as part of the core regulator binding, defined in diff --git a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt index 90ec45f..7ac7259 100644 --- a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt @@ -7,7 +7,7 @@ Required properties: - reg: physical base address of the controller and length of memory mapped region. - interrupts: Two interrupt numbers to the cpu should be specified. First - interrupt number is the rtc alarm interupt and second interrupt number + interrupt number is the rtc alarm interrupt and second interrupt number is the rtc tick interrupt. The number of cells representing a interrupt depends on the parent interrupt controller. diff --git a/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt b/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt index 79ead82..ce0d8e7 100644 --- a/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt @@ -2,7 +2,7 @@ The Samsung's Watchdog controller is used for resuming system operation after a preset amount of time during which the WDT reset event has not -occured. +occurred. Required properties: - compatible : should be "samsung,s3c2410-wdt" -- cgit v0.10.2 From b5961f86802a1d76b377940ae6df53e877bdf235 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 18 Jan 2013 01:32:02 +0000 Subject: powerpc/5200: Fix size to request_mem_region() call The Bestcomm driver requests a memory region larger than the one described in the device tree. This is due to an extra undocumented field in the bestcomm register structure. This hasn't been a problem up to now, but there is a patch pending to make the DT platform_bus support code use platform_device_add() which tightens the rules and provides extra checks for drivers to stay within the specified register regions. Alternately, I could have removed the extra field from the structure, but I'm not sure if it is still needed for resume to work. Better be safe and leave it in. Signed-off-by: Grant Likely Cc: Benjamin Herrenschmidt Cc: Anatolij Gustschin diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c index d913063..81c3314 100644 --- a/arch/powerpc/sysdev/bestcomm/bestcomm.c +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c @@ -414,7 +414,7 @@ static int mpc52xx_bcom_probe(struct platform_device *op) goto error_sramclean; } - if (!request_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma), + if (!request_mem_region(res_bcom.start, resource_size(&res_bcom), DRIVER_NAME)) { printk(KERN_ERR DRIVER_NAME ": " "Can't request registers region\n"); -- cgit v0.10.2 From aac73f34542bc7ae4317928d2eabfeb21d247323 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 15 Nov 2012 15:56:39 +0000 Subject: of: use platform_device_add This allows platform_device_add a chance to call insert_resource on all of the resources from OF. At a minimum this fills in proc/iomem and presumably makes resource tracking and conflict detection work better. However, it has the side effect of moving all OF generated platform devices from /sys/devices to /sys/devices/platform/. It /shouldn't/ break userspace because userspace is not supposed to depend on the full path (because userspace always does what it is supposed to, right?). This may cause breakage if either: 1) any two nodes in a given device tree have overlapping & staggered regions (ie. 0x80..0xbf and 0xa0..0xdf; where one is not contained within the other). In this case one of the devices will fail to register and an exception will be needed in platform_device_add() to complain but not fail. 2) any device calls request_mem_region() on a region larger than specified in the device tree. In this case the device node may be wrong, or the driver is overreaching. In either case I'd like to know about any problems and fix them. Please test. Despite the above, I'm still fairly confident that this patch is in good shape. I'd like to put it into linux-next, but would appreciate some bench testing from others before I do; particularly on PowerPC machines. v2: Remove powerpc special-case Cc: Jason Gunthorpe Cc: Benjamin Herrenschmidt Cc: Rob Herring Cc: Greg Kroah-Hartman Signed-off-by: Grant Likely diff --git a/drivers/of/platform.c b/drivers/of/platform.c index b80891b..3c3e3ca 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -203,6 +203,7 @@ struct platform_device *of_platform_device_create_pdata( struct device *parent) { struct platform_device *dev; + int rc; if (!of_device_is_available(np)) return NULL; @@ -214,16 +215,24 @@ struct platform_device *of_platform_device_create_pdata( #if defined(CONFIG_MICROBLAZE) dev->archdata.dma_mask = 0xffffffffUL; #endif + dev->name = dev_name(&dev->dev); dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - dev->dev.bus = &platform_bus_type; dev->dev.platform_data = platform_data; + dev->dev.id = PLATFORM_DEVID_NONE; + /* device_add will assume that this device is on the same node as + * the parent. If there is no parent defined, set the node + * explicitly */ + if (!parent) + set_dev_node(&dev->dev, of_node_to_nid(np)); /* We do not fill the DMA ops for platform devices by default. * This is currently the responsibility of the platform code * to do such, possibly using a device notifier */ - if (of_device_add(dev) != 0) { + rc = platform_device_add(dev); + if (rc) { + dev_err(&dev->dev, "device registration failed\n"); platform_device_put(dev); return NULL; } -- cgit v0.10.2 From 12514aa0e6c6ca4e03b8a4da557b7d3ee0d91f5d Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 7 Feb 2013 12:20:34 +0000 Subject: devicetree: Move NS2 LEDs binding into LEDs directory leds-ns2.txt is a binding for LEDs, not GPIOs. Move the documentation in with the rest of the LEDs bindings. Cc: Andrew Lunn Cc: Simon Guinot Cc: Jason Cooper Signed-off-by: Grant Likely diff --git a/Documentation/devicetree/bindings/gpio/leds-ns2.txt b/Documentation/devicetree/bindings/gpio/leds-ns2.txt deleted file mode 100644 index aef3aca..0000000 --- a/Documentation/devicetree/bindings/gpio/leds-ns2.txt +++ /dev/null @@ -1,26 +0,0 @@ -Binding for dual-GPIO LED found on Network Space v2 (and parents). - -Required properties: -- compatible: "lacie,ns2-leds". - -Each LED is represented as a sub-node of the ns2-leds device. - -Required sub-node properties: -- cmd-gpio: Command LED GPIO. See OF device-tree GPIO specification. -- slow-gpio: Slow LED GPIO. See OF device-tree GPIO specification. - -Optional sub-node properties: -- label: Name for this LED. If omitted, the label is taken from the node name. -- linux,default-trigger: Trigger assigned to the LED. - -Example: - -ns2-leds { - compatible = "lacie,ns2-leds"; - - blue-sata { - label = "ns2:blue:sata"; - slow-gpio = <&gpio0 29 0>; - cmd-gpio = <&gpio0 30 0>; - }; -}; diff --git a/Documentation/devicetree/bindings/leds/leds-ns2.txt b/Documentation/devicetree/bindings/leds/leds-ns2.txt new file mode 100644 index 0000000..aef3aca --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-ns2.txt @@ -0,0 +1,26 @@ +Binding for dual-GPIO LED found on Network Space v2 (and parents). + +Required properties: +- compatible: "lacie,ns2-leds". + +Each LED is represented as a sub-node of the ns2-leds device. + +Required sub-node properties: +- cmd-gpio: Command LED GPIO. See OF device-tree GPIO specification. +- slow-gpio: Slow LED GPIO. See OF device-tree GPIO specification. + +Optional sub-node properties: +- label: Name for this LED. If omitted, the label is taken from the node name. +- linux,default-trigger: Trigger assigned to the LED. + +Example: + +ns2-leds { + compatible = "lacie,ns2-leds"; + + blue-sata { + label = "ns2:blue:sata"; + slow-gpio = <&gpio0 29 0>; + cmd-gpio = <&gpio0 30 0>; + }; +}; -- cgit v0.10.2 From 1d0b1c74ed22d2614ae9206febf956f0b22c81a5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 10 Jan 2013 17:41:32 -0800 Subject: input: Extend matrix-keypad device tree binding Some matrix keypad drivers can support different numbers of rows and columns. Add a generic binding for these. Implementation note: In order to implement this binding in the kernel, we will need to modify matrix_keypad_() to look up the number of rows and cols in the keymap. Perhaps this could be done by passing 0 for these parameters? Many of the parameters can already be set to NULL. Ick. Signed-off-by: Simon Glass Reviewed-by: Stephen Warren Signed-off-by: Grant Likely diff --git a/Documentation/devicetree/bindings/input/lpc32xx-key.txt b/Documentation/devicetree/bindings/input/lpc32xx-key.txt index 31afd50..bcf62f8 100644 --- a/Documentation/devicetree/bindings/input/lpc32xx-key.txt +++ b/Documentation/devicetree/bindings/input/lpc32xx-key.txt @@ -1,19 +1,22 @@ NXP LPC32xx Key Scan Interface +This binding is based on the matrix-keymap binding with the following +changes: + Required Properties: - compatible: Should be "nxp,lpc3220-key" - reg: Physical base address of the controller and length of memory mapped region. - interrupts: The interrupt number to the cpu. -- keypad,num-rows: Number of rows and columns, e.g. 1: 1x1, 6: 6x6 -- keypad,num-columns: Must be equal to keypad,num-rows since LPC32xx only - supports square matrices - nxp,debounce-delay-ms: Debounce delay in ms - nxp,scan-delay-ms: Repeated scan period in ms - linux,keymap: the key-code to be reported when the key is pressed and released, see also Documentation/devicetree/bindings/input/matrix-keymap.txt +Note: keypad,num-rows and keypad,num-columns are required, and must be equal +since LPC32xx only supports square matrices + Example: key@40050000 { diff --git a/Documentation/devicetree/bindings/input/matrix-keymap.txt b/Documentation/devicetree/bindings/input/matrix-keymap.txt index 3cd8b98..c54919f 100644 --- a/Documentation/devicetree/bindings/input/matrix-keymap.txt +++ b/Documentation/devicetree/bindings/input/matrix-keymap.txt @@ -9,6 +9,12 @@ Required properties: row << 24 | column << 16 | key-code Optional properties: +Properties for the number of rows and columns are optional because some +drivers will use fixed values for these. +- keypad,num-rows: Number of row lines connected to the keypad controller. +- keypad,num-columns: Number of column lines connected to the keypad + controller. + Some users of this binding might choose to specify secondary keymaps for cases where there is a modifier key such as a Fn key. Proposed names for said properties are "linux,fn-keymap" or with another descriptive @@ -17,3 +23,5 @@ word for the modifier other from "Fn". Example: linux,keymap = < 0x00030012 0x0102003a >; + keypad,num-rows = <2>; + keypad,num-columns = <8>; diff --git a/Documentation/devicetree/bindings/input/omap-keypad.txt b/Documentation/devicetree/bindings/input/omap-keypad.txt index f2fa5e1..34ed1c6 100644 --- a/Documentation/devicetree/bindings/input/omap-keypad.txt +++ b/Documentation/devicetree/bindings/input/omap-keypad.txt @@ -6,19 +6,16 @@ A key can be placed at each intersection of a unique row and a unique column. The keypad controller can sense a key-press and key-release and report the event using a interrupt to the cpu. +This binding is based on the matrix-keymap binding with the following +changes: + +keypad,num-rows and keypad,num-columns are required. + Required SoC Specific Properties: - compatible: should be one of the following - "ti,omap4-keypad": For controllers compatible with omap4 keypad controller. -Required Board Specific Properties, in addition to those specified by -the shared matrix-keyboard bindings: -- keypad,num-rows: Number of row lines connected to the keypad - controller. - -- keypad,num-columns: Number of column lines connected to the - keypad controller. - Optional Properties specific to linux: - linux,keypad-no-autorepeat: do no enable autorepeat feature. diff --git a/Documentation/devicetree/bindings/input/tca8418_keypad.txt b/Documentation/devicetree/bindings/input/tca8418_keypad.txt index 2a1538f..2551850 100644 --- a/Documentation/devicetree/bindings/input/tca8418_keypad.txt +++ b/Documentation/devicetree/bindings/input/tca8418_keypad.txt @@ -1,8 +1,10 @@ +This binding is based on the matrix-keymap binding with the following +changes: + +keypad,num-rows and keypad,num-columns are required. Required properties: - compatible: "ti,tca8418" - reg: the I2C address - interrupts: IRQ line number, should trigger on falling edge -- keypad,num-rows: The number of rows -- keypad,num-columns: The number of columns - linux,keymap: Keys definitions, see keypad-matrix. -- cgit v0.10.2 From 22435f38337ef6a8abb33574604e77c335b75d14 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 5 Feb 2013 12:06:28 -0700 Subject: kbuild: create a rule to run the pre-processor on *.dts files Create cmd_dtc_cpp to run the C pre-processor on *.dts file before passing them to dtc for final compilation. This allows the use of #define and #include within the .dts file. Acked-by: Simon Glass Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Michal Marek Acked-by: Srinivas Kandagatla Signed-off-by: Stephen Warren Signed-off-by: Grant Likely diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 14c3f4f..5198b74 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -1186,6 +1186,29 @@ When kbuild executes, the following steps are followed (roughly): clean-files += *.dtb DTC_FLAGS ?= -p 1024 + dtc_cpp + This is just like dtc as describe above, except that the C pre- + processor is invoked upon the .dtsp file before compiling the result + with dtc. + + In order for build dependencies to work, all files compiled using + dtc_cpp must use the C pre-processor's #include functionality and not + dtc's /include/ functionality. + + Using the C pre-processor allows use of #define to create named + constants. In turn, the #defines will typically appear in a header + file, which may be shared with regular C code. Since the dtc language + represents a data structure rather than code in C syntax, similar + restrictions are placed on a header file included by a device tree + file as for a header file included by an assembly language file. + In particular, the C pre-processor is passed -x assembler-with-cpp, + which sets macro __ASSEMBLY__. __DTS__ is also set. These allow header + files to restrict their content to that compatible with device tree + source. + + A central rule exists to create $(obj)/%.dtb from $(src)/%.dtsp; + architecture Makefiles do no need to explicitly write out that rule. + --- 6.8 Custom kbuild commands When kbuild is executing with KBUILD_VERBOSE=0, then only a shorthand diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index bdf42fd..7910229 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -269,6 +269,16 @@ cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile $(obj)/%.dtb: $(src)/%.dts FORCE $(call if_changed_dep,dtc) +dtc-tmp = $(subst $(comma),_,$(dot-target).dts) + +quiet_cmd_dtc_cpp = DTC+CPP $@ +cmd_dtc_cpp = $(CPP) $(cpp_flags) -x assembler-with-cpp -undef -D__DTS__ \ + -o $(dtc-tmp) $< ; \ + $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) $(dtc-tmp) + +$(obj)/%.dtb: $(src)/%.dtsp FORCE + $(call if_changed_dep,dtc_cpp) + # Bzip2 # --------------------------------------------------------------------------- -- cgit v0.10.2 From 09495dda6a62c74b13412a63528093910ef80edd Mon Sep 17 00:00:00 2001 From: Ajay Kumar Date: Thu, 3 Jan 2013 08:03:34 -0500 Subject: of/exynos_g2d: Add Bindings for exynos G2D driver Add documentation for the DT bindings in exynos G2D driver. Signed-off-by: Ajay Kumar Signed-off-by: Grant Likely diff --git a/Documentation/devicetree/bindings/drm/exynos/g2d.txt b/Documentation/devicetree/bindings/drm/exynos/g2d.txt new file mode 100644 index 0000000..1eb124d --- /dev/null +++ b/Documentation/devicetree/bindings/drm/exynos/g2d.txt @@ -0,0 +1,22 @@ +Samsung 2D Graphic Accelerator using DRM frame work + +Samsung FIMG2D is a graphics 2D accelerator which supports Bit Block Transfer. +We set the drawing-context registers for configuring rendering parameters and +then start rendering. +This driver is for SOCs which contain G2D IPs with version 4.1. + +Required properties: + -compatible: + should be "samsung,exynos-g2d-41". + -reg: + physical base address of the controller and length + of memory mapped region. + -interrupts: + interrupt combiner values. + +Example: + g2d { + compatible = "samsung,exynos-g2d-41"; + reg = <0x10850000 0x1000>; + interrupts = <0 91 0>; + }; -- cgit v0.10.2 From d6d3c4e656513dcea61ce900f0ecb9ca820ee7cd Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 6 Feb 2013 15:30:56 -0500 Subject: OF: convert devtree lock from rw_lock to raw spinlock With the locking cleanup in place (from "OF: Fixup resursive locking code paths"), we can now do the conversion from the rw_lock to a raw spinlock as required for preempt-rt. The previous cleanup and this conversion were originally separate since they predated when mainline got raw spinlock (in commit c2f21ce2e31286a "locking: Implement new raw_spinlock"). So, at that point in time, the cleanup was considered plausible for mainline, but not this conversion. In any case, we've kept them separate as it makes for easier review and better bisection. Signed-off-by: Thomas Gleixner [PG: taken from preempt-rt, update subject & add a commit log] Signed-off-by: Paul Gortmaker Signed-off-by: Rob Herring diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index 1303021..9f20566 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c @@ -64,7 +64,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len err = -ENODEV; mutex_lock(&of_set_property_mutex); - write_lock(&devtree_lock); + raw_spin_lock(&devtree_lock); prevp = &dp->properties; while (*prevp) { struct property *prop = *prevp; @@ -91,7 +91,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len } prevp = &(*prevp)->next; } - write_unlock(&devtree_lock); + raw_spin_unlock(&devtree_lock); mutex_unlock(&of_set_property_mutex); /* XXX Upate procfs if necessary... */ diff --git a/drivers/of/base.c b/drivers/of/base.c index 16ee7a0..f86be55 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex); /* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. */ -DEFINE_RWLOCK(devtree_lock); +DEFINE_RAW_SPINLOCK(devtree_lock); int of_n_addr_cells(struct device_node *np) { @@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np, int *lenp) { struct property *pp; + unsigned long flags; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); pp = __of_find_property(np, name, lenp); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return pp; } @@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev) { struct device_node *np; - read_lock(&devtree_lock); + raw_spin_lock(&devtree_lock); np = prev ? prev->allnext : of_allnodes; for (; np != NULL; np = np->allnext) if (of_node_get(np)) break; of_node_put(prev); - read_unlock(&devtree_lock); + raw_spin_unlock(&devtree_lock); return np; } EXPORT_SYMBOL(of_find_all_nodes); @@ -274,11 +275,12 @@ static int __of_device_is_compatible(const struct device_node *device, int of_device_is_compatible(const struct device_node *device, const char *compat) { + unsigned long flags; int res; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); res = __of_device_is_compatible(device, compat); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return res; } EXPORT_SYMBOL(of_device_is_compatible); @@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available); struct device_node *of_get_parent(const struct device_node *node) { struct device_node *np; + unsigned long flags; if (!node) return NULL; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); np = of_node_get(node->parent); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_get_parent); @@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent); struct device_node *of_get_next_parent(struct device_node *node) { struct device_node *parent; + unsigned long flags; if (!node) return NULL; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); parent = of_node_get(node->parent); of_node_put(node); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return parent; } @@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev) { struct device_node *next; + unsigned long flags; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); next = prev ? prev->sibling : node->child; for (; next; next = next->sibling) if (of_node_get(next)) break; of_node_put(prev); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return next; } EXPORT_SYMBOL(of_get_next_child); @@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node, { struct device_node *next; - read_lock(&devtree_lock); + raw_spin_lock(&devtree_lock); next = prev ? prev->sibling : node->child; for (; next; next = next->sibling) { if (!of_device_is_available(next)) @@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node, break; } of_node_put(prev); - read_unlock(&devtree_lock); + raw_spin_unlock(&devtree_lock); return next; } EXPORT_SYMBOL(of_get_next_available_child); @@ -460,14 +465,15 @@ EXPORT_SYMBOL(of_get_child_by_name); struct device_node *of_find_node_by_path(const char *path) { struct device_node *np = of_allnodes; + unsigned long flags; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); for (; np; np = np->allnext) { if (np->full_name && (of_node_cmp(np->full_name, path) == 0) && of_node_get(np)) break; } - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_find_node_by_path); @@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from, const char *name) { struct device_node *np; + unsigned long flags; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) if (np->name && (of_node_cmp(np->name, name) == 0) && of_node_get(np)) break; of_node_put(from); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_find_node_by_name); @@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from, const char *type) { struct device_node *np; + unsigned long flags; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) if (np->type && (of_node_cmp(np->type, type) == 0) && of_node_get(np)) break; of_node_put(from); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_find_node_by_type); @@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compatible) { struct device_node *np; + unsigned long flags; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { if (type @@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, break; } of_node_put(from); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_find_compatible_node); @@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from, { struct device_node *np; struct property *pp; + unsigned long flags; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { for (pp = np->properties; pp; pp = pp->next) { @@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, } out: of_node_put(from); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_find_node_with_property); @@ -635,10 +645,11 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) { const struct of_device_id *match; + unsigned long flags; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); match = __of_match_node(matches, node); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return match; } EXPORT_SYMBOL(of_match_node); @@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, { struct device_node *np; const struct of_device_id *m; + unsigned long flags; if (match) *match = NULL; - read_lock(&devtree_lock); + raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { m = __of_match_node(matches, np); @@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, } } of_node_put(from); - read_unlock(&devtree_lock); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_find_matching_node_and_match); @@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle) { struct device_node *np; - read_lock(&devtree_lock); + raw_spin_lock(&devtree_lock); for (np = of_allnodes; np; np = np->allnext) if (np->phandle == handle) break; of_node_get(np); - read_unlock(&devtree_lock); + raw_spin_unlock(&devtree_lock); return np; } EXPORT_SYMBOL(of_find_node_by_phandle); @@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop) return rc; prop->next = NULL; - write_lock_irqsave(&devtree_lock, flags); + raw_spin_lock_irqsave(&devtree_lock, flags); next = &np->properties; while (*next) { if (strcmp(prop->name, (*next)->name) == 0) { /* duplicate ! don't insert it */ - write_unlock_irqrestore(&devtree_lock, flags); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return -1; } next = &(*next)->next; } *next = prop; - write_unlock_irqrestore(&devtree_lock, flags); + raw_spin_unlock_irqrestore(&devtree_lock, flags); #ifdef CONFIG_PROC_DEVICETREE /* try to add to proc as well if it was initialized */ @@ -1238,7 +1250,7 @@ int of_remove_property(struct device_node *np, struct property *prop) if (rc) return rc; - write_lock_irqsave(&devtree_lock, flags); + raw_spin_lock_irqsave(&devtree_lock, flags); next = &np->properties; while (*next) { if (*next == prop) { @@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop) } next = &(*next)->next; } - write_unlock_irqrestore(&devtree_lock, flags); + raw_spin_unlock_irqrestore(&devtree_lock, flags); if (!found) return -ENODEV; @@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop) if (!oldprop) return of_add_property(np, newprop); - write_lock_irqsave(&devtree_lock, flags); + raw_spin_lock_irqsave(&devtree_lock, flags); next = &np->properties; while (*next) { if (*next == oldprop) { @@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop) } next = &(*next)->next; } - write_unlock_irqrestore(&devtree_lock, flags); + raw_spin_unlock_irqrestore(&devtree_lock, flags); if (!found) return -ENODEV; @@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np) if (rc) return rc; - write_lock_irqsave(&devtree_lock, flags); + raw_spin_lock_irqsave(&devtree_lock, flags); np->sibling = np->parent->child; np->allnext = of_allnodes; np->parent->child = np; of_allnodes = np; - write_unlock_irqrestore(&devtree_lock, flags); + raw_spin_unlock_irqrestore(&devtree_lock, flags); of_add_proc_dt_entry(np); return 0; @@ -1426,17 +1438,17 @@ int of_detach_node(struct device_node *np) if (rc) return rc; - write_lock_irqsave(&devtree_lock, flags); + raw_spin_lock_irqsave(&devtree_lock, flags); if (of_node_check_flag(np, OF_DETACHED)) { /* someone already detached it */ - write_unlock_irqrestore(&devtree_lock, flags); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return rc; } parent = np->parent; if (!parent) { - write_unlock_irqrestore(&devtree_lock, flags); + raw_spin_unlock_irqrestore(&devtree_lock, flags); return rc; } @@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np) } of_node_set_flag(np, OF_DETACHED); - write_unlock_irqrestore(&devtree_lock, flags); + raw_spin_unlock_irqrestore(&devtree_lock, flags); of_remove_proc_dt_entry(np); return rc; diff --git a/include/linux/of.h b/include/linux/of.h index 5ebcc5c..bb35c42 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -92,7 +92,7 @@ static inline void of_node_put(struct device_node *node) { } extern struct device_node *of_allnodes; extern struct device_node *of_chosen; extern struct device_node *of_aliases; -extern rwlock_t devtree_lock; +extern raw_spinlock_t devtree_lock; static inline bool of_have_populated_dt(void) { -- cgit v0.10.2 From 1421954bf9b967d819db23c911f950a2ccd60eff Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 7 Feb 2013 17:14:35 +0530 Subject: documentation/devicetree: Fix a typo in exynos-dw-mshc.txt Fixed a typo in referenced file name. Cc: Thomas Abraham Cc: Grant Likely Signed-off-by: Sachin Kamat Signed-off-by: Rob Herring diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt index 7927689..4e35e55 100644 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -4,7 +4,7 @@ The Synopsis designware mobile storage host controller is used to interface a SoC with storage medium such as eMMC or SD/MMC cards. This file documents differences between the core Synopsis dw mshc controller properties described -by synposis-dw-mshc.txt and the properties used by the Samsung Exynos specific +by synopsis-dw-mshc.txt and the properties used by the Samsung Exynos specific extensions to the Synopsis Designware Mobile Storage Host Controller. Required Properties: -- cgit v0.10.2 From c31a0c052205e3ec24efc3fe18ef70c3e913f2d4 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 11 Feb 2013 14:15:32 -0700 Subject: of: fix recursive locking in of_get_next_available_child() of_get_next_available_child() acquires devtree_lock, then calls of_device_is_available() which calls of_get_property() which calls of_find_property() which tries to re-acquire devtree_lock, thus causing deadlock. To avoid this, create a new __of_device_is_available() which calls __of_get_property() instead, which calls __of_find_property(), which does not take the lock,. Update of_get_next_available_child() to call the new __of_device_is_available() since it already owns the lock. Signed-off-by: Stephen Warren Signed-off-by: Grant Likely diff --git a/drivers/of/base.c b/drivers/of/base.c index e8d65af..f7a87ce 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -290,19 +290,19 @@ int of_machine_is_compatible(const char *compat) EXPORT_SYMBOL(of_machine_is_compatible); /** - * of_device_is_available - check if a device is available for use + * __of_device_is_available - check if a device is available for use * - * @device: Node to check for availability + * @device: Node to check for availability, with locks already held * * Returns 1 if the status property is absent or set to "okay" or "ok", * 0 otherwise */ -int of_device_is_available(const struct device_node *device) +static int __of_device_is_available(const struct device_node *device) { const char *status; int statlen; - status = of_get_property(device, "status", &statlen); + status = __of_get_property(device, "status", &statlen); if (status == NULL) return 1; @@ -313,6 +313,26 @@ int of_device_is_available(const struct device_node *device) return 0; } + +/** + * of_device_is_available - check if a device is available for use + * + * @device: Node to check for availability + * + * Returns 1 if the status property is absent or set to "okay" or "ok", + * 0 otherwise + */ +int of_device_is_available(const struct device_node *device) +{ + unsigned long flags; + int res; + + raw_spin_lock_irqsave(&devtree_lock, flags); + res = __of_device_is_available(device); + raw_spin_unlock_irqrestore(&devtree_lock, flags); + return res; + +} EXPORT_SYMBOL(of_device_is_available); /** @@ -404,7 +424,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node, raw_spin_lock(&devtree_lock); next = prev ? prev->sibling : node->child; for (; next; next = next->sibling) { - if (!of_device_is_available(next)) + if (!__of_device_is_available(next)) continue; if (of_node_get(next)) break; -- cgit v0.10.2 From f7f951c29835622d6096530393a8322131059917 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 12 Feb 2013 17:41:22 +0000 Subject: of/selftest: Fix GPIOs selftest to cover the 7th case The of_gpio_named_count() self test doesn't hit the out-of-range condition even though it is coded. Fix the bug by increasing the for loop range by one. Reported-by: Andreas Larsson Cc: Rob Herring Signed-off-by: Grant Likely diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index f24ffd7..9f62eb5 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -35,7 +35,7 @@ static void __init of_selftest_parse_phandle_with_args(void) return; } - for (i = 0; i < 7; i++) { + for (i = 0; i < 8; i++) { bool passed = true; rc = of_parse_phandle_with_args(np, "phandle-list", "#phandle-cells", i, &args); -- cgit v0.10.2 From cabb7d5b7896a4d307ea6ad6d3bd045810544151 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 12 Feb 2013 21:19:37 +0000 Subject: of/selftest: Use selftest() macro throughout Some of the selftests are open-coded. Others use the selftest() macro defined in drivers/of/selftest.c. The macro makes for cleaner selftest code, so refactor the of_parse_phandle_with_args() tests to use it. Cc: Rob Herring Signed-off-by: Grant Likely diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 9f62eb5..01b4174 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -2,7 +2,7 @@ * Self tests for device tree subsystem */ -#define pr_fmt(fmt) "### %s(): " fmt, __func__ +#define pr_fmt(fmt) "### dt-test ### " fmt #include #include @@ -16,19 +16,20 @@ static bool selftest_passed = true; #define selftest(result, fmt, ...) { \ - selftest_passed &= (result); \ - if (!(result)) \ + if (!(result)) { \ pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + selftest_passed = false; \ + } else { \ + pr_info("pass %s:%i\n", __FILE__, __LINE__); \ + } \ } static void __init of_selftest_parse_phandle_with_args(void) { struct device_node *np; struct of_phandle_args args; - int rc, i; - bool passed_all = true; + int i, rc; - pr_info("start\n"); np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); if (!np) { pr_err("missing testcase data\n"); @@ -79,45 +80,35 @@ static void __init of_selftest_parse_phandle_with_args(void) passed &= (args.args[0] == (i + 1)); break; case 7: - passed &= (rc == -EINVAL); + passed &= (rc == -ENOENT); break; default: passed = false; } - if (!passed) { - int j; - pr_err("index %i - data error on node %s rc=%i regs=[", - i, args.np->full_name, rc); - for (j = 0; j < args.args_count; j++) - printk(" %i", args.args[j]); - printk(" ]\n"); - - passed_all = false; - } + selftest(passed, "index %i - data error on node %s rc=%i\n", + i, args.np->full_name, rc); } /* Check for missing list property */ rc = of_parse_phandle_with_args(np, "phandle-list-missing", "#phandle-cells", 0, &args); - passed_all &= (rc == -EINVAL); + selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); /* Check for missing cells property */ rc = of_parse_phandle_with_args(np, "phandle-list", "#phandle-cells-missing", 0, &args); - passed_all &= (rc == -EINVAL); + selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for bad phandle in list */ rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", "#phandle-cells", 0, &args); - passed_all &= (rc == -EINVAL); + selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for incorrectly formed argument list */ rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", "#phandle-cells", 1, &args); - passed_all &= (rc == -EINVAL); - - pr_info("end - %s\n", passed_all ? "PASS" : "FAIL"); + selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); } static void __init of_selftest_property_match_string(void) -- cgit v0.10.2 From 23ce04c0734e33b1042273b0ed11a8e4f7f988ca Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 12 Feb 2013 21:21:49 +0000 Subject: of/base: Clean up exit paths for of_parse_phandle_with_args() Some of the exit paths were not correctly releasing the node. Fix it by creating an 'err' label for collecting the error paths and releasing the node. Cc: Rob Herring Signed-off-by: Grant Likely diff --git a/drivers/of/base.c b/drivers/of/base.c index f7a87ce..c5572cb 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1096,7 +1096,7 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na struct of_phandle_args *out_args) { const __be32 *list, *list_end; - int size, cur_index = 0; + int rc = 0, size, cur_index = 0; uint32_t count = 0; struct device_node *node = NULL; phandle phandle; @@ -1109,6 +1109,7 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na /* Loop over the phandles until all the requested entry is found */ while (list < list_end) { + rc = -EINVAL; count = 0; /* @@ -1125,13 +1126,13 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na if (!node) { pr_err("%s: could not find phandle\n", np->full_name); - break; + goto err; } if (of_property_read_u32(node, cells_name, &count)) { pr_err("%s: could not get %s for %s\n", np->full_name, cells_name, node->full_name); - break; + goto err; } /* @@ -1141,7 +1142,7 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na if (list + count > list_end) { pr_err("%s: arguments longer than property\n", np->full_name); - break; + goto err; } } @@ -1151,9 +1152,10 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na * index matches, then fill the out_args structure and return, * or return -ENOENT for an empty entry. */ + rc = -ENOENT; if (cur_index == index) { if (!phandle) - return -ENOENT; + goto err; if (out_args) { int i; @@ -1164,6 +1166,10 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na for (i = 0; i < count; i++) out_args->args[i] = be32_to_cpup(list++); } + + /* Found it! return success */ + if (node) + of_node_put(node); return 0; } @@ -1173,10 +1179,16 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na cur_index++; } - /* Loop exited without finding a valid entry; return an error */ + /* + * Unlock node before returning result; will be one of: + * -ENOENT : index is for empty phandle + * -EINVAL : parsing error on data + */ + rc = -ENOENT; + err: if (node) of_node_put(node); - return -EINVAL; + return rc; } EXPORT_SYMBOL(of_parse_phandle_with_args); -- cgit v0.10.2 From bd69f73f2c81eed9a398708b8c4bb3409ba1b0f9 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 10 Feb 2013 22:57:21 +0000 Subject: of: Create function for counting number of phandles in a property This patch creates of_count_phandle_with_args(), a new function for counting the number of phandle+argument tuples in a given property. This is better than the existing method of parsing each phandle individually until parsing fails which is a horribly slow way to do the count. Tested on ARM using the selftest code. v3: - Rebased on top of selftest code cleanup patch v2: - fix bug where of_parse_phandle_with_args() could behave like _count_. - made of_gpio_named_count() into a static inline regardless of CONFIG_OF_GPIO Tested-by: Andreas Larsson Signed-off-by: Grant Likely Cc: Linus Walleij Cc: Rob Herring diff --git a/drivers/of/base.c b/drivers/of/base.c index c5572cb..321d3ef 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1091,9 +1091,10 @@ EXPORT_SYMBOL(of_parse_phandle); * To get a device_node of the `node2' node you may call this: * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); */ -int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, - const char *cells_name, int index, - struct of_phandle_args *out_args) +static int __of_parse_phandle_with_args(const struct device_node *np, + const char *list_name, + const char *cells_name, int index, + struct of_phandle_args *out_args) { const __be32 *list, *list_end; int rc = 0, size, cur_index = 0; @@ -1183,15 +1184,47 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na * Unlock node before returning result; will be one of: * -ENOENT : index is for empty phandle * -EINVAL : parsing error on data + * [1..n] : Number of phandle (count mode; when index = -1) */ - rc = -ENOENT; + rc = index < 0 ? cur_index : -ENOENT; err: if (node) of_node_put(node); return rc; } + +int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, + const char *cells_name, int index, + struct of_phandle_args *out_args) +{ + if (index < 0) + return -EINVAL; + return __of_parse_phandle_with_args(np, list_name, cells_name, index, out_args); +} EXPORT_SYMBOL(of_parse_phandle_with_args); +/** + * of_count_phandle_with_args() - Find the number of phandles references in a property + * @np: pointer to a device tree node containing a list + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * + * Returns the number of phandle + argument tuples within a property. It + * is a typical pattern to encode a list of phandle and variable + * arguments into a single property. The number of arguments is encoded + * by a property in the phandle-target node. For example, a gpios + * property would contain a list of GPIO specifies consisting of a + * phandle and 1 or more arguments. The number of arguments are + * determined by the #gpio-cells property in the node pointed to by the + * phandle. + */ +int of_count_phandle_with_args(const struct device_node *np, const char *list_name, + const char *cells_name) +{ + return __of_parse_phandle_with_args(np, list_name, cells_name, -1, NULL); +} +EXPORT_SYMBOL(of_count_phandle_with_args); + #if defined(CONFIG_OF_DYNAMIC) static int of_property_notify(int action, struct device_node *np, struct property *prop) diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 01b4174..0eb5c38 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -36,6 +36,9 @@ static void __init of_selftest_parse_phandle_with_args(void) return; } + rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells"); + selftest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc); + for (i = 0; i < 8; i++) { bool passed = true; rc = of_parse_phandle_with_args(np, "phandle-list", @@ -94,21 +97,33 @@ static void __init of_selftest_parse_phandle_with_args(void) rc = of_parse_phandle_with_args(np, "phandle-list-missing", "#phandle-cells", 0, &args); selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); + rc = of_count_phandle_with_args(np, "phandle-list-missing", + "#phandle-cells"); + selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); /* Check for missing cells property */ rc = of_parse_phandle_with_args(np, "phandle-list", "#phandle-cells-missing", 0, &args); selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + rc = of_count_phandle_with_args(np, "phandle-list", + "#phandle-cells-missing"); + selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for bad phandle in list */ rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", "#phandle-cells", 0, &args); selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + rc = of_count_phandle_with_args(np, "phandle-list-bad-phandle", + "#phandle-cells"); + selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for incorrectly formed argument list */ rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", "#phandle-cells", 1, &args); selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + rc = of_count_phandle_with_args(np, "phandle-list-bad-args", + "#phandle-cells"); + selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); } static void __init of_selftest_property_match_string(void) diff --git a/include/linux/of.h b/include/linux/of.h index b9e1b91..a0f1292 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -277,6 +277,8 @@ extern struct device_node *of_parse_phandle(const struct device_node *np, extern int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, int index, struct of_phandle_args *out_args); +extern int of_count_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name); extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern int of_alias_get_id(struct device_node *np, const char *stem); @@ -467,6 +469,13 @@ static inline int of_parse_phandle_with_args(struct device_node *np, return -ENOSYS; } +static inline int of_count_phandle_with_args(struct device_node *np, + const char *list_name, + const char *cells_name) +{ + return -ENOSYS; +} + static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOSYS; -- cgit v0.10.2 From e80beb27d2f81a1c3c8887e0e0a82d77bb392d28 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 12 Feb 2013 17:48:37 +0000 Subject: gpio: Make of_count_named_gpios() use new of_count_phandle_with_args() This patch replaces the horribly coded of_count_named_gpios() with a call to of_count_phandle_with_args() which is far more efficient. This also changes the return value of of_gpio_count() & of_gpio_named_count() from 'unsigned int' to 'int' so that it can return an error code. All the users of that function are fixed up to correctly handle a negative return value. v2: Split GPIO portion into a separate patch Tested-by: Andreas Larsson Signed-off-by: Grant Likely Cc: Linus Walleij Cc: Rob Herring diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index d542a14..dd8a212 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -89,41 +89,6 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, EXPORT_SYMBOL(of_get_named_gpio_flags); /** - * of_gpio_named_count - Count GPIOs for a device - * @np: device node to count GPIOs for - * @propname: property name containing gpio specifier(s) - * - * The function returns the count of GPIOs specified for a node. - * - * Note that the empty GPIO specifiers counts too. For example, - * - * gpios = <0 - * &pio1 1 2 - * 0 - * &pio2 3 4>; - * - * defines four GPIOs (so this function will return 4), two of which - * are not specified. - */ -unsigned int of_gpio_named_count(struct device_node *np, const char* propname) -{ - unsigned int cnt = 0; - - do { - int ret; - - ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", - cnt, NULL); - /* A hole in the gpios = <> counts anyway. */ - if (ret < 0 && ret != -EEXIST) - break; - } while (++cnt); - - return cnt; -} -EXPORT_SYMBOL(of_gpio_named_count); - -/** * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags * @gc: pointer to the gpio_chip structure * @np: device node of the GPIO chip diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 4e04c12..3978194 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -422,7 +422,7 @@ static int gpio_fan_get_of_pdata(struct device *dev, /* Fill GPIO pin array */ pdata->num_ctrl = of_gpio_count(node); - if (!pdata->num_ctrl) { + if (pdata->num_ctrl <= 0) { dev_err(dev, "gpios DT property empty / missing"); return -ENODEV; } @@ -477,7 +477,7 @@ static int gpio_fan_get_of_pdata(struct device *dev, pdata->speed = speed; /* Alarm GPIO if one exists */ - if (of_gpio_named_count(node, "alarm-gpios")) { + if (of_gpio_named_count(node, "alarm-gpios") > 0) { struct gpio_fan_alarm *alarm; int val; enum of_gpio_flags flags; diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index f4ff0dd..71d7719 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -403,7 +403,7 @@ matrix_keypad_parse_dt(struct device *dev) struct matrix_keypad_platform_data *pdata; struct device_node *np = dev->of_node; unsigned int *gpios; - int i; + int i, nrow, ncol; if (!np) { dev_err(dev, "device lacks DT data\n"); @@ -416,9 +416,9 @@ matrix_keypad_parse_dt(struct device *dev) return ERR_PTR(-ENOMEM); } - pdata->num_row_gpios = of_gpio_named_count(np, "row-gpios"); - pdata->num_col_gpios = of_gpio_named_count(np, "col-gpios"); - if (!pdata->num_row_gpios || !pdata->num_col_gpios) { + pdata->num_row_gpios = nrow = of_gpio_named_count(np, "row-gpios"); + pdata->num_col_gpios = ncol = of_gpio_named_count(np, "col-gpios"); + if (nrow <= 0 || ncol <= 0) { dev_err(dev, "number of keypad rows/columns not specified\n"); return ERR_PTR(-EINVAL); } diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c index 0c9accb..e91d7d7 100644 --- a/drivers/net/phy/mdio-mux-gpio.c +++ b/drivers/net/phy/mdio-mux-gpio.c @@ -53,7 +53,7 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev) { enum of_gpio_flags f; struct mdio_mux_gpio_state *s; - unsigned int num_gpios; + int num_gpios; unsigned int n; int r; @@ -61,7 +61,7 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev) return -ENODEV; num_gpios = of_gpio_count(pdev->dev.of_node); - if (num_gpios == 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS) + if (num_gpios <= 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS) return -ENODEV; s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 1a7f6359..086a9ee 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -947,12 +947,12 @@ static int of_fsl_spi_get_chipselects(struct device *dev) struct device_node *np = dev->of_node; struct fsl_spi_platform_data *pdata = dev->platform_data; struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); - unsigned int ngpios; + int ngpios; int i = 0; int ret; ngpios = of_gpio_count(np); - if (!ngpios) { + if (ngpios <= 0) { /* * SPI w/o chip-select line. One SPI device is still permitted * though. diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index 432e66e..cb2e284 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -54,7 +54,7 @@ struct tiny_spi { unsigned int txc, rxc; const u8 *txp; u8 *rxp; - unsigned int gpio_cs_count; + int gpio_cs_count; int *gpio_cs; }; @@ -74,7 +74,7 @@ static void tiny_spi_chipselect(struct spi_device *spi, int is_active) { struct tiny_spi *hw = tiny_spi_to_hw(spi); - if (hw->gpio_cs_count) { + if (hw->gpio_cs_count > 0) { gpio_set_value(hw->gpio_cs[spi->chip_select], (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); } @@ -254,7 +254,7 @@ static int tiny_spi_of_probe(struct platform_device *pdev) if (!np) return 0; hw->gpio_cs_count = of_gpio_count(np); - if (hw->gpio_cs_count) { + if (hw->gpio_cs_count > 0) { hw->gpio_cs = devm_kzalloc(&pdev->dev, hw->gpio_cs_count * sizeof(unsigned int), GFP_KERNEL); @@ -352,7 +352,7 @@ static int tiny_spi_probe(struct platform_device *pdev) goto exit_gpio; gpio_direction_output(hw->gpio_cs[i], 1); } - hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count); + hw->bitbang.master->num_chipselect = max(1, hw->gpio_cs_count); /* register our spi controller */ err = spi_bitbang_start(&hw->bitbang); diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 7a85f22..af3e6e7 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -419,7 +419,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op) * This includes both "null" gpio's and real ones. */ num_gpios = of_gpio_count(np); - if (num_gpios) { + if (num_gpios > 0) { int i; hw->gpios = kzalloc(sizeof(int) * num_gpios, GFP_KERNEL); @@ -471,7 +471,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op) SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST; /* this many pins in all GPIO controllers */ - bbp->master->num_chipselect = num_gpios; + bbp->master->num_chipselect = num_gpios > 0 ? num_gpios : 0; /* Get the clock for the OPB */ opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb"); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 19ee901..21c4748 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1059,15 +1059,14 @@ EXPORT_SYMBOL_GPL(spi_alloc_master); #ifdef CONFIG_OF static int of_spi_register_master(struct spi_master *master) { - u16 nb; - int i, *cs; + int nb, i, *cs; struct device_node *np = master->dev.of_node; if (!np) return 0; nb = of_gpio_named_count(np, "cs-gpios"); - master->num_chipselect = max(nb, master->num_chipselect); + master->num_chipselect = max(nb, (int)master->num_chipselect); if (nb < 1) return 0; diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index c454f57..a83dc6f 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -50,9 +50,6 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) extern int of_get_named_gpio_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags); -extern unsigned int of_gpio_named_count(struct device_node *np, - const char* propname); - extern int of_mm_gpiochip_add(struct device_node *np, struct of_mm_gpio_chip *mm_gc); @@ -71,12 +68,6 @@ static inline int of_get_named_gpio_flags(struct device_node *np, return -ENOSYS; } -static inline unsigned int of_gpio_named_count(struct device_node *np, - const char* propname) -{ - return 0; -} - static inline int of_gpio_simple_xlate(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags) @@ -90,22 +81,37 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { } #endif /* CONFIG_OF_GPIO */ /** - * of_gpio_count - Count GPIOs for a device + * of_gpio_named_count() - Count GPIOs for a device * @np: device node to count GPIOs for + * @propname: property name containing gpio specifier(s) * * The function returns the count of GPIOs specified for a node. + * Note that the empty GPIO specifiers count too. Returns either + * Number of gpios defined in property, + * -EINVAL for an incorrectly formed gpios property, or + * -ENOENT for a missing gpios property * - * Note that the empty GPIO specifiers counts too. For example, - * + * Example: * gpios = <0 - * &pio1 1 2 + * &gpio1 1 2 * 0 - * &pio2 3 4>; + * &gpio2 3 4>; + * + * The above example defines four GPIOs, two of which are not specified. + * This function will return '4' + */ +static inline int of_gpio_named_count(struct device_node *np, const char* propname) +{ + return of_count_phandle_with_args(np, propname, "#gpio-cells"); +} + +/** + * of_gpio_count() - Count GPIOs for a device + * @np: device node to count GPIOs for * - * defines four GPIOs (so this function will return 4), two of which - * are not specified. + * Same as of_gpio_named_count, but hard coded to use the 'gpios' property */ -static inline unsigned int of_gpio_count(struct device_node *np) +static inline int of_gpio_count(struct device_node *np) { return of_gpio_named_count(np, "gpios"); } -- cgit v0.10.2 From e570d7c15a73f88942885881a84257a65fa44c80 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 12 Feb 2013 15:03:37 -0700 Subject: kbuild: limit dtc+cpp include path Device tree source files may now include header files. The intent is that those header files define/name constants used as part of the DT bindings. Currently this feature is open to abuse, since any kernel header file at all can be included, This could allow device tree files to become dependant on kernel headers files, and thus make them no longer OS-independent. This would also prevent separating the device tree source files from the kernel repository. Solve this by limiting the cpp include path for device tree files to separate directories. Signed-off-by: Stephen Warren Signed-off-by: Grant Likely diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 7910229..07125e6 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -156,6 +156,11 @@ cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ ld_flags = $(LDFLAGS) $(ldflags-y) +dtc_cpp_flags = -Wp,-MD,$(depfile) -nostdinc \ + -I$(srctree)/arch/$(SRCARCH)/boot/dts \ + -I$(srctree)/arch/$(SRCARCH)/include/dts \ + -undef -D__DTS__ + # Finds the multi-part object the current object will be linked into modname-multi = $(sort $(foreach m,$(multi-used),\ $(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=)))) @@ -272,8 +277,7 @@ $(obj)/%.dtb: $(src)/%.dts FORCE dtc-tmp = $(subst $(comma),_,$(dot-target).dts) quiet_cmd_dtc_cpp = DTC+CPP $@ -cmd_dtc_cpp = $(CPP) $(cpp_flags) -x assembler-with-cpp -undef -D__DTS__ \ - -o $(dtc-tmp) $< ; \ +cmd_dtc_cpp = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) $(dtc-tmp) $(obj)/%.dtb: $(src)/%.dtsp FORCE -- cgit v0.10.2 From 02bbde7849e68e193cefaa1885fe0df0f03c9fcd Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 17 Feb 2013 20:03:27 +0000 Subject: Revert "of: use platform_device_add" This reverts commit aac73f34542bc7ae4317928d2eabfeb21d247323. That commit causes two kinds of breakage; it breaks registration of AMBA devices when one of the parent nodes already contains overlapping resource regions, and it breaks calls to request_region() by device drivers in certain conditions where there are overlapping memory regions. Both of these problems can probably be fixed, but it is better to back out the commit and get a proper fix designed before trying again. Signed-off-by: Grant Likely diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 3c3e3ca..b80891b 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -203,7 +203,6 @@ struct platform_device *of_platform_device_create_pdata( struct device *parent) { struct platform_device *dev; - int rc; if (!of_device_is_available(np)) return NULL; @@ -215,24 +214,16 @@ struct platform_device *of_platform_device_create_pdata( #if defined(CONFIG_MICROBLAZE) dev->archdata.dma_mask = 0xffffffffUL; #endif - dev->name = dev_name(&dev->dev); dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + dev->dev.bus = &platform_bus_type; dev->dev.platform_data = platform_data; - dev->dev.id = PLATFORM_DEVID_NONE; - /* device_add will assume that this device is on the same node as - * the parent. If there is no parent defined, set the node - * explicitly */ - if (!parent) - set_dev_node(&dev->dev, of_node_to_nid(np)); /* We do not fill the DMA ops for platform devices by default. * This is currently the responsibility of the platform code * to do such, possibly using a device notifier */ - rc = platform_device_add(dev); - if (rc) { - dev_err(&dev->dev, "device registration failed\n"); + if (of_device_add(dev) != 0) { platform_device_put(dev); return NULL; } -- cgit v0.10.2