platform.c 19.3 KB
Newer Older
S
Stephen Rothwell 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
 *			 <benh@kernel.crashing.org>
 *    and		 Arnd Bergmann, IBM Corp.
 *    Merged from powerpc/kernel/of_platform.c and
 *    sparc{,64}/kernel/of_device.c by Stephen Rothwell
 *
 *  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.
 *
 */
14 15 16

#define pr_fmt(fmt)	"OF: " fmt

S
Stephen Rothwell 已提交
17
#include <linux/errno.h>
18
#include <linux/module.h>
19
#include <linux/amba/bus.h>
S
Stephen Rothwell 已提交
20
#include <linux/device.h>
21
#include <linux/dma-mapping.h>
G
Grant Likely 已提交
22
#include <linux/slab.h>
23
#include <linux/of_address.h>
S
Stephen Rothwell 已提交
24
#include <linux/of_device.h>
25
#include <linux/of_iommu.h>
26
#include <linux/of_irq.h>
S
Stephen Rothwell 已提交
27
#include <linux/of_platform.h>
28 29
#include <linux/platform_device.h>

30 31
const struct of_device_id of_default_bus_match_table[] = {
	{ .compatible = "simple-bus", },
32
	{ .compatible = "simple-mfd", },
33
	{ .compatible = "isa", },
34 35 36 37 38 39
#ifdef CONFIG_ARM_AMBA
	{ .compatible = "arm,amba-bus", },
#endif /* CONFIG_ARM_AMBA */
	{} /* Empty terminated list */
};

40 41 42 43 44 45 46 47 48
static int of_dev_node_match(struct device *dev, void *data)
{
	return dev->of_node == data;
}

/**
 * of_find_device_by_node - Find the platform_device associated with a node
 * @np: Pointer to device tree node
 *
49 50 51
 * Takes a reference to the embedded struct device which needs to be dropped
 * after use.
 *
52 53 54 55 56 57 58 59 60 61 62
 * Returns platform_device pointer, or NULL if not found
 */
struct platform_device *of_find_device_by_node(struct device_node *np)
{
	struct device *dev;

	dev = bus_find_device(&platform_bus_type, NULL, np, of_dev_node_match);
	return dev ? to_platform_device(dev) : NULL;
}
EXPORT_SYMBOL(of_find_device_by_node);

63
#ifdef CONFIG_OF_ADDRESS
64 65 66 67 68 69 70 71
/*
 * The following routines scan a subtree and registers a device for
 * each applicable node.
 *
 * Note: sparc doesn't use these routines because it has a different
 * mechanism for creating devices from device tree nodes.
 */

72 73 74 75
/**
 * of_device_make_bus_id - Use the device node data to assign a unique name
 * @dev: pointer to device structure that is linked to a device tree node
 *
76 77 78
 * This routine will first try using the translated bus address to
 * derive a unique name. If it cannot, then it will prepend names from
 * parent nodes until a unique name can be derived.
79
 */
80
static void of_device_make_bus_id(struct device *dev)
81 82
{
	struct device_node *node = dev->of_node;
K
Kim Phillips 已提交
83
	const __be32 *reg;
84 85
	u64 addr;

86 87 88 89 90 91 92 93 94 95 96
	/* Construct the name, using parent nodes if necessary to ensure uniqueness */
	while (node->parent) {
		/*
		 * If the address can be translated, then that is as much
		 * uniqueness as we need. Make it the first component and return
		 */
		reg = of_get_property(node, "reg", NULL);
		if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) {
			dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s",
				     (unsigned long long)addr, node->name,
				     dev_name(dev));
97 98 99
			return;
		}

100 101
		/* format arguments only used if dev_name() resolves to NULL */
		dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s",
102
			     kbasename(node->full_name), dev_name(dev));
103 104
		node = node->parent;
	}
105 106 107 108 109 110 111 112
}

/**
 * of_device_alloc - Allocate and initialize an of_device
 * @np: device node to assign to device
 * @bus_id: Name to assign to the device.  May be null to use default name.
 * @parent: Parent device.
 */
