diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-20 14:04:46 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-20 14:04:46 -0500 |
commit | b3cdda2b4f541439ca4205793040aa2e1c852e3b (patch) | |
tree | 12f4249a75ba4348b6674c0d46581d959d1dc5c0 /drivers | |
parent | 3aad3f03b2b6d2d977b985c49274cdb78a1593e5 (diff) | |
parent | 02bbde7849e68e193cefaa1885fe0df0f03c9fcd (diff) |
Merge tag 'dt-for-linus' of git://git.secretlab.ca/git/linux
Pull device tree changes from Grant Likely:
"All around device tree changes destined for v3.8. Aside from the
documentation updates the highlights in this branch include:
- Kbuild changes for using CPP with .dts files
- locking fix from preempt_rt patchset
- include DT alias names in device uevent
- Selftest bugfixes and improvements
- New function for counting phandles stanzas in a property
- constify argument to of_node_full_name()
- Various bug fixes
This tree did also contain a commit to use platform_device_add instead
of open-coding the device add code, but it caused problems with amba
devices and needed to be reverted."
* tag 'dt-for-linus' of git://git.secretlab.ca/git/linux: (23 commits)
Revert "of: use platform_device_add"
kbuild: limit dtc+cpp include path
gpio: Make of_count_named_gpios() use new of_count_phandle_with_args()
of: Create function for counting number of phandles in a property
of/base: Clean up exit paths for of_parse_phandle_with_args()
of/selftest: Use selftest() macro throughout
of/selftest: Fix GPIOs selftest to cover the 7th case
of: fix recursive locking in of_get_next_available_child()
documentation/devicetree: Fix a typo in exynos-dw-mshc.txt
OF: convert devtree lock from rw_lock to raw spinlock
of/exynos_g2d: Add Bindings for exynos G2D driver
kbuild: create a rule to run the pre-processor on *.dts files
input: Extend matrix-keypad device tree binding
devicetree: Move NS2 LEDs binding into LEDs directory
of: use platform_device_add
powerpc/5200: Fix size to request_mem_region() call
documentation/devicetree: Fix typos
of: add 'const' to of_node_full_name parameter
of: Output devicetree alias names in uevent
DT: add vendor prefixes for Renesas and Toshiba
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 35 | ||||
-rw-r--r-- | drivers/hwmon/gpio-fan.c | 4 | ||||
-rw-r--r-- | drivers/input/keyboard/matrix_keypad.c | 8 | ||||
-rw-r--r-- | drivers/net/phy/mdio-mux-gpio.c | 4 | ||||
-rw-r--r-- | drivers/of/base.c | 303 | ||||
-rw-r--r-- | drivers/of/device.c | 13 | ||||
-rw-r--r-- | drivers/of/of_private.h | 36 | ||||
-rw-r--r-- | drivers/of/selftest.c | 54 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-spi.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-oc-tiny.c | 8 | ||||
-rw-r--r-- | drivers/spi/spi-ppc4xx.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi.c | 5 |
12 files changed, 304 insertions, 174 deletions
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 25b1dbe8921d..a71a54a3e3f7 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, | |||
89 | EXPORT_SYMBOL(of_get_named_gpio_flags); | 89 | EXPORT_SYMBOL(of_get_named_gpio_flags); |
90 | 90 | ||
91 | /** | 91 | /** |
92 | * of_gpio_named_count - Count GPIOs for a device | ||
93 | * @np: device node to count GPIOs for | ||
94 | * @propname: property name containing gpio specifier(s) | ||
95 | * | ||
96 | * The function returns the count of GPIOs specified for a node. | ||
97 | * | ||
98 | * Note that the empty GPIO specifiers counts too. For example, | ||
99 | * | ||
100 | * gpios = <0 | ||
101 | * &pio1 1 2 | ||
102 | * 0 | ||
103 | * &pio2 3 4>; | ||
104 | * | ||
105 | * defines four GPIOs (so this function will return 4), two of which | ||
106 | * are not specified. | ||
107 | */ | ||
108 | unsigned int of_gpio_named_count(struct device_node *np, const char* propname) | ||
109 | { | ||
110 | unsigned int cnt = 0; | ||
111 | |||
112 | do { | ||
113 | int ret; | ||
114 | |||
115 | ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", | ||
116 | cnt, NULL); | ||
117 | /* A hole in the gpios = <> counts anyway. */ | ||
118 | if (ret < 0 && ret != -EEXIST) | ||
119 | break; | ||
120 | } while (++cnt); | ||
121 | |||
122 | return cnt; | ||
123 | } | ||
124 | EXPORT_SYMBOL(of_gpio_named_count); | ||
125 | |||
126 | /** | ||
127 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags | 92 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags |
128 | * @gc: pointer to the gpio_chip structure | 93 | * @gc: pointer to the gpio_chip structure |
129 | * @np: device node of the GPIO chip | 94 | * @np: device node of the GPIO chip |
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 4e04c1228e51..39781945a5d2 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, | |||
422 | 422 | ||
423 | /* Fill GPIO pin array */ | 423 | /* Fill GPIO pin array */ |
424 | pdata->num_ctrl = of_gpio_count(node); | 424 | pdata->num_ctrl = of_gpio_count(node); |
425 | if (!pdata->num_ctrl) { | 425 | if (pdata->num_ctrl <= 0) { |
426 | dev_err(dev, "gpios DT property empty / missing"); | 426 | dev_err(dev, "gpios DT property empty / missing"); |
427 | return -ENODEV; | 427 | return -ENODEV; |
428 | } | 428 | } |
@@ -477,7 +477,7 @@ static int gpio_fan_get_of_pdata(struct device *dev, | |||
477 | pdata->speed = speed; | 477 | pdata->speed = speed; |
478 | 478 | ||
479 | /* Alarm GPIO if one exists */ | 479 | /* Alarm GPIO if one exists */ |
480 | if (of_gpio_named_count(node, "alarm-gpios")) { | 480 | if (of_gpio_named_count(node, "alarm-gpios") > 0) { |
481 | struct gpio_fan_alarm *alarm; | 481 | struct gpio_fan_alarm *alarm; |
482 | int val; | 482 | int val; |
483 | enum of_gpio_flags flags; | 483 | enum of_gpio_flags flags; |
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index f4ff0dda7597..71d77192ac1e 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) | |||
403 | struct matrix_keypad_platform_data *pdata; | 403 | struct matrix_keypad_platform_data *pdata; |
404 | struct device_node *np = dev->of_node; | 404 | struct device_node *np = dev->of_node; |
405 | unsigned int *gpios; | 405 | unsigned int *gpios; |
406 | int i; | 406 | int i, nrow, ncol; |
407 | 407 | ||
408 | if (!np) { | 408 | if (!np) { |
409 | dev_err(dev, "device lacks DT data\n"); | 409 | dev_err(dev, "device lacks DT data\n"); |
@@ -416,9 +416,9 @@ matrix_keypad_parse_dt(struct device *dev) | |||
416 | return ERR_PTR(-ENOMEM); | 416 | return ERR_PTR(-ENOMEM); |
417 | } | 417 | } |
418 | 418 | ||
419 | pdata->num_row_gpios = of_gpio_named_count(np, "row-gpios"); | 419 | pdata->num_row_gpios = nrow = of_gpio_named_count(np, "row-gpios"); |
420 | pdata->num_col_gpios = of_gpio_named_count(np, "col-gpios"); | 420 | pdata->num_col_gpios = ncol = of_gpio_named_count(np, "col-gpios"); |
421 | if (!pdata->num_row_gpios || !pdata->num_col_gpios) { | 421 | if (nrow <= 0 || ncol <= 0) { |
422 | dev_err(dev, "number of keypad rows/columns not specified\n"); | 422 | dev_err(dev, "number of keypad rows/columns not specified\n"); |
423 | return ERR_PTR(-EINVAL); | 423 | return ERR_PTR(-EINVAL); |
424 | } | 424 | } |
diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c index 0c9accb1c14f..e91d7d736ae2 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) | |||
53 | { | 53 | { |
54 | enum of_gpio_flags f; | 54 | enum of_gpio_flags f; |
55 | struct mdio_mux_gpio_state *s; | 55 | struct mdio_mux_gpio_state *s; |
56 | unsigned int num_gpios; | 56 | int num_gpios; |
57 | unsigned int n; | 57 | unsigned int n; |
58 | int r; | 58 | int r; |
59 | 59 | ||
@@ -61,7 +61,7 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev) | |||
61 | return -ENODEV; | 61 | return -ENODEV; |
62 | 62 | ||
63 | num_gpios = of_gpio_count(pdev->dev.of_node); | 63 | num_gpios = of_gpio_count(pdev->dev.of_node); |
64 | if (num_gpios == 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS) | 64 | if (num_gpios <= 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS) |
65 | return -ENODEV; | 65 | return -ENODEV; |
66 | 66 | ||
67 | s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); | 67 | s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 2390ddb22d60..321d3ef05006 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -24,38 +24,21 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/proc_fs.h> | 25 | #include <linux/proc_fs.h> |
26 | 26 | ||
27 | /** | 27 | #include "of_private.h" |
28 | * struct alias_prop - Alias property in 'aliases' node | ||
29 | * @link: List node to link the structure in aliases_lookup list | ||
30 | * @alias: Alias property name | ||
31 | * @np: Pointer to device_node that the alias stands for | ||
32 | * @id: Index value from end of alias name | ||
33 | * @stem: Alias string without the index | ||
34 | * | ||
35 | * The structure represents one alias property of 'aliases' node as | ||
36 | * an entry in aliases_lookup list. | ||
37 | */ | ||
38 | struct alias_prop { | ||
39 | struct list_head link; | ||
40 | const char *alias; | ||
41 | struct device_node *np; | ||
42 | int id; | ||
43 | char stem[0]; | ||
44 | }; | ||
45 | 28 | ||
46 | static LIST_HEAD(aliases_lookup); | 29 | LIST_HEAD(aliases_lookup); |
47 | 30 | ||
48 | struct device_node *of_allnodes; | 31 | struct device_node *of_allnodes; |
49 | EXPORT_SYMBOL(of_allnodes); | 32 | EXPORT_SYMBOL(of_allnodes); |
50 | struct device_node *of_chosen; | 33 | struct device_node *of_chosen; |
51 | struct device_node *of_aliases; | 34 | struct device_node *of_aliases; |
52 | 35 | ||
53 | static DEFINE_MUTEX(of_aliases_mutex); | 36 | DEFINE_MUTEX(of_aliases_mutex); |
54 | 37 | ||
55 | /* use when traversing tree through the allnext, child, sibling, | 38 | /* use when traversing tree through the allnext, child, sibling, |
56 | * or parent members of struct device_node. | 39 | * or parent members of struct device_node. |
57 | */ | 40 | */ |
58 | DEFINE_RWLOCK(devtree_lock); | 41 | DEFINE_RAW_SPINLOCK(devtree_lock); |
59 | 42 | ||
60 | int of_n_addr_cells(struct device_node *np) | 43 | int of_n_addr_cells(struct device_node *np) |
61 | { | 44 | { |
@@ -164,16 +147,14 @@ void of_node_put(struct device_node *node) | |||
164 | EXPORT_SYMBOL(of_node_put); | 147 | EXPORT_SYMBOL(of_node_put); |
165 | #endif /* CONFIG_OF_DYNAMIC */ | 148 | #endif /* CONFIG_OF_DYNAMIC */ |
166 | 149 | ||
167 | struct property *of_find_property(const struct device_node *np, | 150 | static struct property *__of_find_property(const struct device_node *np, |
168 | const char *name, | 151 | const char *name, int *lenp) |
169 | int *lenp) | ||
170 | { | 152 | { |
171 | struct property *pp; | 153 | struct property *pp; |
172 | 154 | ||
173 | if (!np) | 155 | if (!np) |
174 | return NULL; | 156 | return NULL; |
175 | 157 | ||
176 | read_lock(&devtree_lock); | ||
177 | for (pp = np->properties; pp; pp = pp->next) { | 158 | for (pp = np->properties; pp; pp = pp->next) { |
178 | if (of_prop_cmp(pp->name, name) == 0) { | 159 | if (of_prop_cmp(pp->name, name) == 0) { |
179 | if (lenp) | 160 | if (lenp) |
@@ -181,7 +162,20 @@ struct property *of_find_property(const struct device_node *np, | |||
181 | break; | 162 | break; |
182 | } | 163 | } |
183 | } | 164 | } |
184 | read_unlock(&devtree_lock); | 165 | |
166 | return pp; | ||
167 | } | ||
168 | |||
169 | struct property *of_find_property(const struct device_node *np, | ||
170 | const char *name, | ||
171 | int *lenp) | ||
172 | { | ||
173 | struct property *pp; | ||
174 | unsigned long flags; | ||
175 | |||
176 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
177 | pp = __of_find_property(np, name, lenp); | ||
178 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
185 | 179 | ||
186 | return pp; | 180 | return pp; |
187 | } | 181 | } |
@@ -199,13 +193,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev) | |||
199 | { | 193 | { |
200 | struct device_node *np; | 194 | struct device_node *np; |
201 | 195 | ||
202 | read_lock(&devtree_lock); | 196 | raw_spin_lock(&devtree_lock); |
203 | np = prev ? prev->allnext : of_allnodes; | 197 | np = prev ? prev->allnext : of_allnodes; |
204 | for (; np != NULL; np = np->allnext) | 198 | for (; np != NULL; np = np->allnext) |
205 | if (of_node_get(np)) | 199 | if (of_node_get(np)) |
206 | break; | 200 | break; |
207 | of_node_put(prev); | 201 | of_node_put(prev); |
208 | read_unlock(&devtree_lock); | 202 | raw_spin_unlock(&devtree_lock); |
209 | return np; | 203 | return np; |
210 | } | 204 | } |
211 | EXPORT_SYMBOL(of_find_all_nodes); | 205 | EXPORT_SYMBOL(of_find_all_nodes); |
@@ -214,8 +208,20 @@ EXPORT_SYMBOL(of_find_all_nodes); | |||
214 | * Find a property with a given name for a given node | 208 | * Find a property with a given name for a given node |
215 | * and return the value. | 209 | * and return the value. |
216 | */ | 210 | */ |
211 | static const void *__of_get_property(const struct device_node *np, | ||
212 | const char *name, int *lenp) | ||
213 | { | ||
214 | struct property *pp = __of_find_property(np, name, lenp); | ||
215 | |||
216 | return pp ? pp->value : NULL; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Find a property with a given name for a given node | ||
221 | * and return the value. | ||
222 | */ | ||
217 | const void *of_get_property(const struct device_node *np, const char *name, | 223 | const void *of_get_property(const struct device_node *np, const char *name, |
218 | int *lenp) | 224 | int *lenp) |
219 | { | 225 | { |
220 | struct property *pp = of_find_property(np, name, lenp); | 226 | struct property *pp = of_find_property(np, name, lenp); |
221 | 227 | ||
@@ -226,13 +232,13 @@ EXPORT_SYMBOL(of_get_property); | |||
226 | /** Checks if the given "compat" string matches one of the strings in | 232 | /** Checks if the given "compat" string matches one of the strings in |
227 | * the device's "compatible" property | 233 | * the device's "compatible" property |
228 | */ | 234 | */ |
229 | int of_device_is_compatible(const struct device_node *device, | 235 | static int __of_device_is_compatible(const struct device_node *device, |
230 | const char *compat) | 236 | const char *compat) |
231 | { | 237 | { |
232 | const char* cp; | 238 | const char* cp; |
233 | int cplen, l; | 239 | int cplen, l; |
234 | 240 | ||
235 | cp = of_get_property(device, "compatible", &cplen); | 241 | cp = __of_get_property(device, "compatible", &cplen); |
236 | if (cp == NULL) | 242 | if (cp == NULL) |
237 | return 0; | 243 | return 0; |
238 | while (cplen > 0) { | 244 | while (cplen > 0) { |
@@ -245,6 +251,21 @@ int of_device_is_compatible(const struct device_node *device, | |||
245 | 251 | ||
246 | return 0; | 252 | return 0; |
247 | } | 253 | } |
254 | |||
255 | /** Checks if the given "compat" string matches one of the strings in | ||
256 | * the device's "compatible" property | ||
257 | */ | ||
258 | int of_device_is_compatible(const struct device_node *device, | ||
259 | const char *compat) | ||
260 | { | ||
261 | unsigned long flags; | ||
262 | int res; | ||
263 | |||
264 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
265 | res = __of_device_is_compatible(device, compat); | ||
266 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
267 | return res; | ||
268 | } | ||
248 | EXPORT_SYMBOL(of_device_is_compatible); | 269 | EXPORT_SYMBOL(of_device_is_compatible); |
249 | 270 | ||
250 | /** | 271 | /** |
@@ -269,19 +290,19 @@ int of_machine_is_compatible(const char *compat) | |||
269 | EXPORT_SYMBOL(of_machine_is_compatible); | 290 | EXPORT_SYMBOL(of_machine_is_compatible); |
270 | 291 | ||
271 | /** | 292 | /** |
272 | * of_device_is_available - check if a device is available for use | 293 | * __of_device_is_available - check if a device is available for use |
273 | * | 294 | * |
274 | * @device: Node to check for availability | 295 | * @device: Node to check for availability, with locks already held |
275 | * | 296 | * |
276 | * Returns 1 if the status property is absent or set to "okay" or "ok", | 297 | * Returns 1 if the status property is absent or set to "okay" or "ok", |
277 | * 0 otherwise | 298 | * 0 otherwise |
278 | */ | 299 | */ |
279 | int of_device_is_available(const struct device_node *device) | 300 | static int __of_device_is_available(const struct device_node *device) |
280 | { | 301 | { |
281 | const char *status; | 302 | const char *status; |
282 | int statlen; | 303 | int statlen; |
283 | 304 | ||
284 | status = of_get_property(device, "status", &statlen); | 305 | status = __of_get_property(device, "status", &statlen); |
285 | if (status == NULL) | 306 | if (status == NULL) |
286 | return 1; | 307 | return 1; |
287 | 308 | ||
@@ -292,6 +313,26 @@ int of_device_is_available(const struct device_node *device) | |||
292 | 313 | ||
293 | return 0; | 314 | return 0; |
294 | } | 315 | } |
316 | |||
317 | /** | ||
318 | * of_device_is_available - check if a device is available for use | ||
319 | * | ||
320 | * @device: Node to check for availability | ||
321 | * | ||
322 | * Returns 1 if the status property is absent or set to "okay" or "ok", | ||
323 | * 0 otherwise | ||
324 | */ | ||
325 | int of_device_is_available(const struct device_node *device) | ||
326 | { | ||
327 | unsigned long flags; | ||
328 | int res; | ||
329 | |||
330 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
331 | res = __of_device_is_available(device); | ||
332 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
333 | return res; | ||
334 | |||
335 | } | ||
295 | EXPORT_SYMBOL(of_device_is_available); | 336 | EXPORT_SYMBOL(of_device_is_available); |
296 | 337 | ||
297 | /** | 338 | /** |
@@ -304,13 +345,14 @@ EXPORT_SYMBOL(of_device_is_available); | |||
304 | struct device_node *of_get_parent(const struct device_node *node) | 345 | struct device_node *of_get_parent(const struct device_node *node) |
305 | { | 346 | { |
306 | struct device_node *np; | 347 | struct device_node *np; |
348 | unsigned long flags; | ||
307 | 349 | ||
308 | if (!node) | 350 | if (!node) |
309 | return NULL; | 351 | return NULL; |
310 | 352 | ||
311 | read_lock(&devtree_lock); | 353 | raw_spin_lock_irqsave(&devtree_lock, flags); |
312 | np = of_node_get(node->parent); | 354 | np = of_node_get(node->parent); |
313 | read_unlock(&devtree_lock); | 355 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
314 | return np; | 356 | return np; |
315 | } | 357 | } |
316 | EXPORT_SYMBOL(of_get_parent); | 358 | EXPORT_SYMBOL(of_get_parent); |
@@ -329,14 +371,15 @@ EXPORT_SYMBOL(of_get_parent); | |||
329 | struct device_node *of_get_next_parent(struct device_node *node) | 371 | struct device_node *of_get_next_parent(struct device_node *node) |
330 | { | 372 | { |
331 | struct device_node *parent; | 373 | struct device_node *parent; |
374 | unsigned long flags; | ||
332 | 375 | ||
333 | if (!node) | 376 | if (!node) |
334 | return NULL; | 377 | return NULL; |
335 | 378 | ||
336 | read_lock(&devtree_lock); | 379 | raw_spin_lock_irqsave(&devtree_lock, flags); |
337 | parent = of_node_get(node->parent); | 380 | parent = of_node_get(node->parent); |
338 | of_node_put(node); | 381 | of_node_put(node); |
339 | read_unlock(&devtree_lock); | 382 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
340 | return parent; | 383 | return parent; |
341 | } | 384 | } |
342 | 385 | ||
@@ -352,14 +395,15 @@ struct device_node *of_get_next_child(const struct device_node *node, | |||
352 | struct device_node *prev) | 395 | struct device_node *prev) |
353 | { | 396 | { |
354 | struct device_node *next; | 397 | struct device_node *next; |
398 | unsigned long flags; | ||
355 | 399 | ||
356 | read_lock(&devtree_lock); | 400 | raw_spin_lock_irqsave(&devtree_lock, flags); |
357 | next = prev ? prev->sibling : node->child; | 401 | next = prev ? prev->sibling : node->child; |
358 | for (; next; next = next->sibling) | 402 | for (; next; next = next->sibling) |
359 | if (of_node_get(next)) | 403 | if (of_node_get(next)) |
360 | break; | 404 | break; |
361 | of_node_put(prev); | 405 | of_node_put(prev); |
362 | read_unlock(&devtree_lock); | 406 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
363 | return next; | 407 | return next; |
364 | } | 408 | } |
365 | EXPORT_SYMBOL(of_get_next_child); | 409 | EXPORT_SYMBOL(of_get_next_child); |
@@ -377,16 +421,16 @@ struct device_node *of_get_next_available_child(const struct device_node *node, | |||
377 | { | 421 | { |
378 | struct device_node *next; | 422 | struct device_node *next; |
379 | 423 | ||
380 | read_lock(&devtree_lock); | 424 | raw_spin_lock(&devtree_lock); |
381 | next = prev ? prev->sibling : node->child; | 425 | next = prev ? prev->sibling : node->child; |
382 | for (; next; next = next->sibling) { | 426 | for (; next; next = next->sibling) { |
383 | if (!of_device_is_available(next)) | 427 | if (!__of_device_is_available(next)) |
384 | continue; | 428 | continue; |
385 | if (of_node_get(next)) | 429 | if (of_node_get(next)) |
386 | break; | 430 | break; |
387 | } | 431 | } |
388 | of_node_put(prev); | 432 | of_node_put(prev); |
389 | read_unlock(&devtree_lock); | 433 | raw_spin_unlock(&devtree_lock); |
390 | return next; | 434 | return next; |
391 | } | 435 | } |
392 | EXPORT_SYMBOL(of_get_next_available_child); | 436 | EXPORT_SYMBOL(of_get_next_available_child); |
@@ -424,14 +468,15 @@ EXPORT_SYMBOL(of_get_child_by_name); | |||
424 | struct device_node *of_find_node_by_path(const char *path) | 468 | struct device_node *of_find_node_by_path(const char *path) |
425 | { | 469 | { |
426 | struct device_node *np = of_allnodes; | 470 | struct device_node *np = of_allnodes; |
471 | unsigned long flags; | ||
427 | 472 | ||
428 | read_lock(&devtree_lock); | 473 | raw_spin_lock_irqsave(&devtree_lock, flags); |
429 | for (; np; np = np->allnext) { | 474 | for (; np; np = np->allnext) { |
430 | if (np->full_name && (of_node_cmp(np->full_name, path) == 0) | 475 | if (np->full_name && (of_node_cmp(np->full_name, path) == 0) |
431 | && of_node_get(np)) | 476 | && of_node_get(np)) |
432 | break; | 477 | break; |
433 | } | 478 | } |
434 | read_unlock(&devtree_lock); | 479 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
435 | return np; | 480 | return np; |
436 | } | 481 | } |
437 | EXPORT_SYMBOL(of_find_node_by_path); | 482 | EXPORT_SYMBOL(of_find_node_by_path); |
@@ -451,15 +496,16 @@ struct device_node *of_find_node_by_name(struct device_node *from, | |||
451 | const char *name) | 496 | const char *name) |
452 | { | 497 | { |
453 | struct device_node *np; | 498 | struct device_node *np; |
499 | unsigned long flags; | ||
454 | 500 | ||
455 | read_lock(&devtree_lock); | 501 | raw_spin_lock_irqsave(&devtree_lock, flags); |
456 | np = from ? from->allnext : of_allnodes; | 502 | np = from ? from->allnext : of_allnodes; |
457 | for (; np; np = np->allnext) | 503 | for (; np; np = np->allnext) |
458 | if (np->name && (of_node_cmp(np->name, name) == 0) | 504 | if (np->name && (of_node_cmp(np->name, name) == 0) |
459 | && of_node_get(np)) | 505 | && of_node_get(np)) |
460 | break; | 506 | break; |
461 | of_node_put(from); | 507 | of_node_put(from); |
462 | read_unlock(&devtree_lock); | 508 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
463 | return np; | 509 | return np; |
464 | } | 510 | } |
465 | EXPORT_SYMBOL(of_find_node_by_name); | 511 | EXPORT_SYMBOL(of_find_node_by_name); |
@@ -480,15 +526,16 @@ struct device_node *of_find_node_by_type(struct device_node *from, | |||
480 | const char *type) | 526 | const char *type) |
481 | { | 527 | { |
482 | struct device_node *np; | 528 | struct device_node *np; |
529 | unsigned long flags; | ||
483 | 530 | ||
484 | read_lock(&devtree_lock); | 531 | raw_spin_lock_irqsave(&devtree_lock, flags); |
485 | np = from ? from->allnext : of_allnodes; | 532 | np = from ? from->allnext : of_allnodes; |
486 | for (; np; np = np->allnext) | 533 | for (; np; np = np->allnext) |
487 | if (np->type && (of_node_cmp(np->type, type) == 0) | 534 | if (np->type && (of_node_cmp(np->type, type) == 0) |
488 | && of_node_get(np)) | 535 | && of_node_get(np)) |
489 | break; | 536 | break; |
490 | of_node_put(from); | 537 | of_node_put(from); |
491 | read_unlock(&devtree_lock); | 538 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
492 | return np; | 539 | return np; |
493 | } | 540 | } |
494 | EXPORT_SYMBOL(of_find_node_by_type); | 541 | EXPORT_SYMBOL(of_find_node_by_type); |
@@ -511,18 +558,20 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
511 | const char *type, const char *compatible) | 558 | const char *type, const char *compatible) |
512 | { | 559 | { |
513 | struct device_node *np; | 560 | struct device_node *np; |
561 | unsigned long flags; | ||
514 | 562 | ||
515 | read_lock(&devtree_lock); | 563 | raw_spin_lock_irqsave(&devtree_lock, flags); |
516 | np = from ? from->allnext : of_allnodes; | 564 | np = from ? from->allnext : of_allnodes; |
517 | for (; np; np = np->allnext) { | 565 | for (; np; np = np->allnext) { |
518 | if (type | 566 | if (type |
519 | && !(np->type && (of_node_cmp(np->type, type) == 0))) | 567 | && !(np->type && (of_node_cmp(np->type, type) == 0))) |
520 | continue; | 568 | continue; |
521 | if (of_device_is_compatible(np, compatible) && of_node_get(np)) | 569 | if (__of_device_is_compatible(np, compatible) && |
570 | of_node_get(np)) | ||
522 | break; | 571 | break; |
523 | } | 572 | } |
524 | of_node_put(from); | 573 | of_node_put(from); |
525 | read_unlock(&devtree_lock); | 574 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
526 | return np; | 575 | return np; |
527 | } | 576 | } |
528 | EXPORT_SYMBOL(of_find_compatible_node); | 577 | EXPORT_SYMBOL(of_find_compatible_node); |
@@ -544,8 +593,9 @@ struct device_node *of_find_node_with_property(struct device_node *from, | |||
544 | { | 593 | { |
545 | struct device_node *np; | 594 | struct device_node *np; |
546 | struct property *pp; | 595 | struct property *pp; |
596 | unsigned long flags; | ||
547 | 597 | ||
548 | read_lock(&devtree_lock); | 598 | raw_spin_lock_irqsave(&devtree_lock, flags); |
549 | np = from ? from->allnext : of_allnodes; | 599 | np = from ? from->allnext : of_allnodes; |
550 | for (; np; np = np->allnext) { | 600 | for (; np; np = np->allnext) { |
551 | for (pp = np->properties; pp; pp = pp->next) { | 601 | for (pp = np->properties; pp; pp = pp->next) { |
@@ -557,20 +607,14 @@ struct device_node *of_find_node_with_property(struct device_node *from, | |||
557 | } | 607 | } |
558 | out: | 608 | out: |
559 | of_node_put(from); | 609 | of_node_put(from); |
560 | read_unlock(&devtree_lock); | 610 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
561 | return np; | 611 | return np; |
562 | } | 612 | } |
563 | EXPORT_SYMBOL(of_find_node_with_property); | 613 | EXPORT_SYMBOL(of_find_node_with_property); |
564 | 614 | ||
565 | /** | 615 | static |
566 | * of_match_node - Tell if an device_node has a matching of_match structure | 616 | const struct of_device_id *__of_match_node(const struct of_device_id *matches, |
567 | * @matches: array of of device match structures to search in | 617 | const struct device_node *node) |
568 | * @node: the of device structure to match against | ||
569 | * | ||
570 | * Low level utility function used by device matching. | ||
571 | */ | ||
572 | const struct of_device_id *of_match_node(const struct of_device_id *matches, | ||
573 | const struct device_node *node) | ||
574 | { | 618 | { |
575 | if (!matches) | 619 | if (!matches) |
576 | return NULL; | 620 | return NULL; |
@@ -584,14 +628,33 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, | |||
584 | match &= node->type | 628 | match &= node->type |
585 | && !strcmp(matches->type, node->type); | 629 | && !strcmp(matches->type, node->type); |
586 | if (matches->compatible[0]) | 630 | if (matches->compatible[0]) |
587 | match &= of_device_is_compatible(node, | 631 | match &= __of_device_is_compatible(node, |
588 | matches->compatible); | 632 | matches->compatible); |
589 | if (match) | 633 | if (match) |
590 | return matches; | 634 | return matches; |
591 | matches++; | 635 | matches++; |
592 | } | 636 | } |
593 | return NULL; | 637 | return NULL; |
594 | } | 638 | } |
639 | |||
640 | /** | ||
641 | * of_match_node - Tell if an device_node has a matching of_match structure | ||
642 | * @matches: array of of device match structures to search in | ||
643 | * @node: the of device structure to match against | ||
644 | * | ||
645 | * Low level utility function used by device matching. | ||
646 | */ | ||
647 | const struct of_device_id *of_match_node(const struct of_device_id *matches, | ||
648 | const struct device_node *node) | ||
649 | { | ||
650 | const struct of_device_id *match; | ||
651 | unsigned long flags; | ||
652 | |||
653 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
654 | match = __of_match_node(matches, node); | ||
655 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
656 | return match; | ||
657 | } | ||
595 | EXPORT_SYMBOL(of_match_node); | 658 | EXPORT_SYMBOL(of_match_node); |
596 | 659 | ||
597 | /** | 660 | /** |
@@ -612,21 +675,24 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, | |||
612 | const struct of_device_id **match) | 675 | const struct of_device_id **match) |
613 | { | 676 | { |
614 | struct device_node *np; | 677 | struct device_node *np; |
678 | const struct of_device_id *m; | ||
679 | unsigned long flags; | ||
615 | 680 | ||
616 | if (match) | 681 | if (match) |
617 | *match = NULL; | 682 | *match = NULL; |
618 | 683 | ||
619 | read_lock(&devtree_lock); | 684 | raw_spin_lock_irqsave(&devtree_lock, flags); |
620 | np = from ? from->allnext : of_allnodes; | 685 | np = from ? from->allnext : of_allnodes; |
621 | for (; np; np = np->allnext) { | 686 | for (; np; np = np->allnext) { |
622 | if (of_match_node(matches, np) && of_node_get(np)) { | 687 | m = __of_match_node(matches, np); |
688 | if (m && of_node_get(np)) { | ||
623 | if (match) | 689 | if (match) |
624 | *match = matches; | 690 | *match = m; |
625 | break; | 691 | break; |
626 | } | 692 | } |
627 | } | 693 | } |
628 | of_node_put(from); | 694 | of_node_put(from); |
629 | read_unlock(&devtree_lock); | 695 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
630 | return np; | 696 | return np; |
631 | } | 697 | } |
632 | EXPORT_SYMBOL(of_find_matching_node_and_match); | 698 | EXPORT_SYMBOL(of_find_matching_node_and_match); |
@@ -669,12 +735,12 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
669 | { | 735 | { |
670 | struct device_node *np; | 736 | struct device_node *np; |
671 | 737 | ||
672 | read_lock(&devtree_lock); | 738 | raw_spin_lock(&devtree_lock); |
673 | for (np = of_allnodes; np; np = np->allnext) | 739 | for (np = of_allnodes; np; np = np->allnext) |
674 | if (np->phandle == handle) | 740 | if (np->phandle == handle) |
675 | break; | 741 | break; |
676 | of_node_get(np); | 742 | of_node_get(np); |
677 | read_unlock(&devtree_lock); | 743 | raw_spin_unlock(&devtree_lock); |
678 | return np; | 744 | return np; |
679 | } | 745 | } |
680 | EXPORT_SYMBOL(of_find_node_by_phandle); | 746 | EXPORT_SYMBOL(of_find_node_by_phandle); |
@@ -1025,12 +1091,13 @@ EXPORT_SYMBOL(of_parse_phandle); | |||
1025 | * To get a device_node of the `node2' node you may call this: | 1091 | * To get a device_node of the `node2' node you may call this: |
1026 | * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); | 1092 | * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); |
1027 | */ | 1093 | */ |
1028 | int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, | 1094 | static int __of_parse_phandle_with_args(const struct device_node *np, |
1029 | const char *cells_name, int index, | 1095 | const char *list_name, |
1030 | struct of_phandle_args *out_args) | 1096 | const char *cells_name, int index, |
1097 | struct of_phandle_args *out_args) | ||
1031 | { | 1098 | { |
1032 | const __be32 *list, *list_end; | 1099 | const __be32 *list, *list_end; |
1033 | int size, cur_index = 0; | 1100 | int rc = 0, size, cur_index = 0; |
1034 | uint32_t count = 0; | 1101 | uint32_t count = 0; |
1035 | struct device_node *node = NULL; | 1102 | struct device_node *node = NULL; |
1036 | phandle phandle; | 1103 | phandle phandle; |
@@ -1043,6 +1110,7 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na | |||
1043 | 1110 | ||
1044 | /* Loop over the phandles until all the requested entry is found */ | 1111 | /* Loop over the phandles until all the requested entry is found */ |
1045 | while (list < list_end) { | 1112 | while (list < list_end) { |
1113 | rc = -EINVAL; | ||
1046 | count = 0; | 1114 | count = 0; |
1047 | 1115 | ||
1048 | /* | 1116 | /* |
@@ -1059,13 +1127,13 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na | |||
1059 | if (!node) { | 1127 | if (!node) { |
1060 | pr_err("%s: could not find phandle\n", | 1128 | pr_err("%s: could not find phandle\n", |
1061 | np->full_name); | 1129 | np->full_name); |
1062 | break; | 1130 | goto err; |
1063 | } | 1131 | } |
1064 | if (of_property_read_u32(node, cells_name, &count)) { | 1132 | if (of_property_read_u32(node, cells_name, &count)) { |
1065 | pr_err("%s: could not get %s for %s\n", | 1133 | pr_err("%s: could not get %s for %s\n", |
1066 | np->full_name, cells_name, | 1134 | np->full_name, cells_name, |
1067 | node->full_name); | 1135 | node->full_name); |
1068 | break; | 1136 | goto err; |
1069 | } | 1137 | } |
1070 | 1138 | ||
1071 | /* | 1139 | /* |
@@ -1075,7 +1143,7 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na | |||
1075 | if (list + count > list_end) { | 1143 | if (list + count > list_end) { |
1076 | pr_err("%s: arguments longer than property\n", | 1144 | pr_err("%s: arguments longer than property\n", |
1077 | np->full_name); | 1145 | np->full_name); |
1078 | break; | 1146 | goto err; |
1079 | } | 1147 | } |
1080 | } | 1148 | } |
1081 | 1149 | ||
@@ -1085,9 +1153,10 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na | |||
1085 | * index matches, then fill the out_args structure and return, | 1153 | * index matches, then fill the out_args structure and return, |
1086 | * or return -ENOENT for an empty entry. | 1154 | * or return -ENOENT for an empty entry. |
1087 | */ | 1155 | */ |
1156 | rc = -ENOENT; | ||
1088 | if (cur_index == index) { | 1157 | if (cur_index == index) { |
1089 | if (!phandle) | 1158 | if (!phandle) |
1090 | return -ENOENT; | 1159 | goto err; |
1091 | 1160 | ||
1092 | if (out_args) { | 1161 | if (out_args) { |
1093 | int i; | 1162 | int i; |
@@ -1098,6 +1167,10 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na | |||
1098 | for (i = 0; i < count; i++) | 1167 | for (i = 0; i < count; i++) |
1099 | out_args->args[i] = be32_to_cpup(list++); | 1168 | out_args->args[i] = be32_to_cpup(list++); |
1100 | } | 1169 | } |
1170 | |||
1171 | /* Found it! return success */ | ||
1172 | if (node) | ||
1173 | of_node_put(node); | ||
1101 | return 0; | 1174 | return 0; |
1102 | } | 1175 | } |
1103 | 1176 | ||
@@ -1107,13 +1180,51 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na | |||
1107 | cur_index++; | 1180 | cur_index++; |
1108 | } | 1181 | } |
1109 | 1182 | ||
1110 | /* Loop exited without finding a valid entry; return an error */ | 1183 | /* |
1184 | * Unlock node before returning result; will be one of: | ||
1185 | * -ENOENT : index is for empty phandle | ||
1186 | * -EINVAL : parsing error on data | ||
1187 | * [1..n] : Number of phandle (count mode; when index = -1) | ||
1188 | */ | ||
1189 | rc = index < 0 ? cur_index : -ENOENT; | ||
1190 | err: | ||
1111 | if (node) | 1191 | if (node) |
1112 | of_node_put(node); | 1192 | of_node_put(node); |
1113 | return -EINVAL; | 1193 | return rc; |
1194 | } | ||
1195 | |||
1196 | int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, | ||
1197 | const char *cells_name, int index, | ||
1198 | struct of_phandle_args *out_args) | ||
1199 | { | ||
1200 | if (index < 0) | ||
1201 | return -EINVAL; | ||
1202 | return __of_parse_phandle_with_args(np, list_name, cells_name, index, out_args); | ||
1114 | } | 1203 | } |
1115 | EXPORT_SYMBOL(of_parse_phandle_with_args); | 1204 | EXPORT_SYMBOL(of_parse_phandle_with_args); |
1116 | 1205 | ||
1206 | /** | ||
1207 | * of_count_phandle_with_args() - Find the number of phandles references in a property | ||
1208 | * @np: pointer to a device tree node containing a list | ||
1209 | * @list_name: property name that contains a list | ||
1210 | * @cells_name: property name that specifies phandles' arguments count | ||
1211 | * | ||
1212 | * Returns the number of phandle + argument tuples within a property. It | ||
1213 | * is a typical pattern to encode a list of phandle and variable | ||
1214 | * arguments into a single property. The number of arguments is encoded | ||
1215 | * by a property in the phandle-target node. For example, a gpios | ||
1216 | * property would contain a list of GPIO specifies consisting of a | ||
1217 | * phandle and 1 or more arguments. The number of arguments are | ||
1218 | * determined by the #gpio-cells property in the node pointed to by the | ||
1219 | * phandle. | ||
1220 | */ | ||
1221 | int of_count_phandle_with_args(const struct device_node *np, const char *list_name, | ||
1222 | const char *cells_name) | ||
1223 | { | ||
1224 | return __of_parse_phandle_with_args(np, list_name, cells_name, -1, NULL); | ||
1225 | } | ||
1226 | EXPORT_SYMBOL(of_count_phandle_with_args); | ||
1227 | |||
1117 | #if defined(CONFIG_OF_DYNAMIC) | 1228 | #if defined(CONFIG_OF_DYNAMIC) |
1118 | static int of_property_notify(int action, struct device_node *np, | 1229 | static int of_property_notify(int action, struct device_node *np, |
1119 | struct property *prop) | 1230 | struct property *prop) |
@@ -1146,18 +1257,18 @@ int of_add_property(struct device_node *np, struct property *prop) | |||
1146 | return rc; | 1257 | return rc; |
1147 | 1258 | ||
1148 | prop->next = NULL; | 1259 | prop->next = NULL; |
1149 | write_lock_irqsave(&devtree_lock, flags); | 1260 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1150 | next = &np->properties; | 1261 | next = &np->properties; |
1151 | while (*next) { | 1262 | while (*next) { |
1152 | if (strcmp(prop->name, (*next)->name) == 0) { | 1263 | if (strcmp(prop->name, (*next)->name) == 0) { |
1153 | /* duplicate ! don't insert it */ | 1264 | /* duplicate ! don't insert it */ |
1154 | write_unlock_irqrestore(&devtree_lock, flags); | 1265 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1155 | return -1; | 1266 | return -1; |
1156 | } | 1267 | } |
1157 | next = &(*next)->next; | 1268 | next = &(*next)->next; |
1158 | } | 1269 | } |
1159 | *next = prop; | 1270 | *next = prop; |
1160 | write_unlock_irqrestore(&devtree_lock, flags); | 1271 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1161 | 1272 | ||
1162 | #ifdef CONFIG_PROC_DEVICETREE | 1273 | #ifdef CONFIG_PROC_DEVICETREE |
1163 | /* try to add to proc as well if it was initialized */ | 1274 | /* try to add to proc as well if it was initialized */ |
@@ -1187,7 +1298,7 @@ int of_remove_property(struct device_node *np, struct property *prop) | |||
1187 | if (rc) | 1298 | if (rc) |
1188 | return rc; | 1299 | return rc; |
1189 | 1300 | ||
1190 | write_lock_irqsave(&devtree_lock, flags); | 1301 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1191 | next = &np->properties; | 1302 | next = &np->properties; |
1192 | while (*next) { | 1303 | while (*next) { |
1193 | if (*next == prop) { | 1304 | if (*next == prop) { |
@@ -1200,7 +1311,7 @@ int of_remove_property(struct device_node *np, struct property *prop) | |||
1200 | } | 1311 | } |
1201 | next = &(*next)->next; | 1312 | next = &(*next)->next; |
1202 | } | 1313 | } |
1203 | write_unlock_irqrestore(&devtree_lock, flags); | 1314 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1204 | 1315 | ||
1205 | if (!found) | 1316 | if (!found) |
1206 | return -ENODEV; | 1317 | return -ENODEV; |
@@ -1240,7 +1351,7 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1240 | if (!oldprop) | 1351 | if (!oldprop) |
1241 | return of_add_property(np, newprop); | 1352 | return of_add_property(np, newprop); |
1242 | 1353 | ||
1243 | write_lock_irqsave(&devtree_lock, flags); | 1354 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1244 | next = &np->properties; | 1355 | next = &np->properties; |
1245 | while (*next) { | 1356 | while (*next) { |
1246 | if (*next == oldprop) { | 1357 | if (*next == oldprop) { |
@@ -1254,7 +1365,7 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1254 | } | 1365 | } |
1255 | next = &(*next)->next; | 1366 | next = &(*next)->next; |
1256 | } | 1367 | } |
1257 | write_unlock_irqrestore(&devtree_lock, flags); | 1368 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1258 | 1369 | ||
1259 | if (!found) | 1370 | if (!found) |
1260 | return -ENODEV; | 1371 | return -ENODEV; |
@@ -1327,12 +1438,12 @@ int of_attach_node(struct device_node *np) | |||
1327 | if (rc) | 1438 | if (rc) |
1328 | return rc; | 1439 | return rc; |
1329 | 1440 | ||
1330 | write_lock_irqsave(&devtree_lock, flags); | 1441 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1331 | np->sibling = np->parent->child; | 1442 | np->sibling = np->parent->child; |
1332 | np->allnext = of_allnodes; | 1443 | np->allnext = of_allnodes; |
1333 | np->parent->child = np; | 1444 | np->parent->child = np; |
1334 | of_allnodes = np; | 1445 | of_allnodes = np; |
1335 | write_unlock_irqrestore(&devtree_lock, flags); | 1446 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1336 | 1447 | ||
1337 | of_add_proc_dt_entry(np); | 1448 | of_add_proc_dt_entry(np); |
1338 | return 0; | 1449 | return 0; |
@@ -1375,17 +1486,17 @@ int of_detach_node(struct device_node *np) | |||
1375 | if (rc) | 1486 | if (rc) |
1376 | return rc; | 1487 | return rc; |
1377 | 1488 | ||
1378 | write_lock_irqsave(&devtree_lock, flags); | 1489 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1379 | 1490 | ||
1380 | if (of_node_check_flag(np, OF_DETACHED)) { | 1491 | if (of_node_check_flag(np, OF_DETACHED)) { |
1381 | /* someone already detached it */ | 1492 | /* someone already detached it */ |
1382 | write_unlock_irqrestore(&devtree_lock, flags); | 1493 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1383 | return rc; | 1494 | return rc; |
1384 | } | 1495 | } |
1385 | 1496 | ||
1386 | parent = np->parent; | 1497 | parent = np->parent; |
1387 | if (!parent) { | 1498 | if (!parent) { |
1388 | write_unlock_irqrestore(&devtree_lock, flags); | 1499 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1389 | return rc; | 1500 | return rc; |
1390 | } | 1501 | } |
1391 | 1502 | ||
@@ -1412,7 +1523,7 @@ int of_detach_node(struct device_node *np) | |||
1412 | } | 1523 | } |
1413 | 1524 | ||
1414 | of_node_set_flag(np, OF_DETACHED); | 1525 | of_node_set_flag(np, OF_DETACHED); |
1415 | write_unlock_irqrestore(&devtree_lock, flags); | 1526 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1416 | 1527 | ||
1417 | of_remove_proc_dt_entry(np); | 1528 | of_remove_proc_dt_entry(np); |
1418 | return rc; | 1529 | return rc; |
diff --git a/drivers/of/device.c b/drivers/of/device.c index 4c74e4fc5a51..f685e55e0717 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
9 | 9 | ||
10 | #include <asm/errno.h> | 10 | #include <asm/errno.h> |
11 | #include "of_private.h" | ||
11 | 12 | ||
12 | /** | 13 | /** |
13 | * of_match_device - Tell if a struct device matches an of_device_id list | 14 | * 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) | |||
131 | void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) | 132 | void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) |
132 | { | 133 | { |
133 | const char *compat; | 134 | const char *compat; |
135 | struct alias_prop *app; | ||
134 | int seen = 0, cplen, sl; | 136 | int seen = 0, cplen, sl; |
135 | 137 | ||
136 | if ((!dev) || (!dev->of_node)) | 138 | if ((!dev) || (!dev->of_node)) |
@@ -153,6 +155,17 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
153 | seen++; | 155 | seen++; |
154 | } | 156 | } |
155 | add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); | 157 | add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); |
158 | |||
159 | seen = 0; | ||
160 | mutex_lock(&of_aliases_mutex); | ||
161 | list_for_each_entry(app, &aliases_lookup, link) { | ||
162 | if (dev->of_node == app->np) { | ||
163 | add_uevent_var(env, "OF_ALIAS_%d=%s", seen, | ||
164 | app->alias); | ||
165 | seen++; | ||
166 | } | ||
167 | } | ||
168 | mutex_unlock(&of_aliases_mutex); | ||
156 | } | 169 | } |
157 | 170 | ||
158 | int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | 171 | 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 000000000000..ff350c8fa7ac --- /dev/null +++ b/drivers/of/of_private.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _LINUX_OF_PRIVATE_H | ||
2 | #define _LINUX_OF_PRIVATE_H | ||
3 | /* | ||
4 | * Private symbols used by OF support code | ||
5 | * | ||
6 | * Paul Mackerras August 1996. | ||
7 | * Copyright (C) 1996-2005 Paul Mackerras. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | /** | ||
16 | * struct alias_prop - Alias property in 'aliases' node | ||
17 | * @link: List node to link the structure in aliases_lookup list | ||
18 | * @alias: Alias property name | ||
19 | * @np: Pointer to device_node that the alias stands for | ||
20 | * @id: Index value from end of alias name | ||
21 | * @stem: Alias string without the index | ||
22 | * | ||
23 | * The structure represents one alias property of 'aliases' node as | ||
24 | * an entry in aliases_lookup list. | ||
25 | */ | ||
26 | struct alias_prop { | ||
27 | struct list_head link; | ||
28 | const char *alias; | ||
29 | struct device_node *np; | ||
30 | int id; | ||
31 | char stem[0]; | ||
32 | }; | ||
33 | |||
34 | extern struct mutex of_aliases_mutex; | ||
35 | extern struct list_head aliases_lookup; | ||
36 | #endif /* _LINUX_OF_PRIVATE_H */ | ||
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index f24ffd7088d2..0eb5c38b4e07 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Self tests for device tree subsystem | 2 | * Self tests for device tree subsystem |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #define pr_fmt(fmt) "### %s(): " fmt, __func__ | 5 | #define pr_fmt(fmt) "### dt-test ### " fmt |
6 | 6 | ||
7 | #include <linux/clk.h> | 7 | #include <linux/clk.h> |
8 | #include <linux/err.h> | 8 | #include <linux/err.h> |
@@ -16,26 +16,30 @@ | |||
16 | 16 | ||
17 | static bool selftest_passed = true; | 17 | static bool selftest_passed = true; |
18 | #define selftest(result, fmt, ...) { \ | 18 | #define selftest(result, fmt, ...) { \ |
19 | selftest_passed &= (result); \ | 19 | if (!(result)) { \ |
20 | if (!(result)) \ | ||
21 | pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ | 20 | pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ |
21 | selftest_passed = false; \ | ||
22 | } else { \ | ||
23 | pr_info("pass %s:%i\n", __FILE__, __LINE__); \ | ||
24 | } \ | ||
22 | } | 25 | } |
23 | 26 | ||
24 | static void __init of_selftest_parse_phandle_with_args(void) | 27 | static void __init of_selftest_parse_phandle_with_args(void) |
25 | { | 28 | { |
26 | struct device_node *np; | 29 | struct device_node *np; |
27 | struct of_phandle_args args; | 30 | struct of_phandle_args args; |
28 | int rc, i; | 31 | int i, rc; |
29 | bool passed_all = true; | ||
30 | 32 | ||
31 | pr_info("start\n"); | ||
32 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); | 33 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); |
33 | if (!np) { | 34 | if (!np) { |
34 | pr_err("missing testcase data\n"); | 35 | pr_err("missing testcase data\n"); |
35 | return; | 36 | return; |
36 | } | 37 | } |
37 | 38 | ||
38 | for (i = 0; i < 7; i++) { | 39 | rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells"); |
40 | selftest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc); | ||
41 | |||
42 | for (i = 0; i < 8; i++) { | ||
39 | bool passed = true; | 43 | bool passed = true; |
40 | rc = of_parse_phandle_with_args(np, "phandle-list", | 44 | rc = of_parse_phandle_with_args(np, "phandle-list", |
41 | "#phandle-cells", i, &args); | 45 | "#phandle-cells", i, &args); |
@@ -79,45 +83,47 @@ static void __init of_selftest_parse_phandle_with_args(void) | |||
79 | passed &= (args.args[0] == (i + 1)); | 83 | passed &= (args.args[0] == (i + 1)); |
80 | break; | 84 | break; |
81 | case 7: | 85 | case 7: |
82 | passed &= (rc == -EINVAL); | 86 | passed &= (rc == -ENOENT); |
83 | break; | 87 | break; |
84 | default: | 88 | default: |
85 | passed = false; | 89 | passed = false; |
86 | } | 90 | } |
87 | 91 | ||
88 | if (!passed) { | 92 | selftest(passed, "index %i - data error on node %s rc=%i\n", |
89 | int j; | 93 | i, args.np->full_name, rc); |
90 | pr_err("index %i - data error on node %s rc=%i regs=[", | ||
91 | i, args.np->full_name, rc); | ||
92 | for (j = 0; j < args.args_count; j++) | ||
93 | printk(" %i", args.args[j]); | ||
94 | printk(" ]\n"); | ||
95 | |||
96 | passed_all = false; | ||
97 | } | ||
98 | } | 94 | } |
99 | 95 | ||
100 | /* Check for missing list property */ | 96 | /* Check for missing list property */ |
101 | rc = of_parse_phandle_with_args(np, "phandle-list-missing", | 97 | rc = of_parse_phandle_with_args(np, "phandle-list-missing", |
102 | "#phandle-cells", 0, &args); | 98 | "#phandle-cells", 0, &args); |
103 | passed_all &= (rc == -EINVAL); | 99 | selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); |
100 | rc = of_count_phandle_with_args(np, "phandle-list-missing", | ||
101 | "#phandle-cells"); | ||
102 | selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); | ||
104 | 103 | ||
105 | /* Check for missing cells property */ | 104 | /* Check for missing cells property */ |
106 | rc = of_parse_phandle_with_args(np, "phandle-list", | 105 | rc = of_parse_phandle_with_args(np, "phandle-list", |
107 | "#phandle-cells-missing", 0, &args); | 106 | "#phandle-cells-missing", 0, &args); |
108 | passed_all &= (rc == -EINVAL); | 107 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); |
108 | rc = of_count_phandle_with_args(np, "phandle-list", | ||
109 | "#phandle-cells-missing"); | ||
110 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | ||
109 | 111 | ||
110 | /* Check for bad phandle in list */ | 112 | /* Check for bad phandle in list */ |
111 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", | 113 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", |
112 | "#phandle-cells", 0, &args); | 114 | "#phandle-cells", 0, &args); |
113 | passed_all &= (rc == -EINVAL); | 115 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); |
116 | rc = of_count_phandle_with_args(np, "phandle-list-bad-phandle", | ||
117 | "#phandle-cells"); | ||
118 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | ||
114 | 119 | ||
115 | /* Check for incorrectly formed argument list */ | 120 | /* Check for incorrectly formed argument list */ |
116 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", | 121 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", |
117 | "#phandle-cells", 1, &args); | 122 | "#phandle-cells", 1, &args); |
118 | passed_all &= (rc == -EINVAL); | 123 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); |
119 | 124 | rc = of_count_phandle_with_args(np, "phandle-list-bad-args", | |
120 | pr_info("end - %s\n", passed_all ? "PASS" : "FAIL"); | 125 | "#phandle-cells"); |
126 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | ||
121 | } | 127 | } |
122 | 128 | ||
123 | static void __init of_selftest_property_match_string(void) | 129 | static void __init of_selftest_property_match_string(void) |
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 1a7f6359d998..086a9eef2e05 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) | |||
947 | struct device_node *np = dev->of_node; | 947 | struct device_node *np = dev->of_node; |
948 | struct fsl_spi_platform_data *pdata = dev->platform_data; | 948 | struct fsl_spi_platform_data *pdata = dev->platform_data; |
949 | struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); | 949 | struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); |
950 | unsigned int ngpios; | 950 | int ngpios; |
951 | int i = 0; | 951 | int i = 0; |
952 | int ret; | 952 | int ret; |
953 | 953 | ||
954 | ngpios = of_gpio_count(np); | 954 | ngpios = of_gpio_count(np); |
955 | if (!ngpios) { | 955 | if (ngpios <= 0) { |
956 | /* | 956 | /* |
957 | * SPI w/o chip-select line. One SPI device is still permitted | 957 | * SPI w/o chip-select line. One SPI device is still permitted |
958 | * though. | 958 | * though. |
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index 432e66ec3088..cb2e284bd814 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c | |||
@@ -54,7 +54,7 @@ struct tiny_spi { | |||
54 | unsigned int txc, rxc; | 54 | unsigned int txc, rxc; |
55 | const u8 *txp; | 55 | const u8 *txp; |
56 | u8 *rxp; | 56 | u8 *rxp; |
57 | unsigned int gpio_cs_count; | 57 | int gpio_cs_count; |
58 | int *gpio_cs; | 58 | int *gpio_cs; |
59 | }; | 59 | }; |
60 | 60 | ||
@@ -74,7 +74,7 @@ static void tiny_spi_chipselect(struct spi_device *spi, int is_active) | |||
74 | { | 74 | { |
75 | struct tiny_spi *hw = tiny_spi_to_hw(spi); | 75 | struct tiny_spi *hw = tiny_spi_to_hw(spi); |
76 | 76 | ||
77 | if (hw->gpio_cs_count) { | 77 | if (hw->gpio_cs_count > 0) { |
78 | gpio_set_value(hw->gpio_cs[spi->chip_select], | 78 | gpio_set_value(hw->gpio_cs[spi->chip_select], |
79 | (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); | 79 | (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); |
80 | } | 80 | } |
@@ -254,7 +254,7 @@ static int tiny_spi_of_probe(struct platform_device *pdev) | |||
254 | if (!np) | 254 | if (!np) |
255 | return 0; | 255 | return 0; |
256 | hw->gpio_cs_count = of_gpio_count(np); | 256 | hw->gpio_cs_count = of_gpio_count(np); |
257 | if (hw->gpio_cs_count) { | 257 | if (hw->gpio_cs_count > 0) { |
258 | hw->gpio_cs = devm_kzalloc(&pdev->dev, | 258 | hw->gpio_cs = devm_kzalloc(&pdev->dev, |
259 | hw->gpio_cs_count * sizeof(unsigned int), | 259 | hw->gpio_cs_count * sizeof(unsigned int), |
260 | GFP_KERNEL); | 260 | GFP_KERNEL); |
@@ -352,7 +352,7 @@ static int tiny_spi_probe(struct platform_device *pdev) | |||
352 | goto exit_gpio; | 352 | goto exit_gpio; |
353 | gpio_direction_output(hw->gpio_cs[i], 1); | 353 | gpio_direction_output(hw->gpio_cs[i], 1); |
354 | } | 354 | } |
355 | hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count); | 355 | hw->bitbang.master->num_chipselect = max(1, hw->gpio_cs_count); |
356 | 356 | ||
357 | /* register our spi controller */ | 357 | /* register our spi controller */ |
358 | err = spi_bitbang_start(&hw->bitbang); | 358 | err = spi_bitbang_start(&hw->bitbang); |
diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index 424b333fab18..357f183a4fb7 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c | |||
@@ -419,7 +419,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) | |||
419 | * This includes both "null" gpio's and real ones. | 419 | * This includes both "null" gpio's and real ones. |
420 | */ | 420 | */ |
421 | num_gpios = of_gpio_count(np); | 421 | num_gpios = of_gpio_count(np); |
422 | if (num_gpios) { | 422 | if (num_gpios > 0) { |
423 | int i; | 423 | int i; |
424 | 424 | ||
425 | hw->gpios = kzalloc(sizeof(int) * num_gpios, GFP_KERNEL); | 425 | hw->gpios = kzalloc(sizeof(int) * num_gpios, GFP_KERNEL); |
@@ -471,7 +471,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) | |||
471 | SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST; | 471 | SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST; |
472 | 472 | ||
473 | /* this many pins in all GPIO controllers */ | 473 | /* this many pins in all GPIO controllers */ |
474 | bbp->master->num_chipselect = num_gpios; | 474 | bbp->master->num_chipselect = num_gpios > 0 ? num_gpios : 0; |
475 | 475 | ||
476 | /* Get the clock for the OPB */ | 476 | /* Get the clock for the OPB */ |
477 | opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb"); | 477 | opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb"); |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 4fffb1f39def..6f193b02a9e8 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -1059,15 +1059,14 @@ EXPORT_SYMBOL_GPL(spi_alloc_master); | |||
1059 | #ifdef CONFIG_OF | 1059 | #ifdef CONFIG_OF |
1060 | static int of_spi_register_master(struct spi_master *master) | 1060 | static int of_spi_register_master(struct spi_master *master) |
1061 | { | 1061 | { |
1062 | u16 nb; | 1062 | int nb, i, *cs; |
1063 | int i, *cs; | ||
1064 | struct device_node *np = master->dev.of_node; | 1063 | struct device_node *np = master->dev.of_node; |
1065 | 1064 | ||
1066 | if (!np) | 1065 | if (!np) |
1067 | return 0; | 1066 | return 0; |
1068 | 1067 | ||
1069 | nb = of_gpio_named_count(np, "cs-gpios"); | 1068 | nb = of_gpio_named_count(np, "cs-gpios"); |
1070 | master->num_chipselect = max(nb, master->num_chipselect); | 1069 | master->num_chipselect = max(nb, (int)master->num_chipselect); |
1071 | 1070 | ||
1072 | if (nb < 1) | 1071 | if (nb < 1) |
1073 | return 0; | 1072 | return 0; |