xref: /rk3399_rockchip-uboot/drivers/core/device.c (revision 706865afe54eee83c1f3d7e9ea2f51db8e986d7b)
16494d708SSimon Glass /*
26494d708SSimon Glass  * Device manager
36494d708SSimon Glass  *
46494d708SSimon Glass  * Copyright (c) 2013 Google, Inc
56494d708SSimon Glass  *
66494d708SSimon Glass  * (C) Copyright 2012
76494d708SSimon Glass  * Pavel Herrmann <morpheus.ibis@gmail.com>
86494d708SSimon Glass  *
96494d708SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
106494d708SSimon Glass  */
116494d708SSimon Glass 
126494d708SSimon Glass #include <common.h>
137c616862SVignesh R #include <asm/io.h>
145a66a8ffSSimon Glass #include <fdtdec.h>
15ef5cd330SStefan Roese #include <fdt_support.h>
166494d708SSimon Glass #include <malloc.h>
176494d708SSimon Glass #include <dm/device.h>
186494d708SSimon Glass #include <dm/device-internal.h>
196494d708SSimon Glass #include <dm/lists.h>
20d90a5a30SMasahiro Yamada #include <dm/pinctrl.h>
216494d708SSimon Glass #include <dm/platdata.h>
226494d708SSimon Glass #include <dm/uclass.h>
236494d708SSimon Glass #include <dm/uclass-internal.h>
246494d708SSimon Glass #include <dm/util.h>
256494d708SSimon Glass #include <linux/err.h>
266494d708SSimon Glass #include <linux/list.h>
276494d708SSimon Glass 
285a66a8ffSSimon Glass DECLARE_GLOBAL_DATA_PTR;
295a66a8ffSSimon Glass 
30daac3bfeSStephen Warren static int device_bind_common(struct udevice *parent, const struct driver *drv,
31daac3bfeSStephen Warren 			      const char *name, void *platdata,
32daac3bfeSStephen Warren 			      ulong driver_data, int of_offset,
339fa28190SSimon Glass 			      uint of_platdata_size, struct udevice **devp)
346494d708SSimon Glass {
3554c5d08aSHeiko Schocher 	struct udevice *dev;
366494d708SSimon Glass 	struct uclass *uc;
375eaed880SPrzemyslaw Marczak 	int size, ret = 0;
386494d708SSimon Glass 
39e6cabe4aSMasahiro Yamada 	if (devp)
406494d708SSimon Glass 		*devp = NULL;
416494d708SSimon Glass 	if (!name)
426494d708SSimon Glass 		return -EINVAL;
436494d708SSimon Glass 
446494d708SSimon Glass 	ret = uclass_get(drv->id, &uc);
453346c876SSimon Glass 	if (ret) {
463346c876SSimon Glass 		debug("Missing uclass for driver %s\n", drv->name);
476494d708SSimon Glass 		return ret;
483346c876SSimon Glass 	}
496494d708SSimon Glass 
5054c5d08aSHeiko Schocher 	dev = calloc(1, sizeof(struct udevice));
516494d708SSimon Glass 	if (!dev)
526494d708SSimon Glass 		return -ENOMEM;
536494d708SSimon Glass 
546494d708SSimon Glass 	INIT_LIST_HEAD(&dev->sibling_node);
556494d708SSimon Glass 	INIT_LIST_HEAD(&dev->child_head);
566494d708SSimon Glass 	INIT_LIST_HEAD(&dev->uclass_node);
57e2282d70SMasahiro Yamada #ifdef CONFIG_DEVRES
58608f26c5SMasahiro Yamada 	INIT_LIST_HEAD(&dev->devres_head);
59e2282d70SMasahiro Yamada #endif
606494d708SSimon Glass 	dev->platdata = platdata;
61daac3bfeSStephen Warren 	dev->driver_data = driver_data;
626494d708SSimon Glass 	dev->name = name;
636494d708SSimon Glass 	dev->of_offset = of_offset;
646494d708SSimon Glass 	dev->parent = parent;
656494d708SSimon Glass 	dev->driver = drv;
666494d708SSimon Glass 	dev->uclass = uc;
675a66a8ffSSimon Glass 
685a66a8ffSSimon Glass 	dev->seq = -1;
6991cbd792SSimon Glass 	dev->req_seq = -1;
704f627c5aSNathan Rossi 	if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) {
719cc36a2bSSimon Glass 		/*
7236fa61dcSSimon Glass 		 * Some devices, such as a SPI bus, I2C bus and serial ports
7336fa61dcSSimon Glass 		 * are numbered using aliases.
749cc36a2bSSimon Glass 		 *
759cc36a2bSSimon Glass 		 * This is just a 'requested' sequence, and will be
769cc36a2bSSimon Glass 		 * resolved (and ->seq updated) when the device is probed.
779cc36a2bSSimon Glass 		 */
789cc36a2bSSimon Glass 		if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
799cc36a2bSSimon Glass 			if (uc->uc_drv->name && of_offset != -1) {
8036fa61dcSSimon Glass 				fdtdec_get_alias_seq(gd->fdt_blob,
8136fa61dcSSimon Glass 						uc->uc_drv->name, of_offset,
8236fa61dcSSimon Glass 						&dev->req_seq);
839cc36a2bSSimon Glass 			}
849cc36a2bSSimon Glass 		}
8536fa61dcSSimon Glass 	}
8636fa61dcSSimon Glass 
879fa28190SSimon Glass 	if (drv->platdata_auto_alloc_size) {
889fa28190SSimon Glass 		bool alloc = !platdata;
899fa28190SSimon Glass 
909fa28190SSimon Glass 		if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
919fa28190SSimon Glass 			if (of_platdata_size) {
929fa28190SSimon Glass 				dev->flags |= DM_FLAG_OF_PLATDATA;
939fa28190SSimon Glass 				if (of_platdata_size <
949fa28190SSimon Glass 						drv->platdata_auto_alloc_size)
959fa28190SSimon Glass 					alloc = true;
969fa28190SSimon Glass 			}
979fa28190SSimon Glass 		}
989fa28190SSimon Glass 		if (alloc) {
996494d708SSimon Glass 			dev->flags |= DM_FLAG_ALLOC_PDATA;
1009fa28190SSimon Glass 			dev->platdata = calloc(1,
1019fa28190SSimon Glass 					       drv->platdata_auto_alloc_size);
102f8a85449SSimon Glass 			if (!dev->platdata) {
103f8a85449SSimon Glass 				ret = -ENOMEM;
104f8a85449SSimon Glass 				goto fail_alloc1;
105f8a85449SSimon Glass 			}
1069fa28190SSimon Glass 			if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
1079fa28190SSimon Glass 				memcpy(dev->platdata, platdata,
1089fa28190SSimon Glass 				       of_platdata_size);
1099fa28190SSimon Glass 			}
1109fa28190SSimon Glass 		}
111f8a85449SSimon Glass 	}
112cdc133bdSSimon Glass 
1135eaed880SPrzemyslaw Marczak 	size = uc->uc_drv->per_device_platdata_auto_alloc_size;
1145eaed880SPrzemyslaw Marczak 	if (size) {
1155eaed880SPrzemyslaw Marczak 		dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
1165eaed880SPrzemyslaw Marczak 		dev->uclass_platdata = calloc(1, size);
1175eaed880SPrzemyslaw Marczak 		if (!dev->uclass_platdata) {
1185eaed880SPrzemyslaw Marczak 			ret = -ENOMEM;
1195eaed880SPrzemyslaw Marczak 			goto fail_alloc2;
1205eaed880SPrzemyslaw Marczak 		}
1215eaed880SPrzemyslaw Marczak 	}
1225eaed880SPrzemyslaw Marczak 
1235eaed880SPrzemyslaw Marczak 	if (parent) {
1245eaed880SPrzemyslaw Marczak 		size = parent->driver->per_child_platdata_auto_alloc_size;
125ba8da9dcSSimon Glass 		if (!size) {
126ba8da9dcSSimon Glass 			size = parent->uclass->uc_drv->
127ba8da9dcSSimon Glass 					per_child_platdata_auto_alloc_size;
128ba8da9dcSSimon Glass 		}
129cdc133bdSSimon Glass 		if (size) {
130cdc133bdSSimon Glass 			dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
131cdc133bdSSimon Glass 			dev->parent_platdata = calloc(1, size);
132cdc133bdSSimon Glass 			if (!dev->parent_platdata) {
133cdc133bdSSimon Glass 				ret = -ENOMEM;
1345eaed880SPrzemyslaw Marczak 				goto fail_alloc3;
135cdc133bdSSimon Glass 			}
136cdc133bdSSimon Glass 		}
137cdc133bdSSimon Glass 	}
1386494d708SSimon Glass 
1396494d708SSimon Glass 	/* put dev into parent's successor list */
1406494d708SSimon Glass 	if (parent)
1416494d708SSimon Glass 		list_add_tail(&dev->sibling_node, &parent->child_head);
1426494d708SSimon Glass 
1436494d708SSimon Glass 	ret = uclass_bind_device(dev);
1446494d708SSimon Glass 	if (ret)
14572ebfe86SSimon Glass 		goto fail_uclass_bind;
1466494d708SSimon Glass 
1476494d708SSimon Glass 	/* if we fail to bind we remove device from successors and free it */
1486494d708SSimon Glass 	if (drv->bind) {
1496494d708SSimon Glass 		ret = drv->bind(dev);
15072ebfe86SSimon Glass 		if (ret)
1516494d708SSimon Glass 			goto fail_bind;
1526494d708SSimon Glass 	}
1530118ce79SSimon Glass 	if (parent && parent->driver->child_post_bind) {
1540118ce79SSimon Glass 		ret = parent->driver->child_post_bind(dev);
1550118ce79SSimon Glass 		if (ret)
1560118ce79SSimon Glass 			goto fail_child_post_bind;
1570118ce79SSimon Glass 	}
15820af3c0aSSimon Glass 	if (uc->uc_drv->post_bind) {
15920af3c0aSSimon Glass 		ret = uc->uc_drv->post_bind(dev);
16020af3c0aSSimon Glass 		if (ret)
16120af3c0aSSimon Glass 			goto fail_uclass_post_bind;
16220af3c0aSSimon Glass 	}
1630118ce79SSimon Glass 
1646494d708SSimon Glass 	if (parent)
1656494d708SSimon Glass 		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
166e6cabe4aSMasahiro Yamada 	if (devp)
1676494d708SSimon Glass 		*devp = dev;
1686494d708SSimon Glass 
169aed1a4ddSMasahiro Yamada 	dev->flags |= DM_FLAG_BOUND;
170aed1a4ddSMasahiro Yamada 
1716494d708SSimon Glass 	return 0;
1726494d708SSimon Glass 
17320af3c0aSSimon Glass fail_uclass_post_bind:
17420af3c0aSSimon Glass 	/* There is no child unbind() method, so no clean-up required */
1750118ce79SSimon Glass fail_child_post_bind:
1760a5804b5SMasahiro Yamada 	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
1770118ce79SSimon Glass 		if (drv->unbind && drv->unbind(dev)) {
1780118ce79SSimon Glass 			dm_warn("unbind() method failed on dev '%s' on error path\n",
1790118ce79SSimon Glass 				dev->name);
1800118ce79SSimon Glass 		}
1815a87c417SSimon Glass 	}
1820118ce79SSimon Glass 
1836494d708SSimon Glass fail_bind:
1840a5804b5SMasahiro Yamada 	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
18572ebfe86SSimon Glass 		if (uclass_unbind_device(dev)) {
18672ebfe86SSimon Glass 			dm_warn("Failed to unbind dev '%s' on error path\n",
18772ebfe86SSimon Glass 				dev->name);
18872ebfe86SSimon Glass 		}
1895a87c417SSimon Glass 	}
19072ebfe86SSimon Glass fail_uclass_bind:
1910a5804b5SMasahiro Yamada 	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
1926494d708SSimon Glass 		list_del(&dev->sibling_node);
193cdc133bdSSimon Glass 		if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
194cdc133bdSSimon Glass 			free(dev->parent_platdata);
195cdc133bdSSimon Glass 			dev->parent_platdata = NULL;
196cdc133bdSSimon Glass 		}
1975a87c417SSimon Glass 	}
1985eaed880SPrzemyslaw Marczak fail_alloc3:
1995eaed880SPrzemyslaw Marczak 	if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
2005eaed880SPrzemyslaw Marczak 		free(dev->uclass_platdata);
2015eaed880SPrzemyslaw Marczak 		dev->uclass_platdata = NULL;
2025eaed880SPrzemyslaw Marczak 	}
203cdc133bdSSimon Glass fail_alloc2:
204f8a85449SSimon Glass 	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
205f8a85449SSimon Glass 		free(dev->platdata);
206f8a85449SSimon Glass 		dev->platdata = NULL;
207f8a85449SSimon Glass 	}
208f8a85449SSimon Glass fail_alloc1:
209608f26c5SMasahiro Yamada 	devres_release_all(dev);
210608f26c5SMasahiro Yamada 
2116494d708SSimon Glass 	free(dev);
21272ebfe86SSimon Glass 
2136494d708SSimon Glass 	return ret;
2146494d708SSimon Glass }
2156494d708SSimon Glass 
216daac3bfeSStephen Warren int device_bind_with_driver_data(struct udevice *parent,
217daac3bfeSStephen Warren 				 const struct driver *drv, const char *name,
218daac3bfeSStephen Warren 				 ulong driver_data, int of_offset,
219daac3bfeSStephen Warren 				 struct udevice **devp)
220daac3bfeSStephen Warren {
221daac3bfeSStephen Warren 	return device_bind_common(parent, drv, name, NULL, driver_data,
2229fa28190SSimon Glass 				  of_offset, 0, devp);
223daac3bfeSStephen Warren }
224daac3bfeSStephen Warren 
225daac3bfeSStephen Warren int device_bind(struct udevice *parent, const struct driver *drv,
226daac3bfeSStephen Warren 		const char *name, void *platdata, int of_offset,
227daac3bfeSStephen Warren 		struct udevice **devp)
228daac3bfeSStephen Warren {
2299fa28190SSimon Glass 	return device_bind_common(parent, drv, name, platdata, 0, of_offset, 0,
230daac3bfeSStephen Warren 				  devp);
231daac3bfeSStephen Warren }
232daac3bfeSStephen Warren 
23300606d7eSSimon Glass int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
23400606d7eSSimon Glass 			const struct driver_info *info, struct udevice **devp)
2356494d708SSimon Glass {
2366494d708SSimon Glass 	struct driver *drv;
2379fa28190SSimon Glass 	uint platdata_size = 0;
2386494d708SSimon Glass 
2396494d708SSimon Glass 	drv = lists_driver_lookup_name(info->name);
2406494d708SSimon Glass 	if (!drv)
2416494d708SSimon Glass 		return -ENOENT;
24200606d7eSSimon Glass 	if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
24300606d7eSSimon Glass 		return -EPERM;
2446494d708SSimon Glass 
2459fa28190SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
2469fa28190SSimon Glass 	platdata_size = info->platdata_size;
2479fa28190SSimon Glass #endif
2489fa28190SSimon Glass 	return device_bind_common(parent, drv, info->name,
2499fa28190SSimon Glass 			(void *)info->platdata, 0, -1, platdata_size, devp);
2506494d708SSimon Glass }
2516494d708SSimon Glass 
2522c03c463SSimon Glass static void *alloc_priv(int size, uint flags)
2532c03c463SSimon Glass {
2542c03c463SSimon Glass 	void *priv;
2552c03c463SSimon Glass 
2562c03c463SSimon Glass 	if (flags & DM_FLAG_ALLOC_PRIV_DMA) {
2572c03c463SSimon Glass 		priv = memalign(ARCH_DMA_MINALIGN, size);
2582c03c463SSimon Glass 		if (priv)
2592c03c463SSimon Glass 			memset(priv, '\0', size);
2602c03c463SSimon Glass 	} else {
2612c03c463SSimon Glass 		priv = calloc(1, size);
2622c03c463SSimon Glass 	}
2632c03c463SSimon Glass 
2642c03c463SSimon Glass 	return priv;
2652c03c463SSimon Glass }
2662c03c463SSimon Glass 
267c6db965fSSimon Glass int device_probe(struct udevice *dev)
2686494d708SSimon Glass {
2693479253dSSimon Glass 	const struct driver *drv;
2706494d708SSimon Glass 	int size = 0;
2716494d708SSimon Glass 	int ret;
2725a66a8ffSSimon Glass 	int seq;
2736494d708SSimon Glass 
2746494d708SSimon Glass 	if (!dev)
2756494d708SSimon Glass 		return -EINVAL;
2766494d708SSimon Glass 
2776494d708SSimon Glass 	if (dev->flags & DM_FLAG_ACTIVATED)
2786494d708SSimon Glass 		return 0;
2796494d708SSimon Glass 
2806494d708SSimon Glass 	drv = dev->driver;
2816494d708SSimon Glass 	assert(drv);
2826494d708SSimon Glass 
283cdeb2ba9SBin Meng 	/* Allocate private data if requested and not reentered */
284cdeb2ba9SBin Meng 	if (drv->priv_auto_alloc_size && !dev->priv) {
2852c03c463SSimon Glass 		dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags);
2866494d708SSimon Glass 		if (!dev->priv) {
2876494d708SSimon Glass 			ret = -ENOMEM;
2886494d708SSimon Glass 			goto fail;
2896494d708SSimon Glass 		}
2906494d708SSimon Glass 	}
291cdeb2ba9SBin Meng 	/* Allocate private data if requested and not reentered */
2926494d708SSimon Glass 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
293cdeb2ba9SBin Meng 	if (size && !dev->uclass_priv) {
2946494d708SSimon Glass 		dev->uclass_priv = calloc(1, size);
2956494d708SSimon Glass 		if (!dev->uclass_priv) {
2966494d708SSimon Glass 			ret = -ENOMEM;
2976494d708SSimon Glass 			goto fail;
2986494d708SSimon Glass 		}
2996494d708SSimon Glass 	}
3006494d708SSimon Glass 
3016494d708SSimon Glass 	/* Ensure all parents are probed */
3026494d708SSimon Glass 	if (dev->parent) {
303e59f458dSSimon Glass 		size = dev->parent->driver->per_child_auto_alloc_size;
304dac8db2cSSimon Glass 		if (!size) {
305dac8db2cSSimon Glass 			size = dev->parent->uclass->uc_drv->
306dac8db2cSSimon Glass 					per_child_auto_alloc_size;
307dac8db2cSSimon Glass 		}
308cdeb2ba9SBin Meng 		if (size && !dev->parent_priv) {
3092c03c463SSimon Glass 			dev->parent_priv = alloc_priv(size, drv->flags);
310e59f458dSSimon Glass 			if (!dev->parent_priv) {
311e59f458dSSimon Glass 				ret = -ENOMEM;
312e59f458dSSimon Glass 				goto fail;
313e59f458dSSimon Glass 			}
314e59f458dSSimon Glass 		}
315e59f458dSSimon Glass 
3166494d708SSimon Glass 		ret = device_probe(dev->parent);
3176494d708SSimon Glass 		if (ret)
3186494d708SSimon Glass 			goto fail;
319cdeb2ba9SBin Meng 
320cdeb2ba9SBin Meng 		/*
321cdeb2ba9SBin Meng 		 * The device might have already been probed during
322cdeb2ba9SBin Meng 		 * the call to device_probe() on its parent device
323cdeb2ba9SBin Meng 		 * (e.g. PCI bridge devices). Test the flags again
324cdeb2ba9SBin Meng 		 * so that we don't mess up the device.
325cdeb2ba9SBin Meng 		 */
326cdeb2ba9SBin Meng 		if (dev->flags & DM_FLAG_ACTIVATED)
327cdeb2ba9SBin Meng 			return 0;
3286494d708SSimon Glass 	}
3296494d708SSimon Glass 
3305a66a8ffSSimon Glass 	seq = uclass_resolve_seq(dev);
3315a66a8ffSSimon Glass 	if (seq < 0) {
3325a66a8ffSSimon Glass 		ret = seq;
3335a66a8ffSSimon Glass 		goto fail;
3345a66a8ffSSimon Glass 	}
3355a66a8ffSSimon Glass 	dev->seq = seq;
3365a66a8ffSSimon Glass 
337206d4d2bSSimon Glass 	dev->flags |= DM_FLAG_ACTIVATED;
338206d4d2bSSimon Glass 
33984d26e29SSimon Glass 	/*
34084d26e29SSimon Glass 	 * Process pinctrl for everything except the root device, and
3410379597eSSimon Glass 	 * continue regardless of the result of pinctrl. Don't process pinctrl
3420379597eSSimon Glass 	 * settings for pinctrl devices since the device may not yet be
3430379597eSSimon Glass 	 * probed.
34484d26e29SSimon Glass 	 */
3450379597eSSimon Glass 	if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
346d90a5a30SMasahiro Yamada 		pinctrl_select_state(dev, "default");
347d90a5a30SMasahiro Yamada 
34802c07b37SSimon Glass 	ret = uclass_pre_probe_device(dev);
34983c7e434SSimon Glass 	if (ret)
35083c7e434SSimon Glass 		goto fail;
35183c7e434SSimon Glass 
352a327dee0SSimon Glass 	if (dev->parent && dev->parent->driver->child_pre_probe) {
353a327dee0SSimon Glass 		ret = dev->parent->driver->child_pre_probe(dev);
354a327dee0SSimon Glass 		if (ret)
355a327dee0SSimon Glass 			goto fail;
356a327dee0SSimon Glass 	}
357a327dee0SSimon Glass 
358e160f7d4SSimon Glass 	if (drv->ofdata_to_platdata && dev_of_offset(dev) >= 0) {
3596494d708SSimon Glass 		ret = drv->ofdata_to_platdata(dev);
3606494d708SSimon Glass 		if (ret)
3616494d708SSimon Glass 			goto fail;
3626494d708SSimon Glass 	}
3636494d708SSimon Glass 
3646494d708SSimon Glass 	if (drv->probe) {
3656494d708SSimon Glass 		ret = drv->probe(dev);
36602eeb1bbSSimon Glass 		if (ret) {
36702eeb1bbSSimon Glass 			dev->flags &= ~DM_FLAG_ACTIVATED;
3686494d708SSimon Glass 			goto fail;
3696494d708SSimon Glass 		}
37002eeb1bbSSimon Glass 	}
3716494d708SSimon Glass 
3726494d708SSimon Glass 	ret = uclass_post_probe_device(dev);
373206d4d2bSSimon Glass 	if (ret)
3746494d708SSimon Glass 		goto fail_uclass;
3756494d708SSimon Glass 
376c3ab9853SPeng Fan 	if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL)
377c3ab9853SPeng Fan 		pinctrl_select_state(dev, "default");
378c3ab9853SPeng Fan 
3796494d708SSimon Glass 	return 0;
3806494d708SSimon Glass fail_uclass:
381*706865afSStefan Roese 	if (device_remove(dev, DM_REMOVE_NORMAL)) {
3826494d708SSimon Glass 		dm_warn("%s: Device '%s' failed to remove on error path\n",
3836494d708SSimon Glass 			__func__, dev->name);
3846494d708SSimon Glass 	}
3856494d708SSimon Glass fail:
386206d4d2bSSimon Glass 	dev->flags &= ~DM_FLAG_ACTIVATED;
387206d4d2bSSimon Glass 
3885a66a8ffSSimon Glass 	dev->seq = -1;
3896494d708SSimon Glass 	device_free(dev);
3906494d708SSimon Glass 
3916494d708SSimon Glass 	return ret;
3926494d708SSimon Glass }
3936494d708SSimon Glass 
39454c5d08aSHeiko Schocher void *dev_get_platdata(struct udevice *dev)
3956494d708SSimon Glass {
3966494d708SSimon Glass 	if (!dev) {
397964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
3986494d708SSimon Glass 		return NULL;
3996494d708SSimon Glass 	}
4006494d708SSimon Glass 
4016494d708SSimon Glass 	return dev->platdata;
4026494d708SSimon Glass }
4036494d708SSimon Glass 
404cdc133bdSSimon Glass void *dev_get_parent_platdata(struct udevice *dev)
405cdc133bdSSimon Glass {
406cdc133bdSSimon Glass 	if (!dev) {
40736d7cc17SSimon Glass 		dm_warn("%s: null device\n", __func__);
408cdc133bdSSimon Glass 		return NULL;
409cdc133bdSSimon Glass 	}
410cdc133bdSSimon Glass 
411cdc133bdSSimon Glass 	return dev->parent_platdata;
412cdc133bdSSimon Glass }
413cdc133bdSSimon Glass 
4145eaed880SPrzemyslaw Marczak void *dev_get_uclass_platdata(struct udevice *dev)
4155eaed880SPrzemyslaw Marczak {
4165eaed880SPrzemyslaw Marczak 	if (!dev) {
41736d7cc17SSimon Glass 		dm_warn("%s: null device\n", __func__);
4185eaed880SPrzemyslaw Marczak 		return NULL;
4195eaed880SPrzemyslaw Marczak 	}
4205eaed880SPrzemyslaw Marczak 
4215eaed880SPrzemyslaw Marczak 	return dev->uclass_platdata;
4225eaed880SPrzemyslaw Marczak }
4235eaed880SPrzemyslaw Marczak 
42454c5d08aSHeiko Schocher void *dev_get_priv(struct udevice *dev)
4256494d708SSimon Glass {
4266494d708SSimon Glass 	if (!dev) {
427964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
4286494d708SSimon Glass 		return NULL;
4296494d708SSimon Glass 	}
4306494d708SSimon Glass 
4316494d708SSimon Glass 	return dev->priv;
4326494d708SSimon Glass }
433997c87bbSSimon Glass 
434e564f054SSimon Glass void *dev_get_uclass_priv(struct udevice *dev)
435e564f054SSimon Glass {
436e564f054SSimon Glass 	if (!dev) {
437e564f054SSimon Glass 		dm_warn("%s: null device\n", __func__);
438e564f054SSimon Glass 		return NULL;
439e564f054SSimon Glass 	}
440e564f054SSimon Glass 
441e564f054SSimon Glass 	return dev->uclass_priv;
442e564f054SSimon Glass }
443e564f054SSimon Glass 
444bcbe3d15SSimon Glass void *dev_get_parent_priv(struct udevice *dev)
445e59f458dSSimon Glass {
446e59f458dSSimon Glass 	if (!dev) {
447964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
448e59f458dSSimon Glass 		return NULL;
449e59f458dSSimon Glass 	}
450e59f458dSSimon Glass 
451e59f458dSSimon Glass 	return dev->parent_priv;
452e59f458dSSimon Glass }
453e59f458dSSimon Glass 
454997c87bbSSimon Glass static int device_get_device_tail(struct udevice *dev, int ret,
455997c87bbSSimon Glass 				  struct udevice **devp)
456997c87bbSSimon Glass {
457997c87bbSSimon Glass 	if (ret)
458997c87bbSSimon Glass 		return ret;
459997c87bbSSimon Glass 
460997c87bbSSimon Glass 	ret = device_probe(dev);
461997c87bbSSimon Glass 	if (ret)
462997c87bbSSimon Glass 		return ret;
463997c87bbSSimon Glass 
464997c87bbSSimon Glass 	*devp = dev;
465997c87bbSSimon Glass 
466997c87bbSSimon Glass 	return 0;
467997c87bbSSimon Glass }
468997c87bbSSimon Glass 
469997c87bbSSimon Glass int device_get_child(struct udevice *parent, int index, struct udevice **devp)
470997c87bbSSimon Glass {
471997c87bbSSimon Glass 	struct udevice *dev;
472997c87bbSSimon Glass 
473997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
474997c87bbSSimon Glass 		if (!index--)
475997c87bbSSimon Glass 			return device_get_device_tail(dev, 0, devp);
476997c87bbSSimon Glass 	}
477997c87bbSSimon Glass 
478997c87bbSSimon Glass 	return -ENODEV;
479997c87bbSSimon Glass }
480997c87bbSSimon Glass 
481997c87bbSSimon Glass int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
482997c87bbSSimon Glass 			     bool find_req_seq, struct udevice **devp)
483997c87bbSSimon Glass {
484997c87bbSSimon Glass 	struct udevice *dev;
485997c87bbSSimon Glass 
486997c87bbSSimon Glass 	*devp = NULL;
487997c87bbSSimon Glass 	if (seq_or_req_seq == -1)
488997c87bbSSimon Glass 		return -ENODEV;
489997c87bbSSimon Glass 
490997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
491997c87bbSSimon Glass 		if ((find_req_seq ? dev->req_seq : dev->seq) ==
492997c87bbSSimon Glass 				seq_or_req_seq) {
493997c87bbSSimon Glass 			*devp = dev;
494997c87bbSSimon Glass 			return 0;
495997c87bbSSimon Glass 		}
496997c87bbSSimon Glass 	}
497997c87bbSSimon Glass 
498997c87bbSSimon Glass 	return -ENODEV;
499997c87bbSSimon Glass }
500997c87bbSSimon Glass 
501997c87bbSSimon Glass int device_get_child_by_seq(struct udevice *parent, int seq,
502997c87bbSSimon Glass 			    struct udevice **devp)
503997c87bbSSimon Glass {
504997c87bbSSimon Glass 	struct udevice *dev;
505997c87bbSSimon Glass 	int ret;
506997c87bbSSimon Glass 
507997c87bbSSimon Glass 	*devp = NULL;
508997c87bbSSimon Glass 	ret = device_find_child_by_seq(parent, seq, false, &dev);
509997c87bbSSimon Glass 	if (ret == -ENODEV) {
510997c87bbSSimon Glass 		/*
511997c87bbSSimon Glass 		 * We didn't find it in probed devices. See if there is one
512997c87bbSSimon Glass 		 * that will request this seq if probed.
513997c87bbSSimon Glass 		 */
514997c87bbSSimon Glass 		ret = device_find_child_by_seq(parent, seq, true, &dev);
515997c87bbSSimon Glass 	}
516997c87bbSSimon Glass 	return device_get_device_tail(dev, ret, devp);
517997c87bbSSimon Glass }
518997c87bbSSimon Glass 
519997c87bbSSimon Glass int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
520997c87bbSSimon Glass 				   struct udevice **devp)
521997c87bbSSimon Glass {
522997c87bbSSimon Glass 	struct udevice *dev;
523997c87bbSSimon Glass 
524997c87bbSSimon Glass 	*devp = NULL;
525997c87bbSSimon Glass 
526997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
527e160f7d4SSimon Glass 		if (dev_of_offset(dev) == of_offset) {
528997c87bbSSimon Glass 			*devp = dev;
529997c87bbSSimon Glass 			return 0;
530997c87bbSSimon Glass 		}
531997c87bbSSimon Glass 	}
532997c87bbSSimon Glass 
533997c87bbSSimon Glass 	return -ENODEV;
534997c87bbSSimon Glass }
535997c87bbSSimon Glass 
536132f9bfcSSimon Glass int device_get_child_by_of_offset(struct udevice *parent, int node,
537997c87bbSSimon Glass 				  struct udevice **devp)
538997c87bbSSimon Glass {
539997c87bbSSimon Glass 	struct udevice *dev;
540997c87bbSSimon Glass 	int ret;
541997c87bbSSimon Glass 
542997c87bbSSimon Glass 	*devp = NULL;
543132f9bfcSSimon Glass 	ret = device_find_child_by_of_offset(parent, node, &dev);
544997c87bbSSimon Glass 	return device_get_device_tail(dev, ret, devp);
545997c87bbSSimon Glass }
546a8981d4fSSimon Glass 
5472693047aSSimon Glass static struct udevice *_device_find_global_by_of_offset(struct udevice *parent,
5482693047aSSimon Glass 							int of_offset)
5492693047aSSimon Glass {
5502693047aSSimon Glass 	struct udevice *dev, *found;
5512693047aSSimon Glass 
552e160f7d4SSimon Glass 	if (dev_of_offset(parent) == of_offset)
5532693047aSSimon Glass 		return parent;
5542693047aSSimon Glass 
5552693047aSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
5562693047aSSimon Glass 		found = _device_find_global_by_of_offset(dev, of_offset);
5572693047aSSimon Glass 		if (found)
5582693047aSSimon Glass 			return found;
5592693047aSSimon Glass 	}
5602693047aSSimon Glass 
5612693047aSSimon Glass 	return NULL;
5622693047aSSimon Glass }
5632693047aSSimon Glass 
5642693047aSSimon Glass int device_get_global_by_of_offset(int of_offset, struct udevice **devp)
5652693047aSSimon Glass {
5662693047aSSimon Glass 	struct udevice *dev;
5672693047aSSimon Glass 
5682693047aSSimon Glass 	dev = _device_find_global_by_of_offset(gd->dm_root, of_offset);
5692693047aSSimon Glass 	return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
5702693047aSSimon Glass }
5712693047aSSimon Glass 
572a8981d4fSSimon Glass int device_find_first_child(struct udevice *parent, struct udevice **devp)
573a8981d4fSSimon Glass {
574a8981d4fSSimon Glass 	if (list_empty(&parent->child_head)) {
575a8981d4fSSimon Glass 		*devp = NULL;
576a8981d4fSSimon Glass 	} else {
577a8981d4fSSimon Glass 		*devp = list_first_entry(&parent->child_head, struct udevice,
578a8981d4fSSimon Glass 					 sibling_node);
579a8981d4fSSimon Glass 	}
580a8981d4fSSimon Glass 
581a8981d4fSSimon Glass 	return 0;
582a8981d4fSSimon Glass }
583a8981d4fSSimon Glass 
584a8981d4fSSimon Glass int device_find_next_child(struct udevice **devp)
585a8981d4fSSimon Glass {
586a8981d4fSSimon Glass 	struct udevice *dev = *devp;
587a8981d4fSSimon Glass 	struct udevice *parent = dev->parent;
588a8981d4fSSimon Glass 
589a8981d4fSSimon Glass 	if (list_is_last(&dev->sibling_node, &parent->child_head)) {
590a8981d4fSSimon Glass 		*devp = NULL;
591a8981d4fSSimon Glass 	} else {
592a8981d4fSSimon Glass 		*devp = list_entry(dev->sibling_node.next, struct udevice,
593a8981d4fSSimon Glass 				   sibling_node);
594a8981d4fSSimon Glass 	}
595a8981d4fSSimon Glass 
596a8981d4fSSimon Glass 	return 0;
597a8981d4fSSimon Glass }
5982ef249b4SSimon Glass 
599479728cbSSimon Glass struct udevice *dev_get_parent(struct udevice *child)
600479728cbSSimon Glass {
601479728cbSSimon Glass 	return child->parent;
602479728cbSSimon Glass }
603479728cbSSimon Glass 
60439de8433SSimon Glass ulong dev_get_driver_data(struct udevice *dev)
6052ef249b4SSimon Glass {
60639de8433SSimon Glass 	return dev->driver_data;
6072ef249b4SSimon Glass }
608b3670531SSimon Glass 
609cc73d37bSPrzemyslaw Marczak const void *dev_get_driver_ops(struct udevice *dev)
610cc73d37bSPrzemyslaw Marczak {
611cc73d37bSPrzemyslaw Marczak 	if (!dev || !dev->driver->ops)
612cc73d37bSPrzemyslaw Marczak 		return NULL;
613cc73d37bSPrzemyslaw Marczak 
614cc73d37bSPrzemyslaw Marczak 	return dev->driver->ops;
615cc73d37bSPrzemyslaw Marczak }
616cc73d37bSPrzemyslaw Marczak 
617b3670531SSimon Glass enum uclass_id device_get_uclass_id(struct udevice *dev)
618b3670531SSimon Glass {
619b3670531SSimon Glass 	return dev->uclass->uc_drv->id;
620b3670531SSimon Glass }
621c9cac3f8SPeng Fan 
622f9c370dcSPrzemyslaw Marczak const char *dev_get_uclass_name(struct udevice *dev)
623f9c370dcSPrzemyslaw Marczak {
624f9c370dcSPrzemyslaw Marczak 	if (!dev)
625f9c370dcSPrzemyslaw Marczak 		return NULL;
626f9c370dcSPrzemyslaw Marczak 
627f9c370dcSPrzemyslaw Marczak 	return dev->uclass->uc_drv->name;
628f9c370dcSPrzemyslaw Marczak }
629f9c370dcSPrzemyslaw Marczak 
63069b41388SMugunthan V N fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
631f3301771SSimon Glass {
63229629eb8SSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
633f3301771SSimon Glass 	fdt_addr_t addr;
634f3301771SSimon Glass 
635ef5cd330SStefan Roese 	if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
636ef5cd330SStefan Roese 		const fdt32_t *reg;
63769b41388SMugunthan V N 		int len = 0;
63869b41388SMugunthan V N 		int na, ns;
639ef5cd330SStefan Roese 
640e160f7d4SSimon Glass 		na = fdt_address_cells(gd->fdt_blob,
641e160f7d4SSimon Glass 				       dev_of_offset(dev->parent));
64269b41388SMugunthan V N 		if (na < 1) {
64369b41388SMugunthan V N 			debug("bad #address-cells\n");
644ef5cd330SStefan Roese 			return FDT_ADDR_T_NONE;
64569b41388SMugunthan V N 		}
64669b41388SMugunthan V N 
647e160f7d4SSimon Glass 		ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent));
64869b41388SMugunthan V N 		if (ns < 0) {
64969b41388SMugunthan V N 			debug("bad #size-cells\n");
65069b41388SMugunthan V N 			return FDT_ADDR_T_NONE;
65169b41388SMugunthan V N 		}
65269b41388SMugunthan V N 
653e160f7d4SSimon Glass 		reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg",
654e160f7d4SSimon Glass 				  &len);
65569b41388SMugunthan V N 		if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) {
65669b41388SMugunthan V N 			debug("Req index out of range\n");
65769b41388SMugunthan V N 			return FDT_ADDR_T_NONE;
65869b41388SMugunthan V N 		}
65969b41388SMugunthan V N 
66069b41388SMugunthan V N 		reg += index * (na + ns);
661ef5cd330SStefan Roese 
662ef5cd330SStefan Roese 		/*
663ef5cd330SStefan Roese 		 * Use the full-fledged translate function for complex
664ef5cd330SStefan Roese 		 * bus setups.
665ef5cd330SStefan Roese 		 */
66666eaea6cSStefan Roese 		addr = fdt_translate_address((void *)gd->fdt_blob,
667e160f7d4SSimon Glass 					     dev_of_offset(dev), reg);
66866eaea6cSStefan Roese 	} else {
669ef5cd330SStefan Roese 		/*
670ef5cd330SStefan Roese 		 * Use the "simple" translate function for less complex
671ef5cd330SStefan Roese 		 * bus setups.
672ef5cd330SStefan Roese 		 */
67302464e38SStephen Warren 		addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
674e160f7d4SSimon Glass 				dev_of_offset(dev->parent), dev_of_offset(dev),
675e160f7d4SSimon Glass 				"reg", index, NULL, false);
676628d792cSMarek Vasut 		if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
67766eaea6cSStefan Roese 			if (device_get_uclass_id(dev->parent) ==
67866eaea6cSStefan Roese 			    UCLASS_SIMPLE_BUS)
679f3301771SSimon Glass 				addr = simple_bus_translate(dev->parent, addr);
680c9cac3f8SPeng Fan 		}
68166eaea6cSStefan Roese 	}
68266eaea6cSStefan Roese 
68366eaea6cSStefan Roese 	/*
68466eaea6cSStefan Roese 	 * Some platforms need a special address translation. Those
68566eaea6cSStefan Roese 	 * platforms (e.g. mvebu in SPL) can configure a translation
68666eaea6cSStefan Roese 	 * offset in the DM by calling dm_set_translation_offset() that
68766eaea6cSStefan Roese 	 * will get added to all addresses returned by dev_get_addr().
68866eaea6cSStefan Roese 	 */
68966eaea6cSStefan Roese 	addr += dm_get_translation_offset();
690f3301771SSimon Glass 
691f3301771SSimon Glass 	return addr;
692c9cac3f8SPeng Fan #else
693c9cac3f8SPeng Fan 	return FDT_ADDR_T_NONE;
694c9cac3f8SPeng Fan #endif
695f3301771SSimon Glass }
696c5785673SSimon Glass 
69713f3fcacSStefan Roese fdt_addr_t dev_get_addr_size_index(struct udevice *dev, int index,
69813f3fcacSStefan Roese 				   fdt_size_t *size)
69913f3fcacSStefan Roese {
70013f3fcacSStefan Roese #if CONFIG_IS_ENABLED(OF_CONTROL)
70113f3fcacSStefan Roese 	/*
70213f3fcacSStefan Roese 	 * Only get the size in this first call. We'll get the addr in the
70313f3fcacSStefan Roese 	 * next call to the exisiting dev_get_xxx function which handles
70413f3fcacSStefan Roese 	 * all config options.
70513f3fcacSStefan Roese 	 */
706e160f7d4SSimon Glass 	fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev_of_offset(dev),
70713f3fcacSStefan Roese 					   "reg", index, size, false);
70813f3fcacSStefan Roese 
70913f3fcacSStefan Roese 	/*
71013f3fcacSStefan Roese 	 * Get the base address via the existing function which handles
71113f3fcacSStefan Roese 	 * all Kconfig cases
71213f3fcacSStefan Roese 	 */
71313f3fcacSStefan Roese 	return dev_get_addr_index(dev, index);
71413f3fcacSStefan Roese #else
71513f3fcacSStefan Roese 	return FDT_ADDR_T_NONE;
71613f3fcacSStefan Roese #endif
71713f3fcacSStefan Roese }
71813f3fcacSStefan Roese 
71943c4d44eSStephen Warren fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name)
72043c4d44eSStephen Warren {
72143c4d44eSStephen Warren #if CONFIG_IS_ENABLED(OF_CONTROL)
72243c4d44eSStephen Warren 	int index;
72343c4d44eSStephen Warren 
724e160f7d4SSimon Glass 	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
7256e67f176SMasahiro Yamada 				      "reg-names", name);
72643c4d44eSStephen Warren 	if (index < 0)
72743c4d44eSStephen Warren 		return index;
72843c4d44eSStephen Warren 
72943c4d44eSStephen Warren 	return dev_get_addr_index(dev, index);
73043c4d44eSStephen Warren #else
73143c4d44eSStephen Warren 	return FDT_ADDR_T_NONE;
73243c4d44eSStephen Warren #endif
73343c4d44eSStephen Warren }
73443c4d44eSStephen Warren 
73569b41388SMugunthan V N fdt_addr_t dev_get_addr(struct udevice *dev)
73669b41388SMugunthan V N {
73769b41388SMugunthan V N 	return dev_get_addr_index(dev, 0);
73869b41388SMugunthan V N }
73969b41388SMugunthan V N 
74028027521SStefan Roese void *dev_get_addr_ptr(struct udevice *dev)
74128027521SStefan Roese {
74228027521SStefan Roese 	return (void *)(uintptr_t)dev_get_addr_index(dev, 0);
74328027521SStefan Roese }
74428027521SStefan Roese 
7457c616862SVignesh R void *dev_map_physmem(struct udevice *dev, unsigned long size)
7467c616862SVignesh R {
7477c616862SVignesh R 	fdt_addr_t addr = dev_get_addr(dev);
7487c616862SVignesh R 
7497c616862SVignesh R 	if (addr == FDT_ADDR_T_NONE)
7507c616862SVignesh R 		return NULL;
7517c616862SVignesh R 
7527c616862SVignesh R 	return map_physmem(addr, size, MAP_NOCACHE);
7537c616862SVignesh R }
7547c616862SVignesh R 
755c5785673SSimon Glass bool device_has_children(struct udevice *dev)
756c5785673SSimon Glass {
757c5785673SSimon Glass 	return !list_empty(&dev->child_head);
758c5785673SSimon Glass }
759c5785673SSimon Glass 
760c5785673SSimon Glass bool device_has_active_children(struct udevice *dev)
761c5785673SSimon Glass {
762c5785673SSimon Glass 	struct udevice *child;
763c5785673SSimon Glass 
764c5785673SSimon Glass 	for (device_find_first_child(dev, &child);
765c5785673SSimon Glass 	     child;
766c5785673SSimon Glass 	     device_find_next_child(&child)) {
767c5785673SSimon Glass 		if (device_active(child))
768c5785673SSimon Glass 			return true;
769c5785673SSimon Glass 	}
770c5785673SSimon Glass 
771c5785673SSimon Glass 	return false;
772c5785673SSimon Glass }
773c5785673SSimon Glass 
774c5785673SSimon Glass bool device_is_last_sibling(struct udevice *dev)
775c5785673SSimon Glass {
776c5785673SSimon Glass 	struct udevice *parent = dev->parent;
777c5785673SSimon Glass 
778c5785673SSimon Glass 	if (!parent)
779c5785673SSimon Glass 		return false;
780c5785673SSimon Glass 	return list_is_last(&dev->sibling_node, &parent->child_head);
781c5785673SSimon Glass }
782f5c67ea0SSimon Glass 
783a2040facSSimon Glass void device_set_name_alloced(struct udevice *dev)
784a2040facSSimon Glass {
785fd1c2d9bSSimon Glass 	dev->flags |= DM_FLAG_NAME_ALLOCED;
786a2040facSSimon Glass }
787a2040facSSimon Glass 
788f5c67ea0SSimon Glass int device_set_name(struct udevice *dev, const char *name)
789f5c67ea0SSimon Glass {
790f5c67ea0SSimon Glass 	name = strdup(name);
791f5c67ea0SSimon Glass 	if (!name)
792f5c67ea0SSimon Glass 		return -ENOMEM;
793f5c67ea0SSimon Glass 	dev->name = name;
794a2040facSSimon Glass 	device_set_name_alloced(dev);
795f5c67ea0SSimon Glass 
796f5c67ea0SSimon Glass 	return 0;
797f5c67ea0SSimon Glass }
79873443b9eSMugunthan V N 
79973443b9eSMugunthan V N bool of_device_is_compatible(struct udevice *dev, const char *compat)
80073443b9eSMugunthan V N {
80173443b9eSMugunthan V N 	const void *fdt = gd->fdt_blob;
80273443b9eSMugunthan V N 
803e160f7d4SSimon Glass 	return !fdt_node_check_compatible(fdt, dev_of_offset(dev), compat);
80473443b9eSMugunthan V N }
80573443b9eSMugunthan V N 
80673443b9eSMugunthan V N bool of_machine_is_compatible(const char *compat)
80773443b9eSMugunthan V N {
80873443b9eSMugunthan V N 	const void *fdt = gd->fdt_blob;
80973443b9eSMugunthan V N 
81073443b9eSMugunthan V N 	return !fdt_node_check_compatible(fdt, 0, compat);
81173443b9eSMugunthan V N }
812