113
struct platform_device *of_device_alloc(struct device_node *np,
114 115 116
				  const char *bus_id,
				  struct device *parent)
{
117
	struct platform_device *dev;
118
	int rc, i, num_reg = 0, num_irq;
119 120
	struct resource *res, temp_res;

121
	dev = platform_device_alloc("", PLATFORM_DEVID_NONE);
122 123 124 125
	if (!dev)
		return NULL;

	/* count the io and irq resources */
126 127
	while (of_address_to_resource(np, num_reg, &temp_res) == 0)
		num_reg++;
128
	num_irq = of_irq_count(np);
129 130 131

	/* Populate the resource table */
	if (num_irq || num_reg) {
132 133 134 135 136 137
		res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
		if (!res) {
			platform_device_put(dev);
			return NULL;
		}

138 139 140 141 142 143
		dev->num_resources = num_reg + num_irq;
		dev->resource = res;
		for (i = 0; i < num_reg; i++, res++) {
			rc = of_address_to_resource(np, i, res);
			WARN_ON(rc);
		}
144 145 146
		if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
			pr_debug("not all legacy IRQ resources mapped for %s\n",
				 np->name);
147
	}
148 149

	dev->dev.of_node = of_node_get(np);
150
	dev->dev.fwnode = &np->fwnode;
151
	dev->dev.parent = parent ? : &platform_bus;
152 153 154 155 156 157 158 159 160 161

	if (bus_id)
		dev_set_name(&dev->dev, "%s", bus_id);
	else
		of_device_make_bus_id(&dev->dev);

	return dev;
}
EXPORT_SYMBOL(of_device_alloc);

162
/**
163
 * of_platform_device_create_pdata - Alloc, initialize and register an of_device
164 165
 * @np: pointer to node to create device for
 * @bus_id: name to assign device
166
 * @platform_data: pointer to populate platform_data pointer with
167
 * @parent: Linux device model parent device.
168 169 170
 *
 * Returns pointer to created platform device, or NULL if a device was not
 * registered.  Unavailable devices will not get registered.
171
 */
172
static struct platform_device *of_platform_device_create_pdata(
173 174 175 176
					struct device_node *np,
					const char *bus_id,
					void *platform_data,
					struct device *parent)
177
{
178
	struct platform_device *dev;
179

180 181
	if (!of_device_is_available(np) ||
	    of_node_test_and_set_flag(np, OF_POPULATED))
182 183
		return NULL;

184 185
	dev = of_device_alloc(np, bus_id, parent);
	if (!dev)
186
		goto err_clear_flag;
187

188
	dev->dev.bus = &platform_bus_type;
189
	dev->dev.platform_data = platform_data;
190
	of_msi_configure(&dev->dev, dev->dev.of_node);
191

192 193
	if (of_device_add(dev) != 0) {
		platform_device_put(dev);
194
		goto err_clear_flag;
195 196 197
	}

	return dev;
198 199 200 201

err_clear_flag:
	of_node_clear_flag(np, OF_POPULATED);
	return NULL;
202
}
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

/**
 * of_platform_device_create - Alloc, initialize and register an of_device
 * @np: pointer to node to create device for
 * @bus_id: name to assign device
 * @parent: Linux device model parent device.
 *
 * Returns pointer to created platform device, or NULL if a device was not
 * registered.  Unavailable devices will not get registered.
 */
struct platform_device *of_platform_device_create(struct device_node *np,
					    const char *bus_id,
					    struct device *parent)
{
	return of_platform_device_create_pdata(np, bus_id, NULL, parent);
}
219 220
EXPORT_SYMBOL(of_platform_device_create);

221 222 223 224 225 226 227 228 229 230
#ifdef CONFIG_ARM_AMBA
static struct amba_device *of_amba_device_create(struct device_node *node,
						 const char *bus_id,
						 void *platform_data,
						 struct device *parent)
{
	struct amba_device *dev;
	const void *prop;
	int i, ret;

231
	pr_debug("Creating amba device %pOF\n", node);
232

233 234
	if (!of_device_is_available(node) ||
	    of_node_test_and_set_flag(node, OF_POPULATED))
235 236
		return NULL;

237
	dev = amba_device_alloc(NULL, 0, 0);
238
	if (!dev)
239
		goto err_clear_flag;
240 241 242

	/* setup generic device info */
	dev->dev.of_node = of_node_get(node);
243
	dev->dev.fwnode = &node->fwnode;
244
	dev->dev.parent = parent ? : &platform_bus;
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
	dev->dev.platform_data = platform_data;
	if (bus_id)
		dev_set_name(&dev->dev, "%s", bus_id);
	else
		of_device_make_bus_id(&dev->dev);

	/* Allow the HW Peripheral ID to be overridden */
	prop = of_get_property(node, "arm,primecell-periphid", NULL);
	if (prop)
		dev->periphid = of_read_ulong(prop, 1);

	/* Decode the IRQs and address ranges */
	for (i = 0; i < AMBA_NR_IRQS; i++)
		dev->irq[i] = irq_of_parse_and_map(node, i);

	ret = of_address_to_resource(node, 0, &dev->res);
261
	if (ret) {
262 263
		pr_err("amba: of_address_to_resource() failed (%d) for %pOF\n",
		       ret, node);
264
		goto err_free;
265
	}
266

267
	ret = amba_device_add(dev, &iomem_resource);
268
	if (ret) {
269 270
		pr_err("amba_device_add() failed (%d) for %pOF\n",
		       ret, node);
271
		goto err_free;
272
	}
273 274 275 276

	return dev;

err_free:
277
	amba_device_put(dev);
278 279
err_clear_flag:
	of_node_clear_flag(node, OF_POPULATED);
280 281 282 283 284 285 286 287 288 289 290 291
	return NULL;
}
#else /* CONFIG_ARM_AMBA */
static struct amba_device *of_amba_device_create(struct device_node *node,
						 const char *bus_id,
						 void *platform_data,
						 struct device *parent)
{
	return NULL;
}
#endif /* CONFIG_ARM_AMBA */

292 293 294 295 296 297
/**
 * of_devname_lookup() - Given a device node, lookup the preferred Linux name
 */
static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,
				 struct device_node *np)
{
298
	const struct of_dev_auxdata *auxdata;
299
	struct resource res;
300
	int compatible = 0;
O
Olof Johansson 已提交
301 302 303 304

	if (!lookup)
		return NULL;

305 306 307
	auxdata = lookup;
	for (; auxdata->compatible; auxdata++) {
		if (!of_device_is_compatible(np, auxdata->compatible))
O
Olof Johansson 已提交
308
			continue;
309
		compatible++;
310
		if (!of_address_to_resource(np, 0, &res))
311
			if (res.start != auxdata->phys_addr)
312
				continue;
313
		pr_debug("%pOF: devname=%s\n", np, auxdata->name);
314 315 316 317 318 319 320 321 322 323 324 325
		return auxdata;
	}

	if (!compatible)
		return NULL;

	/* Try compatible match if no phys_addr and name are specified */
	auxdata = lookup;
	for (; auxdata->compatible; auxdata++) {
		if (!of_device_is_compatible(np, auxdata->compatible))
			continue;
		if (!auxdata->phys_addr && !auxdata->name) {
326
			pr_debug("%pOF: compatible match\n", np);
327 328
			return auxdata;
		}
329
	}
O
Olof Johansson 已提交
330

331 332 333
	return NULL;
}

334
/**
335
 * of_platform_bus_create() - Create a device for a node and its children.
336
 * @bus: device node of the bus to instantiate
337
 * @matches: match table for bus nodes
O
Olof Johansson 已提交
338
 * @lookup: auxdata table for matching id and platform_data with device nodes
339
 * @parent: parent for new device, or NULL for top level.
O
Olof Johansson 已提交
340
 * @strict: require compatible property
341 342 343
 *
 * Creates a platform_device for the provided device_node, and optionally
 * recursively create devices for all the child nodes.
344
 */
345
static int of_platform_bus_create(struct device_node *bus,
346
				  const struct of_device_id *matches,
347
				  const struct of_dev_auxdata *lookup,
348
				  struct device *parent, bool strict)
349
{
350
	const struct of_dev_auxdata *auxdata;
351
	struct device_node *child;
352
	struct platform_device *dev;
353 354
	const char *bus_id = NULL;
	void *platform_data = NULL;
355 356
	int rc = 0;

357 358
	/* Make sure it has a compatible property */
	if (strict && (!of_get_property(bus, "compatible", NULL))) {
359 360
		pr_debug("%s() - skipping %pOF, no compatible prop\n",
			 __func__, bus);
361 362 363
		return 0;
	}

364
	if (of_node_check_flag(bus, OF_POPULATED_BUS)) {
365 366
		pr_debug("%s() - skipping %pOF, already populated\n",
			__func__, bus);
367 368 369
		return 0;
	}

370 371 372 373 374 375
	auxdata = of_dev_lookup(lookup, bus);
	if (auxdata) {
		bus_id = auxdata->name;
		platform_data = auxdata->platform_data;
	}

376
	if (of_device_is_compatible(bus, "arm,primecell")) {
377 378 379 380
		/*
		 * Don't return an error here to keep compatibility with older
		 * device tree files.
		 */
381
		of_amba_device_create(bus, bus_id, platform_data, parent);
382 383 384
		return 0;
	}

385
	dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
386 387 388
	if (!dev || !of_match_node(matches, bus))
		return 0;

389
	for_each_child_of_node(bus, child) {
390
		pr_debug("   create child: %pOF\n", child);
391
		rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
392 393 394 395 396
		if (rc) {
			of_node_put(child);
			break;
		}
	}
397
	of_node_set_flag(bus, OF_POPULATED_BUS);
398 399 400 401
	return rc;
}

/**
402
 * of_platform_bus_probe() - Probe the device-tree for platform buses
403
 * @root: parent of the first level to probe or NULL for the root of the tree
404
 * @matches: match table for bus nodes
405 406 407 408 409 410 411 412 413 414 415 416
 * @parent: parent to hook devices from, NULL for toplevel
 *
 * Note that children of the provided root are not instantiated as devices
 * unless the specified root itself matches the bus list and is not NULL.
 */
int of_platform_bus_probe(struct device_node *root,
			  const struct of_device_id *matches,
			  struct device *parent)
{
	struct device_node *child;
	int rc = 0;

417 418
	root = root ? of_node_get(root) : of_find_node_by_path("/");
	if (!root)
419
		return -EINVAL;
420

421
	pr_debug("%s()\n", __func__);
422
	pr_debug(" starting at: %pOF\n", root);
423

424
	/* Do a self check of bus type, if there's a match, create children */
425
	if (of_match_node(matches, root)) {
426
		rc = of_platform_bus_create(root, matches, NULL, parent, false);
427
	} else for_each_child_of_node(root, child) {
428 429
		if (!of_match_node(matches, child))
			continue;
430
		rc = of_platform_bus_create(child, matches, NULL, parent, false);
431 432
		if (rc) {
			of_node_put(child);
433
			break;
434
		}
435
	}
436

437 438 439 440
	of_node_put(root);
	return rc;
}
EXPORT_SYMBOL(of_platform_bus_probe);
441 442 443 444 445

/**
 * of_platform_populate() - Populate platform_devices from device tree data
 * @root: parent of the first level to probe or NULL for the root of the tree
 * @matches: match table, NULL to use the default
446
 * @lookup: auxdata table for matching id and platform_data with device nodes
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
 * @parent: parent to hook devices from, NULL for toplevel
 *
 * Similar to of_platform_bus_probe(), this function walks the device tree
 * and creates devices from nodes.  It differs in that it follows the modern
 * convention of requiring all device nodes to have a 'compatible' property,
 * and it is suitable for creating devices which are children of the root
 * node (of_platform_bus_probe will only create children of the root which
 * are selected by the @matches argument).
 *
 * New board support should be using this function instead of
 * of_platform_bus_probe().
 *
 * Returns 0 on success, < 0 on failure.
 */
int of_platform_populate(struct device_node *root,
			const struct of_device_id *matches,
463
			const struct of_dev_auxdata *lookup,
464 465 466 467 468 469 470 471 472
			struct device *parent)
{
	struct device_node *child;
	int rc = 0;

	root = root ? of_node_get(root) : of_find_node_by_path("/");
	if (!root)
		return -EINVAL;

473
	pr_debug("%s()\n", __func__);
474
	pr_debug(" starting at: %pOF\n", root);
475

476
	for_each_child_of_node(root, child) {
477
		rc = of_platform_bus_create(child, matches, lookup, parent, true);
478 479
		if (rc) {
			of_node_put(child);
480
			break;
481
		}
482
	}
483
	of_node_set_flag(root, OF_POPULATED_BUS);
484 485 486 487

	of_node_put(root);
	return rc;
}
488
EXPORT_SYMBOL_GPL(of_platform_populate);
489

490 491 492 493 494 495 496 497 498
int of_platform_default_populate(struct device_node *root,
				 const struct of_dev_auxdata *lookup,
				 struct device *parent)
{
	return of_platform_populate(root, of_default_bus_match_table, lookup,
				    parent);
}
EXPORT_SYMBOL_GPL(of_platform_default_populate);

499
#ifndef CONFIG_PPC
500
static const struct of_device_id reserved_mem_matches[] = {
501
	{ .compatible = "qcom,rmtfs-mem" },
502 503 504 505
	{ .compatible = "ramoops" },
	{}
};

506 507
static int __init of_platform_default_populate_init(void)
{
508 509 510 511 512 513
	struct device_node *node;

	if (!of_have_populated_dt())
		return -ENODEV;

	/*
514 515 516
	 * Handle certain compatibles explicitly, since we don't want to create
	 * platform_devices for every node in /reserved-memory with a
	 * "compatible",
517
	 */
518 519
	for_each_matching_node(node, reserved_mem_matches)
		of_platform_device_create(node, NULL, NULL);
520 521 522

	/* Populate everything else. */
	of_platform_default_populate(NULL, NULL, NULL);
523 524 525 526

	return 0;
}
arch_initcall_sync(of_platform_default_populate_init);
527
#endif
528

529
int of_platform_device_destroy(struct device *dev, void *data)
530 531
{
	/* Do not touch devices not populated from the device tree */
532
	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
533 534
		return 0;

535 536 537
	/* Recurse for any nodes that were treated as busses */
	if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
		device_for_each_child(dev, NULL, of_platform_device_destroy);
538 539 540 541 542 543 544 545 546

	if (dev->bus == &platform_bus_type)
		platform_device_unregister(to_platform_device(dev));
#ifdef CONFIG_ARM_AMBA
	else if (dev->bus == &amba_bustype)
		amba_device_unregister(to_amba_device(dev));
#endif

	of_node_clear_flag(dev->of_node, OF_POPULATED);
547
	of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
548 549
	return 0;
}
550
EXPORT_SYMBOL_GPL(of_platform_device_destroy);
551 552 553

/**
 * of_platform_depopulate() - Remove devices populated from device tree
554
 * @parent: device which children will be removed
555 556 557 558 559 560
 *
 * Complementary to of_platform_populate(), this function removes children
 * of the given device (and, recurrently, their children) that have been
 * created from their respective device tree nodes (and only those,
 * leaving others - eg. manually created - unharmed).
 */
561
void of_platform_depopulate(struct device *parent)
562
{
563 564 565 566
	if (parent->of_node && of_node_check_flag(parent->of_node, OF_POPULATED_BUS)) {
		device_for_each_child(parent, NULL, of_platform_device_destroy);
		of_node_clear_flag(parent->of_node, OF_POPULATED_BUS);
	}
567 568 569
}
EXPORT_SYMBOL_GPL(of_platform_depopulate);

570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
static void devm_of_platform_populate_release(struct device *dev, void *res)
{
	of_platform_depopulate(*(struct device **)res);
}

/**
 * devm_of_platform_populate() - Populate platform_devices from device tree data
 * @dev: device that requested to populate from device tree data
 *
 * Similar to of_platform_populate(), but will automatically call
 * of_platform_depopulate() when the device is unbound from the bus.
 *
 * Returns 0 on success, < 0 on failure.
 */
int devm_of_platform_populate(struct device *dev)
{
	struct device **ptr;
	int ret;

	if (!dev)
		return -EINVAL;

	ptr = devres_alloc(devm_of_platform_populate_release,
			   sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return -ENOMEM;

	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
	if (ret) {
		devres_free(ptr);
	} else {
		*ptr = dev;
		devres_add(dev, ptr);
	}

	return ret;
}
EXPORT_SYMBOL_GPL(devm_of_platform_populate);

static int devm_of_platform_match(struct device *dev, void *res, void *data)
{
	struct device **ptr = res;

	if (!ptr) {
		WARN_ON(!ptr);
		return 0;
	}

	return *ptr == data;
}

/**
 * devm_of_platform_depopulate() - Remove devices populated from device tree
 * @dev: device that requested to depopulate from device tree data
 *
 * Complementary to devm_of_platform_populate(), this function removes children
 * of the given device (and, recurrently, their children) that have been
 * created from their respective device tree nodes (and only those,
 * leaving others - eg. manually created - unharmed).
 */
void devm_of_platform_depopulate(struct device *dev)
{
	int ret;

	ret = devres_release(dev, devm_of_platform_populate_release,
			     devm_of_platform_match, dev);

	WARN_ON(ret);
}
EXPORT_SYMBOL_GPL(devm_of_platform_depopulate);

641 642 643 644 645 646 647 648 649 650 651 652 653 654
#ifdef CONFIG_OF_DYNAMIC
static int of_platform_notify(struct notifier_block *nb,
				unsigned long action, void *arg)
{
	struct of_reconfig_data *rd = arg;
	struct platform_device *pdev_parent, *pdev;
	bool children_left;

	switch (of_reconfig_get_state_change(action, rd)) {
	case OF_RECONFIG_CHANGE_ADD:
		/* verify that the parent is a bus */
		if (!of_node_check_flag(rd->dn->parent, OF_POPULATED_BUS))
			return NOTIFY_OK;	/* not for us */

655 656 657 658
		/* already populated? (driver using of_populate manually) */
		if (of_node_check_flag(rd->dn, OF_POPULATED))
			return NOTIFY_OK;

659 660 661 662 663 664 665
		/* pdev_parent may be NULL when no bus platform device */
		pdev_parent = of_find_device_by_node(rd->dn->parent);
		pdev = of_platform_device_create(rd->dn, NULL,
				pdev_parent ? &pdev_parent->dev : NULL);
		of_dev_put(pdev_parent);

		if (pdev == NULL) {
666 667
			pr_err("%s: failed to create for '%pOF'\n",
					__func__, rd->dn);
668 669 670 671 672 673
			/* of_platform_device_create tosses the error code */
			return notifier_from_errno(-EINVAL);
		}
		break;

	case OF_RECONFIG_CHANGE_REMOVE:
674 675 676 677 678

		/* already depopulated? */
		if (!of_node_check_flag(rd->dn, OF_POPULATED))
			return NOTIFY_OK;

679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
		/* find our device by node */
		pdev = of_find_device_by_node(rd->dn);
		if (pdev == NULL)
			return NOTIFY_OK;	/* no? not meant for us */

		/* unregister takes one ref away */
		of_platform_device_destroy(&pdev->dev, &children_left);

		/* and put the reference of the find */
		of_dev_put(pdev);
		break;
	}

	return NOTIFY_OK;
}

static struct notifier_block platform_of_notifier = {
	.notifier_call = of_platform_notify,
};

void of_platform_register_reconfig_notifier(void)
{
	WARN_ON(of_reconfig_notifier_register(&platform_of_notifier));
}
#endif /* CONFIG_OF_DYNAMIC */

705
#endif /* CONFIG_OF_ADDRESS */