xref: /rk3399_rockchip-uboot/drivers/core/device.c (revision d9da4b44281a549e13a5f3a136d1ffc16cd52f57)
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>
140b2881acSPhilipp Tomsich #include <clk.h>
155a66a8ffSSimon Glass #include <fdtdec.h>
16ef5cd330SStefan Roese #include <fdt_support.h>
176494d708SSimon Glass #include <malloc.h>
186494d708SSimon Glass #include <dm/device.h>
196494d708SSimon Glass #include <dm/device-internal.h>
206494d708SSimon Glass #include <dm/lists.h>
2118aa8da9SMario Six #include <dm/of_access.h>
22d90a5a30SMasahiro Yamada #include <dm/pinctrl.h>
236494d708SSimon Glass #include <dm/platdata.h>
24396e343bSSimon Glass #include <dm/read.h>
256494d708SSimon Glass #include <dm/uclass.h>
266494d708SSimon Glass #include <dm/uclass-internal.h>
276494d708SSimon Glass #include <dm/util.h>
286494d708SSimon Glass #include <linux/err.h>
296494d708SSimon Glass #include <linux/list.h>
306494d708SSimon Glass 
315a66a8ffSSimon Glass DECLARE_GLOBAL_DATA_PTR;
325a66a8ffSSimon Glass 
33daac3bfeSStephen Warren static int device_bind_common(struct udevice *parent, const struct driver *drv,
34daac3bfeSStephen Warren 			      const char *name, void *platdata,
357a61b0b5SSimon Glass 			      ulong driver_data, ofnode node,
369fa28190SSimon Glass 			      uint of_platdata_size, struct udevice **devp)
376494d708SSimon Glass {
3854c5d08aSHeiko Schocher 	struct udevice *dev;
396494d708SSimon Glass 	struct uclass *uc;
40*d9da4b44SJoseph Chen 	bool after_u_boot_dev = true;
415eaed880SPrzemyslaw Marczak 	int size, ret = 0;
426494d708SSimon Glass 
43e6cabe4aSMasahiro Yamada 	if (devp)
446494d708SSimon Glass 		*devp = NULL;
456494d708SSimon Glass 	if (!name)
466494d708SSimon Glass 		return -EINVAL;
476494d708SSimon Glass 
486494d708SSimon Glass 	ret = uclass_get(drv->id, &uc);
493346c876SSimon Glass 	if (ret) {
503346c876SSimon Glass 		debug("Missing uclass for driver %s\n", drv->name);
516494d708SSimon Glass 		return ret;
523346c876SSimon Glass 	}
536494d708SSimon Glass 
54*d9da4b44SJoseph Chen #if defined(CONFIG_USING_KERNEL_DTB) && !defined(CONFIG_USING_KERNEL_DTB_V2)
55527e4be7SKever Yang 	if (gd->flags & GD_FLG_RELOC) {
56d24a078fSJoseph Chen 		/* For mmc/nand/spiflash, just update from kernel dtb instead bind again*/
57d24a078fSJoseph Chen 		if (drv->id == UCLASS_MMC || drv->id == UCLASS_RKNAND ||
5880907d3cSShawn Lin 		    drv->id == UCLASS_SPI_FLASH || drv->id == UCLASS_MTD ||
59e30e978dSYifeng Zhao 		    drv->id == UCLASS_PCI || drv->id == UCLASS_AHCI) {
6033273e09SJoseph Chen 			/*
6133273e09SJoseph Chen 			 * Reject all mmc device from kernel.
6233273e09SJoseph Chen 			 *
6333273e09SJoseph Chen 			 * - we always follow the rule: use mmc device from U-Boot
6433273e09SJoseph Chen 			 * - avoid alias id on defferent device between U-Boot and kernel
6533273e09SJoseph Chen 			 */
6633273e09SJoseph Chen 			if ((gd->flags & GD_FLG_KDTB_READY) &&
6733273e09SJoseph Chen 			     (drv->id == UCLASS_MMC))
6833273e09SJoseph Chen 				return 0;
6933273e09SJoseph Chen 
7089f947ecSKever Yang 			list_for_each_entry(dev, &uc->dev_head, uclass_node) {
7189f947ecSKever Yang 				if (!strcmp(name, dev->name)) {
7289f947ecSKever Yang 					debug("%s do not bind dev already in list %s\n",
73527e4be7SKever Yang 					      __func__, dev->name);
7430a85904SJoseph Chen 					/*
7530a85904SJoseph Chen 					 * There is no clearly reason for this
7630a85904SJoseph Chen 					 * legacy code, but remain it here since
7730a85904SJoseph Chen 					 * everything seems fine with or without
7830a85904SJoseph Chen 					 * this. Maybe removed in the future.
7930a85904SJoseph Chen 					 */
8089f947ecSKever Yang 					dev->node = node;
8189f947ecSKever Yang 					return 0;
8289f947ecSKever Yang 				}
8389f947ecSKever Yang 			}
84527e4be7SKever Yang 		}
85713d9646SFinley Xiao 
86527e4be7SKever Yang 		/* Use other nodes from kernel dtb */
87713d9646SFinley Xiao 		struct udevice *n;
88713d9646SFinley Xiao 
89713d9646SFinley Xiao 		list_for_each_entry_safe(dev, n, &uc->dev_head, uclass_node) {
90d7a244f9SJoseph Chen 			if (!strcmp(name, dev->name) &&
91930ceb12SJoseph Chen 			    (dev_read_bool(dev, "u-boot,dm-pre-reloc") ||
92930ceb12SJoseph Chen 			     dev_read_bool(dev, "u-boot,dm-spl"))) {
9330a85904SJoseph Chen 
94ef5a68b1SJoseph Chen 				/* Always use these node from U-Boot dtb */
95ef5a68b1SJoseph Chen 				if (drv->id == UCLASS_CRYPTO ||
96ef5a68b1SJoseph Chen 				    drv->id == UCLASS_WDT) {
97527e4be7SKever Yang 					debug("%s do not delete uboot dev: %s\n",
98527e4be7SKever Yang 					      __func__, dev->name);
99527e4be7SKever Yang 					return 0;
100527e4be7SKever Yang 				} else {
1018f5dfc4aSJoseph Chen 					list_del_init(&dev->uclass_node);
102713d9646SFinley Xiao 				}
103713d9646SFinley Xiao 			}
104527e4be7SKever Yang 		}
105527e4be7SKever Yang 	}
1065039ac47SKever Yang #endif
10754c5d08aSHeiko Schocher 	dev = calloc(1, sizeof(struct udevice));
1086494d708SSimon Glass 	if (!dev)
1096494d708SSimon Glass 		return -ENOMEM;
1106494d708SSimon Glass 
1116494d708SSimon Glass 	INIT_LIST_HEAD(&dev->sibling_node);
1126494d708SSimon Glass 	INIT_LIST_HEAD(&dev->child_head);
1136494d708SSimon Glass 	INIT_LIST_HEAD(&dev->uclass_node);
114e2282d70SMasahiro Yamada #ifdef CONFIG_DEVRES
115608f26c5SMasahiro Yamada 	INIT_LIST_HEAD(&dev->devres_head);
116e2282d70SMasahiro Yamada #endif
1176494d708SSimon Glass 	dev->platdata = platdata;
118daac3bfeSStephen Warren 	dev->driver_data = driver_data;
1196494d708SSimon Glass 	dev->name = name;
1207a61b0b5SSimon Glass 	dev->node = node;
1216494d708SSimon Glass 	dev->parent = parent;
1226494d708SSimon Glass 	dev->driver = drv;
1236494d708SSimon Glass 	dev->uclass = uc;
1245a66a8ffSSimon Glass 
1255a66a8ffSSimon Glass 	dev->seq = -1;
12691cbd792SSimon Glass 	dev->req_seq = -1;
1274f627c5aSNathan Rossi 	if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) {
1289cc36a2bSSimon Glass 		/*
12936fa61dcSSimon Glass 		 * Some devices, such as a SPI bus, I2C bus and serial ports
13036fa61dcSSimon Glass 		 * are numbered using aliases.
1319cc36a2bSSimon Glass 		 *
1329cc36a2bSSimon Glass 		 * This is just a 'requested' sequence, and will be
1339cc36a2bSSimon Glass 		 * resolved (and ->seq updated) when the device is probed.
1349cc36a2bSSimon Glass 		 */
1359cc36a2bSSimon Glass 		if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
1367a61b0b5SSimon Glass 			if (uc->uc_drv->name && ofnode_valid(node)) {
137396e343bSSimon Glass 				dev_read_alias_seq(dev, &dev->req_seq);
1389cc36a2bSSimon Glass 			}
1399cc36a2bSSimon Glass 		}
14036fa61dcSSimon Glass 	}
14136fa61dcSSimon Glass 
1429fa28190SSimon Glass 	if (drv->platdata_auto_alloc_size) {
1439fa28190SSimon Glass 		bool alloc = !platdata;
1449fa28190SSimon Glass 
1459fa28190SSimon Glass 		if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
1469fa28190SSimon Glass 			if (of_platdata_size) {
1479fa28190SSimon Glass 				dev->flags |= DM_FLAG_OF_PLATDATA;
1489fa28190SSimon Glass 				if (of_platdata_size <
1499fa28190SSimon Glass 						drv->platdata_auto_alloc_size)
1509fa28190SSimon Glass 					alloc = true;
1519fa28190SSimon Glass 			}
1529fa28190SSimon Glass 		}
1539fa28190SSimon Glass 		if (alloc) {
1546494d708SSimon Glass 			dev->flags |= DM_FLAG_ALLOC_PDATA;
1559fa28190SSimon Glass 			dev->platdata = calloc(1,
1569fa28190SSimon Glass 					       drv->platdata_auto_alloc_size);
157f8a85449SSimon Glass 			if (!dev->platdata) {
158f8a85449SSimon Glass 				ret = -ENOMEM;
159f8a85449SSimon Glass 				goto fail_alloc1;
160f8a85449SSimon Glass 			}
1619fa28190SSimon Glass 			if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
1629fa28190SSimon Glass 				memcpy(dev->platdata, platdata,
1639fa28190SSimon Glass 				       of_platdata_size);
1649fa28190SSimon Glass 			}
1659fa28190SSimon Glass 		}
166f8a85449SSimon Glass 	}
167cdc133bdSSimon Glass 
1685eaed880SPrzemyslaw Marczak 	size = uc->uc_drv->per_device_platdata_auto_alloc_size;
1695eaed880SPrzemyslaw Marczak 	if (size) {
1705eaed880SPrzemyslaw Marczak 		dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
1715eaed880SPrzemyslaw Marczak 		dev->uclass_platdata = calloc(1, size);
1725eaed880SPrzemyslaw Marczak 		if (!dev->uclass_platdata) {
1735eaed880SPrzemyslaw Marczak 			ret = -ENOMEM;
1745eaed880SPrzemyslaw Marczak 			goto fail_alloc2;
1755eaed880SPrzemyslaw Marczak 		}
1765eaed880SPrzemyslaw Marczak 	}
1775eaed880SPrzemyslaw Marczak 
1785eaed880SPrzemyslaw Marczak 	if (parent) {
1795eaed880SPrzemyslaw Marczak 		size = parent->driver->per_child_platdata_auto_alloc_size;
180ba8da9dcSSimon Glass 		if (!size) {
181ba8da9dcSSimon Glass 			size = parent->uclass->uc_drv->
182ba8da9dcSSimon Glass 					per_child_platdata_auto_alloc_size;
183ba8da9dcSSimon Glass 		}
184cdc133bdSSimon Glass 		if (size) {
185cdc133bdSSimon Glass 			dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
186cdc133bdSSimon Glass 			dev->parent_platdata = calloc(1, size);
187cdc133bdSSimon Glass 			if (!dev->parent_platdata) {
188cdc133bdSSimon Glass 				ret = -ENOMEM;
1895eaed880SPrzemyslaw Marczak 				goto fail_alloc3;
190cdc133bdSSimon Glass 			}
191cdc133bdSSimon Glass 		}
192cdc133bdSSimon Glass 	}
1936494d708SSimon Glass 
1946494d708SSimon Glass 	/* put dev into parent's successor list */
1956494d708SSimon Glass 	if (parent)
1966494d708SSimon Glass 		list_add_tail(&dev->sibling_node, &parent->child_head);
1976494d708SSimon Glass 
198*d9da4b44SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB
199*d9da4b44SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB_V2
200*d9da4b44SJoseph Chen 	/*
201*d9da4b44SJoseph Chen 	 * Put these U-Boot devices in the head of uclass device list for
202*d9da4b44SJoseph Chen 	 * the primary get by uclass_get_device_xxx().
203*d9da4b44SJoseph Chen 	 *
204*d9da4b44SJoseph Chen 	 * device-list: U0, U1, U2, ... K0, K1, K2, ... (prior u-boot dev)
205*d9da4b44SJoseph Chen 	 * device-list: K0, K1, K2, ... U0, U1, U2, ... (normal)
206*d9da4b44SJoseph Chen 	 *
207*d9da4b44SJoseph Chen 	 * U: u-boot dev
208*d9da4b44SJoseph Chen 	 * K: kernel dev
209*d9da4b44SJoseph Chen 	 */
210*d9da4b44SJoseph Chen 	u32 i, prior_u_boot_uclass_id[] = {
211*d9da4b44SJoseph Chen 		UCLASS_AHCI,		/* boot device */
212*d9da4b44SJoseph Chen 		UCLASS_BLK,
213*d9da4b44SJoseph Chen 		UCLASS_MMC,
214*d9da4b44SJoseph Chen 		UCLASS_MTD,
215*d9da4b44SJoseph Chen 		UCLASS_PCI,
216*d9da4b44SJoseph Chen 		UCLASS_RKNAND,
217*d9da4b44SJoseph Chen 		UCLASS_SPI_FLASH,
218*d9da4b44SJoseph Chen 
219*d9da4b44SJoseph Chen 		UCLASS_CRYPTO,		/* RSA security */
220*d9da4b44SJoseph Chen 		UCLASS_FIRMWARE,	/* psci sysreset */
221*d9da4b44SJoseph Chen 		UCLASS_RNG,		/* ramdom number */
222*d9da4b44SJoseph Chen 		UCLASS_SYSCON,		/* grf, pmugrf */
223*d9da4b44SJoseph Chen 		UCLASS_SYSRESET,	/* psci sysreset */
224*d9da4b44SJoseph Chen 		UCLASS_WDT,		/* reliable sysreset */
225*d9da4b44SJoseph Chen 	};
226*d9da4b44SJoseph Chen 
227*d9da4b44SJoseph Chen 	if (gd->flags & GD_FLG_KDTB_READY) {
228*d9da4b44SJoseph Chen 		after_u_boot_dev = false;
229*d9da4b44SJoseph Chen 		dev->flags |= DM_FLAG_KNRL_DTB;
230*d9da4b44SJoseph Chen 
231*d9da4b44SJoseph Chen 		for (i = 0; i < ARRAY_SIZE(prior_u_boot_uclass_id); i++) {
232*d9da4b44SJoseph Chen 			if (drv->id == prior_u_boot_uclass_id[i]) {
233*d9da4b44SJoseph Chen 				after_u_boot_dev = true;
234*d9da4b44SJoseph Chen 				break;
235*d9da4b44SJoseph Chen 			}
236*d9da4b44SJoseph Chen 		}
237*d9da4b44SJoseph Chen 
238*d9da4b44SJoseph Chen 		/* no u-boot dev ? */
239*d9da4b44SJoseph Chen 		if (!dev->uclass->u_boot_dev_head)
240*d9da4b44SJoseph Chen 			dev->uclass->u_boot_dev_head = &uc->dev_head;
241*d9da4b44SJoseph Chen 	} else {
242*d9da4b44SJoseph Chen 		if (!dev->uclass->u_boot_dev_head)
243*d9da4b44SJoseph Chen 			dev->uclass->u_boot_dev_head = &dev->uclass_node;
244*d9da4b44SJoseph Chen 	}
245*d9da4b44SJoseph Chen #else
246*d9da4b44SJoseph Chen 	if (gd->flags & GD_FLG_KDTB_READY)
247*d9da4b44SJoseph Chen 		dev->flags |= DM_FLAG_KNRL_DTB;
248*d9da4b44SJoseph Chen #endif
249*d9da4b44SJoseph Chen #endif
250*d9da4b44SJoseph Chen 	ret = uclass_bind_device(dev, after_u_boot_dev);
2516494d708SSimon Glass 	if (ret)
25272ebfe86SSimon Glass 		goto fail_uclass_bind;
2536494d708SSimon Glass 
2546494d708SSimon Glass 	/* if we fail to bind we remove device from successors and free it */
2556494d708SSimon Glass 	if (drv->bind) {
2566494d708SSimon Glass 		ret = drv->bind(dev);
25772ebfe86SSimon Glass 		if (ret)
2586494d708SSimon Glass 			goto fail_bind;
2596494d708SSimon Glass 	}
2600118ce79SSimon Glass 	if (parent && parent->driver->child_post_bind) {
2610118ce79SSimon Glass 		ret = parent->driver->child_post_bind(dev);
2620118ce79SSimon Glass 		if (ret)
2630118ce79SSimon Glass 			goto fail_child_post_bind;
2640118ce79SSimon Glass 	}
26520af3c0aSSimon Glass 	if (uc->uc_drv->post_bind) {
26620af3c0aSSimon Glass 		ret = uc->uc_drv->post_bind(dev);
26720af3c0aSSimon Glass 		if (ret)
26820af3c0aSSimon Glass 			goto fail_uclass_post_bind;
26920af3c0aSSimon Glass 	}
2700118ce79SSimon Glass 
2716494d708SSimon Glass 	if (parent)
272d42197e4SMasahiro Yamada 		pr_debug("Bound device %s to %s\n", dev->name, parent->name);
273e6cabe4aSMasahiro Yamada 	if (devp)
2746494d708SSimon Glass 		*devp = dev;
2756494d708SSimon Glass 
276aed1a4ddSMasahiro Yamada 	dev->flags |= DM_FLAG_BOUND;
277aed1a4ddSMasahiro Yamada 
2786494d708SSimon Glass 	return 0;
2796494d708SSimon Glass 
28020af3c0aSSimon Glass fail_uclass_post_bind:
28120af3c0aSSimon Glass 	/* There is no child unbind() method, so no clean-up required */
2820118ce79SSimon Glass fail_child_post_bind:
2830a5804b5SMasahiro Yamada 	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
2840118ce79SSimon Glass 		if (drv->unbind && drv->unbind(dev)) {
2850118ce79SSimon Glass 			dm_warn("unbind() method failed on dev '%s' on error path\n",
2860118ce79SSimon Glass 				dev->name);
2870118ce79SSimon Glass 		}
2885a87c417SSimon Glass 	}
2890118ce79SSimon Glass 
2906494d708SSimon Glass fail_bind:
2910a5804b5SMasahiro Yamada 	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
29272ebfe86SSimon Glass 		if (uclass_unbind_device(dev)) {
29372ebfe86SSimon Glass 			dm_warn("Failed to unbind dev '%s' on error path\n",
29472ebfe86SSimon Glass 				dev->name);
29572ebfe86SSimon Glass 		}
2965a87c417SSimon Glass 	}
29772ebfe86SSimon Glass fail_uclass_bind:
2980a5804b5SMasahiro Yamada 	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
2996494d708SSimon Glass 		list_del(&dev->sibling_node);
300cdc133bdSSimon Glass 		if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
301cdc133bdSSimon Glass 			free(dev->parent_platdata);
302cdc133bdSSimon Glass 			dev->parent_platdata = NULL;
303cdc133bdSSimon Glass 		}
3045a87c417SSimon Glass 	}
3055eaed880SPrzemyslaw Marczak fail_alloc3:
3065eaed880SPrzemyslaw Marczak 	if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
3075eaed880SPrzemyslaw Marczak 		free(dev->uclass_platdata);
3085eaed880SPrzemyslaw Marczak 		dev->uclass_platdata = NULL;
3095eaed880SPrzemyslaw Marczak 	}
310cdc133bdSSimon Glass fail_alloc2:
311f8a85449SSimon Glass 	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
312f8a85449SSimon Glass 		free(dev->platdata);
313f8a85449SSimon Glass 		dev->platdata = NULL;
314f8a85449SSimon Glass 	}
315f8a85449SSimon Glass fail_alloc1:
316608f26c5SMasahiro Yamada 	devres_release_all(dev);
317608f26c5SMasahiro Yamada 
3186494d708SSimon Glass 	free(dev);
31972ebfe86SSimon Glass 
3206494d708SSimon Glass 	return ret;
3216494d708SSimon Glass }
3226494d708SSimon Glass 
323daac3bfeSStephen Warren int device_bind_with_driver_data(struct udevice *parent,
324daac3bfeSStephen Warren 				 const struct driver *drv, const char *name,
325396e343bSSimon Glass 				 ulong driver_data, ofnode node,
326daac3bfeSStephen Warren 				 struct udevice **devp)
327daac3bfeSStephen Warren {
328396e343bSSimon Glass 	return device_bind_common(parent, drv, name, NULL, driver_data, node,
329396e343bSSimon Glass 				  0, devp);
330daac3bfeSStephen Warren }
331daac3bfeSStephen Warren 
332daac3bfeSStephen Warren int device_bind(struct udevice *parent, const struct driver *drv,
333daac3bfeSStephen Warren 		const char *name, void *platdata, int of_offset,
334daac3bfeSStephen Warren 		struct udevice **devp)
335daac3bfeSStephen Warren {
3367a61b0b5SSimon Glass 	return device_bind_common(parent, drv, name, platdata, 0,
3377a61b0b5SSimon Glass 				  offset_to_ofnode(of_offset), 0, devp);
338daac3bfeSStephen Warren }
339daac3bfeSStephen Warren 
34000606d7eSSimon Glass int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
34100606d7eSSimon Glass 			const struct driver_info *info, struct udevice **devp)
3426494d708SSimon Glass {
3436494d708SSimon Glass 	struct driver *drv;
3449fa28190SSimon Glass 	uint platdata_size = 0;
3456494d708SSimon Glass 
3466494d708SSimon Glass 	drv = lists_driver_lookup_name(info->name);
3476494d708SSimon Glass 	if (!drv)
3486494d708SSimon Glass 		return -ENOENT;
34900606d7eSSimon Glass 	if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
35000606d7eSSimon Glass 		return -EPERM;
3516494d708SSimon Glass 
3529fa28190SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
3539fa28190SSimon Glass 	platdata_size = info->platdata_size;
3549fa28190SSimon Glass #endif
3559fa28190SSimon Glass 	return device_bind_common(parent, drv, info->name,
356396e343bSSimon Glass 			(void *)info->platdata, 0, ofnode_null(), platdata_size,
357396e343bSSimon Glass 			devp);
3586494d708SSimon Glass }
3596494d708SSimon Glass 
3602c03c463SSimon Glass static void *alloc_priv(int size, uint flags)
3612c03c463SSimon Glass {
3622c03c463SSimon Glass 	void *priv;
3632c03c463SSimon Glass 
3642c03c463SSimon Glass 	if (flags & DM_FLAG_ALLOC_PRIV_DMA) {
3659ab2e5ebSFaiz Abbas 		size = ROUND(size, ARCH_DMA_MINALIGN);
3662c03c463SSimon Glass 		priv = memalign(ARCH_DMA_MINALIGN, size);
3675a8a8045SSimon Glass 		if (priv) {
3682c03c463SSimon Glass 			memset(priv, '\0', size);
3695a8a8045SSimon Glass 
3705a8a8045SSimon Glass 			/*
3715a8a8045SSimon Glass 			 * Ensure that the zero bytes are flushed to memory.
3725a8a8045SSimon Glass 			 * This prevents problems if the driver uses this as
3735a8a8045SSimon Glass 			 * both an input and an output buffer:
3745a8a8045SSimon Glass 			 *
3755a8a8045SSimon Glass 			 * 1. Zeroes written to buffer (here) and sit in the
3765a8a8045SSimon Glass 			 *	cache
3775a8a8045SSimon Glass 			 * 2. Driver issues a read command to DMA
3785a8a8045SSimon Glass 			 * 3. CPU runs out of cache space and evicts some cache
3795a8a8045SSimon Glass 			 *	data in the buffer, writing zeroes to RAM from
3805a8a8045SSimon Glass 			 *	the memset() above
3815a8a8045SSimon Glass 			 * 4. DMA completes
3825a8a8045SSimon Glass 			 * 5. Buffer now has some DMA data and some zeroes
3835a8a8045SSimon Glass 			 * 6. Data being read is now incorrect
3845a8a8045SSimon Glass 			 *
3855a8a8045SSimon Glass 			 * To prevent this, ensure that the cache is clean
3865a8a8045SSimon Glass 			 * within this range at the start. The driver can then
3875a8a8045SSimon Glass 			 * use normal flush-after-write, invalidate-before-read
3885a8a8045SSimon Glass 			 * procedures.
3895a8a8045SSimon Glass 			 *
3905a8a8045SSimon Glass 			 * TODO(sjg@chromium.org): Drop this microblaze
3915a8a8045SSimon Glass 			 * exception.
3925a8a8045SSimon Glass 			 */
3935a8a8045SSimon Glass #ifndef CONFIG_MICROBLAZE
3945a8a8045SSimon Glass 			flush_dcache_range((ulong)priv, (ulong)priv + size);
3955a8a8045SSimon Glass #endif
3965a8a8045SSimon Glass 		}
3972c03c463SSimon Glass 	} else {
3982c03c463SSimon Glass 		priv = calloc(1, size);
3992c03c463SSimon Glass 	}
4002c03c463SSimon Glass 
4012c03c463SSimon Glass 	return priv;
4022c03c463SSimon Glass }
4032c03c463SSimon Glass 
404c6db965fSSimon Glass int device_probe(struct udevice *dev)
4056494d708SSimon Glass {
4063479253dSSimon Glass 	const struct driver *drv;
4076494d708SSimon Glass 	int size = 0;
4086494d708SSimon Glass 	int ret;
4095a66a8ffSSimon Glass 	int seq;
4106494d708SSimon Glass 
4116494d708SSimon Glass 	if (!dev)
4126494d708SSimon Glass 		return -EINVAL;
4136494d708SSimon Glass 
4146494d708SSimon Glass 	if (dev->flags & DM_FLAG_ACTIVATED)
4156494d708SSimon Glass 		return 0;
4166494d708SSimon Glass 
4176494d708SSimon Glass 	drv = dev->driver;
4186494d708SSimon Glass 	assert(drv);
4196494d708SSimon Glass 
420cdeb2ba9SBin Meng 	/* Allocate private data if requested and not reentered */
421cdeb2ba9SBin Meng 	if (drv->priv_auto_alloc_size && !dev->priv) {
4222c03c463SSimon Glass 		dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags);
4236494d708SSimon Glass 		if (!dev->priv) {
4246494d708SSimon Glass 			ret = -ENOMEM;
4256494d708SSimon Glass 			goto fail;
4266494d708SSimon Glass 		}
4276494d708SSimon Glass 	}
428cdeb2ba9SBin Meng 	/* Allocate private data if requested and not reentered */
4296494d708SSimon Glass 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
430cdeb2ba9SBin Meng 	if (size && !dev->uclass_priv) {
4316494d708SSimon Glass 		dev->uclass_priv = calloc(1, size);
4326494d708SSimon Glass 		if (!dev->uclass_priv) {
4336494d708SSimon Glass 			ret = -ENOMEM;
4346494d708SSimon Glass 			goto fail;
4356494d708SSimon Glass 		}
4366494d708SSimon Glass 	}
4376494d708SSimon Glass 
4386494d708SSimon Glass 	/* Ensure all parents are probed */
4396494d708SSimon Glass 	if (dev->parent) {
440e59f458dSSimon Glass 		size = dev->parent->driver->per_child_auto_alloc_size;
441dac8db2cSSimon Glass 		if (!size) {
442dac8db2cSSimon Glass 			size = dev->parent->uclass->uc_drv->
443dac8db2cSSimon Glass 					per_child_auto_alloc_size;
444dac8db2cSSimon Glass 		}
445cdeb2ba9SBin Meng 		if (size && !dev->parent_priv) {
4462c03c463SSimon Glass 			dev->parent_priv = alloc_priv(size, drv->flags);
447e59f458dSSimon Glass 			if (!dev->parent_priv) {
448e59f458dSSimon Glass 				ret = -ENOMEM;
449e59f458dSSimon Glass 				goto fail;
450e59f458dSSimon Glass 			}
451e59f458dSSimon Glass 		}
452e59f458dSSimon Glass 
4536494d708SSimon Glass 		ret = device_probe(dev->parent);
4546494d708SSimon Glass 		if (ret)
4556494d708SSimon Glass 			goto fail;
456cdeb2ba9SBin Meng 
457cdeb2ba9SBin Meng 		/*
458cdeb2ba9SBin Meng 		 * The device might have already been probed during
459cdeb2ba9SBin Meng 		 * the call to device_probe() on its parent device
460cdeb2ba9SBin Meng 		 * (e.g. PCI bridge devices). Test the flags again
461cdeb2ba9SBin Meng 		 * so that we don't mess up the device.
462cdeb2ba9SBin Meng 		 */
463cdeb2ba9SBin Meng 		if (dev->flags & DM_FLAG_ACTIVATED)
464cdeb2ba9SBin Meng 			return 0;
4656494d708SSimon Glass 	}
4666494d708SSimon Glass 
4675a66a8ffSSimon Glass 	seq = uclass_resolve_seq(dev);
4685a66a8ffSSimon Glass 	if (seq < 0) {
4695a66a8ffSSimon Glass 		ret = seq;
4705a66a8ffSSimon Glass 		goto fail;
4715a66a8ffSSimon Glass 	}
4725a66a8ffSSimon Glass 	dev->seq = seq;
4735a66a8ffSSimon Glass 
474206d4d2bSSimon Glass 	dev->flags |= DM_FLAG_ACTIVATED;
475206d4d2bSSimon Glass 
47684d26e29SSimon Glass 	/*
47784d26e29SSimon Glass 	 * Process pinctrl for everything except the root device, and
4780379597eSSimon Glass 	 * continue regardless of the result of pinctrl. Don't process pinctrl
4790379597eSSimon Glass 	 * settings for pinctrl devices since the device may not yet be
4800379597eSSimon Glass 	 * probed.
48184d26e29SSimon Glass 	 */
4820379597eSSimon Glass 	if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
483d90a5a30SMasahiro Yamada 		pinctrl_select_state(dev, "default");
484d90a5a30SMasahiro Yamada 
48502c07b37SSimon Glass 	ret = uclass_pre_probe_device(dev);
48683c7e434SSimon Glass 	if (ret)
48783c7e434SSimon Glass 		goto fail;
48883c7e434SSimon Glass 
489a327dee0SSimon Glass 	if (dev->parent && dev->parent->driver->child_pre_probe) {
490a327dee0SSimon Glass 		ret = dev->parent->driver->child_pre_probe(dev);
491a327dee0SSimon Glass 		if (ret)
492a327dee0SSimon Glass 			goto fail;
493a327dee0SSimon Glass 	}
494a327dee0SSimon Glass 
495396e343bSSimon Glass 	if (drv->ofdata_to_platdata && dev_has_of_node(dev)) {
4966494d708SSimon Glass 		ret = drv->ofdata_to_platdata(dev);
4976494d708SSimon Glass 		if (ret)
4986494d708SSimon Glass 			goto fail;
4996494d708SSimon Glass 	}
5006494d708SSimon Glass 
5016494d708SSimon Glass 	if (drv->probe) {
5026494d708SSimon Glass 		ret = drv->probe(dev);
50302eeb1bbSSimon Glass 		if (ret) {
50402eeb1bbSSimon Glass 			dev->flags &= ~DM_FLAG_ACTIVATED;
5056494d708SSimon Glass 			goto fail;
5066494d708SSimon Glass 		}
50702eeb1bbSSimon Glass 	}
5086494d708SSimon Glass 
5096494d708SSimon Glass 	ret = uclass_post_probe_device(dev);
510206d4d2bSSimon Glass 	if (ret)
5116494d708SSimon Glass 		goto fail_uclass;
5126494d708SSimon Glass 
513c3ab9853SPeng Fan 	if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL)
514c3ab9853SPeng Fan 		pinctrl_select_state(dev, "default");
515c3ab9853SPeng Fan 
5166494d708SSimon Glass 	return 0;
5176494d708SSimon Glass fail_uclass:
518706865afSStefan Roese 	if (device_remove(dev, DM_REMOVE_NORMAL)) {
5196494d708SSimon Glass 		dm_warn("%s: Device '%s' failed to remove on error path\n",
5206494d708SSimon Glass 			__func__, dev->name);
5216494d708SSimon Glass 	}
5226494d708SSimon Glass fail:
523206d4d2bSSimon Glass 	dev->flags &= ~DM_FLAG_ACTIVATED;
524206d4d2bSSimon Glass 
5255a66a8ffSSimon Glass 	dev->seq = -1;
5266494d708SSimon Glass 	device_free(dev);
5276494d708SSimon Glass 
5286494d708SSimon Glass 	return ret;
5296494d708SSimon Glass }
5306494d708SSimon Glass 
53154c5d08aSHeiko Schocher void *dev_get_platdata(struct udevice *dev)
5326494d708SSimon Glass {
5336494d708SSimon Glass 	if (!dev) {
534964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
5356494d708SSimon Glass 		return NULL;
5366494d708SSimon Glass 	}
5376494d708SSimon Glass 
5386494d708SSimon Glass 	return dev->platdata;
5396494d708SSimon Glass }
5406494d708SSimon Glass 
541cdc133bdSSimon Glass void *dev_get_parent_platdata(struct udevice *dev)
542cdc133bdSSimon Glass {
543cdc133bdSSimon Glass 	if (!dev) {
54436d7cc17SSimon Glass 		dm_warn("%s: null device\n", __func__);
545cdc133bdSSimon Glass 		return NULL;
546cdc133bdSSimon Glass 	}
547cdc133bdSSimon Glass 
548cdc133bdSSimon Glass 	return dev->parent_platdata;
549cdc133bdSSimon Glass }
550cdc133bdSSimon Glass 
5515eaed880SPrzemyslaw Marczak void *dev_get_uclass_platdata(struct udevice *dev)
5525eaed880SPrzemyslaw Marczak {
5535eaed880SPrzemyslaw Marczak 	if (!dev) {
55436d7cc17SSimon Glass 		dm_warn("%s: null device\n", __func__);
5555eaed880SPrzemyslaw Marczak 		return NULL;
5565eaed880SPrzemyslaw Marczak 	}
5575eaed880SPrzemyslaw Marczak 
5585eaed880SPrzemyslaw Marczak 	return dev->uclass_platdata;
5595eaed880SPrzemyslaw Marczak }
5605eaed880SPrzemyslaw Marczak 
56154c5d08aSHeiko Schocher void *dev_get_priv(struct udevice *dev)
5626494d708SSimon Glass {
5636494d708SSimon Glass 	if (!dev) {
564964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
5656494d708SSimon Glass 		return NULL;
5666494d708SSimon Glass 	}
5676494d708SSimon Glass 
5686494d708SSimon Glass 	return dev->priv;
5696494d708SSimon Glass }
570997c87bbSSimon Glass 
571e564f054SSimon Glass void *dev_get_uclass_priv(struct udevice *dev)
572e564f054SSimon Glass {
573e564f054SSimon Glass 	if (!dev) {
574e564f054SSimon Glass 		dm_warn("%s: null device\n", __func__);
575e564f054SSimon Glass 		return NULL;
576e564f054SSimon Glass 	}
577e564f054SSimon Glass 
578e564f054SSimon Glass 	return dev->uclass_priv;
579e564f054SSimon Glass }
580e564f054SSimon Glass 
581bcbe3d15SSimon Glass void *dev_get_parent_priv(struct udevice *dev)
582e59f458dSSimon Glass {
583e59f458dSSimon Glass 	if (!dev) {
584964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
585e59f458dSSimon Glass 		return NULL;
586e59f458dSSimon Glass 	}
587e59f458dSSimon Glass 
588e59f458dSSimon Glass 	return dev->parent_priv;
589e59f458dSSimon Glass }
590e59f458dSSimon Glass 
591997c87bbSSimon Glass static int device_get_device_tail(struct udevice *dev, int ret,
592997c87bbSSimon Glass 				  struct udevice **devp)
593997c87bbSSimon Glass {
594997c87bbSSimon Glass 	if (ret)
595997c87bbSSimon Glass 		return ret;
596997c87bbSSimon Glass 
597997c87bbSSimon Glass 	ret = device_probe(dev);
598997c87bbSSimon Glass 	if (ret)
599997c87bbSSimon Glass 		return ret;
600997c87bbSSimon Glass 
601997c87bbSSimon Glass 	*devp = dev;
602997c87bbSSimon Glass 
603997c87bbSSimon Glass 	return 0;
604997c87bbSSimon Glass }
605997c87bbSSimon Glass 
606997c87bbSSimon Glass int device_get_child(struct udevice *parent, int index, struct udevice **devp)
607997c87bbSSimon Glass {
608997c87bbSSimon Glass 	struct udevice *dev;
609997c87bbSSimon Glass 
610997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
611997c87bbSSimon Glass 		if (!index--)
612997c87bbSSimon Glass 			return device_get_device_tail(dev, 0, devp);
613997c87bbSSimon Glass 	}
614997c87bbSSimon Glass 
615997c87bbSSimon Glass 	return -ENODEV;
616997c87bbSSimon Glass }
617997c87bbSSimon Glass 
618997c87bbSSimon Glass int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
619997c87bbSSimon Glass 			     bool find_req_seq, struct udevice **devp)
620997c87bbSSimon Glass {
621997c87bbSSimon Glass 	struct udevice *dev;
622997c87bbSSimon Glass 
623997c87bbSSimon Glass 	*devp = NULL;
624997c87bbSSimon Glass 	if (seq_or_req_seq == -1)
625997c87bbSSimon Glass 		return -ENODEV;
626997c87bbSSimon Glass 
627997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
628997c87bbSSimon Glass 		if ((find_req_seq ? dev->req_seq : dev->seq) ==
629997c87bbSSimon Glass 				seq_or_req_seq) {
630997c87bbSSimon Glass 			*devp = dev;
631997c87bbSSimon Glass 			return 0;
632997c87bbSSimon Glass 		}
633997c87bbSSimon Glass 	}
634997c87bbSSimon Glass 
635997c87bbSSimon Glass 	return -ENODEV;
636997c87bbSSimon Glass }
637997c87bbSSimon Glass 
638997c87bbSSimon Glass int device_get_child_by_seq(struct udevice *parent, int seq,
639997c87bbSSimon Glass 			    struct udevice **devp)
640997c87bbSSimon Glass {
641997c87bbSSimon Glass 	struct udevice *dev;
642997c87bbSSimon Glass 	int ret;
643997c87bbSSimon Glass 
644997c87bbSSimon Glass 	*devp = NULL;
645997c87bbSSimon Glass 	ret = device_find_child_by_seq(parent, seq, false, &dev);
646997c87bbSSimon Glass 	if (ret == -ENODEV) {
647997c87bbSSimon Glass 		/*
648997c87bbSSimon Glass 		 * We didn't find it in probed devices. See if there is one
649997c87bbSSimon Glass 		 * that will request this seq if probed.
650997c87bbSSimon Glass 		 */
651997c87bbSSimon Glass 		ret = device_find_child_by_seq(parent, seq, true, &dev);
652997c87bbSSimon Glass 	}
653997c87bbSSimon Glass 	return device_get_device_tail(dev, ret, devp);
654997c87bbSSimon Glass }
655997c87bbSSimon Glass 
656997c87bbSSimon Glass int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
657997c87bbSSimon Glass 				   struct udevice **devp)
658997c87bbSSimon Glass {
659997c87bbSSimon Glass 	struct udevice *dev;
660997c87bbSSimon Glass 
661997c87bbSSimon Glass 	*devp = NULL;
662997c87bbSSimon Glass 
663997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
664e160f7d4SSimon Glass 		if (dev_of_offset(dev) == of_offset) {
665997c87bbSSimon Glass 			*devp = dev;
666997c87bbSSimon Glass 			return 0;
667997c87bbSSimon Glass 		}
668997c87bbSSimon Glass 	}
669997c87bbSSimon Glass 
670997c87bbSSimon Glass 	return -ENODEV;
671997c87bbSSimon Glass }
672997c87bbSSimon Glass 
673132f9bfcSSimon Glass int device_get_child_by_of_offset(struct udevice *parent, int node,
674997c87bbSSimon Glass 				  struct udevice **devp)
675997c87bbSSimon Glass {
676997c87bbSSimon Glass 	struct udevice *dev;
677997c87bbSSimon Glass 	int ret;
678997c87bbSSimon Glass 
679997c87bbSSimon Glass 	*devp = NULL;
680132f9bfcSSimon Glass 	ret = device_find_child_by_of_offset(parent, node, &dev);
681997c87bbSSimon Glass 	return device_get_device_tail(dev, ret, devp);
682997c87bbSSimon Glass }
683a8981d4fSSimon Glass 
6842693047aSSimon Glass static struct udevice *_device_find_global_by_of_offset(struct udevice *parent,
6852693047aSSimon Glass 							int of_offset)
6862693047aSSimon Glass {
6872693047aSSimon Glass 	struct udevice *dev, *found;
6882693047aSSimon Glass 
689e160f7d4SSimon Glass 	if (dev_of_offset(parent) == of_offset)
6902693047aSSimon Glass 		return parent;
6912693047aSSimon Glass 
6922693047aSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
6932693047aSSimon Glass 		found = _device_find_global_by_of_offset(dev, of_offset);
6942693047aSSimon Glass 		if (found)
6952693047aSSimon Glass 			return found;
6962693047aSSimon Glass 	}
6972693047aSSimon Glass 
6982693047aSSimon Glass 	return NULL;
6992693047aSSimon Glass }
7002693047aSSimon Glass 
7012693047aSSimon Glass int device_get_global_by_of_offset(int of_offset, struct udevice **devp)
7022693047aSSimon Glass {
7032693047aSSimon Glass 	struct udevice *dev;
7042693047aSSimon Glass 
7052693047aSSimon Glass 	dev = _device_find_global_by_of_offset(gd->dm_root, of_offset);
7062693047aSSimon Glass 	return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
7072693047aSSimon Glass }
7082693047aSSimon Glass 
709a8981d4fSSimon Glass int device_find_first_child(struct udevice *parent, struct udevice **devp)
710a8981d4fSSimon Glass {
711a8981d4fSSimon Glass 	if (list_empty(&parent->child_head)) {
712a8981d4fSSimon Glass 		*devp = NULL;
713a8981d4fSSimon Glass 	} else {
714a8981d4fSSimon Glass 		*devp = list_first_entry(&parent->child_head, struct udevice,
715a8981d4fSSimon Glass 					 sibling_node);
716a8981d4fSSimon Glass 	}
717a8981d4fSSimon Glass 
718a8981d4fSSimon Glass 	return 0;
719a8981d4fSSimon Glass }
720a8981d4fSSimon Glass 
721a8981d4fSSimon Glass int device_find_next_child(struct udevice **devp)
722a8981d4fSSimon Glass {
723a8981d4fSSimon Glass 	struct udevice *dev = *devp;
724a8981d4fSSimon Glass 	struct udevice *parent = dev->parent;
725a8981d4fSSimon Glass 
726a8981d4fSSimon Glass 	if (list_is_last(&dev->sibling_node, &parent->child_head)) {
727a8981d4fSSimon Glass 		*devp = NULL;
728a8981d4fSSimon Glass 	} else {
729a8981d4fSSimon Glass 		*devp = list_entry(dev->sibling_node.next, struct udevice,
730a8981d4fSSimon Glass 				   sibling_node);
731a8981d4fSSimon Glass 	}
732a8981d4fSSimon Glass 
733a8981d4fSSimon Glass 	return 0;
734a8981d4fSSimon Glass }
7352ef249b4SSimon Glass 
736479728cbSSimon Glass struct udevice *dev_get_parent(struct udevice *child)
737479728cbSSimon Glass {
738479728cbSSimon Glass 	return child->parent;
739479728cbSSimon Glass }
740479728cbSSimon Glass 
74139de8433SSimon Glass ulong dev_get_driver_data(struct udevice *dev)
7422ef249b4SSimon Glass {
74339de8433SSimon Glass 	return dev->driver_data;
7442ef249b4SSimon Glass }
745b3670531SSimon Glass 
746cc73d37bSPrzemyslaw Marczak const void *dev_get_driver_ops(struct udevice *dev)
747cc73d37bSPrzemyslaw Marczak {
748cc73d37bSPrzemyslaw Marczak 	if (!dev || !dev->driver->ops)
749cc73d37bSPrzemyslaw Marczak 		return NULL;
750cc73d37bSPrzemyslaw Marczak 
751cc73d37bSPrzemyslaw Marczak 	return dev->driver->ops;
752cc73d37bSPrzemyslaw Marczak }
753cc73d37bSPrzemyslaw Marczak 
754b3670531SSimon Glass enum uclass_id device_get_uclass_id(struct udevice *dev)
755b3670531SSimon Glass {
756b3670531SSimon Glass 	return dev->uclass->uc_drv->id;
757b3670531SSimon Glass }
758c9cac3f8SPeng Fan 
759f9c370dcSPrzemyslaw Marczak const char *dev_get_uclass_name(struct udevice *dev)
760f9c370dcSPrzemyslaw Marczak {
761f9c370dcSPrzemyslaw Marczak 	if (!dev)
762f9c370dcSPrzemyslaw Marczak 		return NULL;
763f9c370dcSPrzemyslaw Marczak 
764f9c370dcSPrzemyslaw Marczak 	return dev->uclass->uc_drv->name;
765f9c370dcSPrzemyslaw Marczak }
766f9c370dcSPrzemyslaw Marczak 
767c5785673SSimon Glass bool device_has_children(struct udevice *dev)
768c5785673SSimon Glass {
769c5785673SSimon Glass 	return !list_empty(&dev->child_head);
770c5785673SSimon Glass }
771c5785673SSimon Glass 
772c5785673SSimon Glass bool device_has_active_children(struct udevice *dev)
773c5785673SSimon Glass {
774c5785673SSimon Glass 	struct udevice *child;
775c5785673SSimon Glass 
776c5785673SSimon Glass 	for (device_find_first_child(dev, &child);
777c5785673SSimon Glass 	     child;
778c5785673SSimon Glass 	     device_find_next_child(&child)) {
779c5785673SSimon Glass 		if (device_active(child))
780c5785673SSimon Glass 			return true;
781c5785673SSimon Glass 	}
782c5785673SSimon Glass 
783c5785673SSimon Glass 	return false;
784c5785673SSimon Glass }
785c5785673SSimon Glass 
786c5785673SSimon Glass bool device_is_last_sibling(struct udevice *dev)
787c5785673SSimon Glass {
788c5785673SSimon Glass 	struct udevice *parent = dev->parent;
789c5785673SSimon Glass 
790c5785673SSimon Glass 	if (!parent)
791c5785673SSimon Glass 		return false;
792c5785673SSimon Glass 	return list_is_last(&dev->sibling_node, &parent->child_head);
793c5785673SSimon Glass }
794f5c67ea0SSimon Glass 
795a2040facSSimon Glass void device_set_name_alloced(struct udevice *dev)
796a2040facSSimon Glass {
797fd1c2d9bSSimon Glass 	dev->flags |= DM_FLAG_NAME_ALLOCED;
798a2040facSSimon Glass }
799a2040facSSimon Glass 
800f5c67ea0SSimon Glass int device_set_name(struct udevice *dev, const char *name)
801f5c67ea0SSimon Glass {
802f5c67ea0SSimon Glass 	name = strdup(name);
803f5c67ea0SSimon Glass 	if (!name)
804f5c67ea0SSimon Glass 		return -ENOMEM;
805f5c67ea0SSimon Glass 	dev->name = name;
806a2040facSSimon Glass 	device_set_name_alloced(dev);
807f5c67ea0SSimon Glass 
808f5c67ea0SSimon Glass 	return 0;
809f5c67ea0SSimon Glass }
81073443b9eSMugunthan V N 
811911f3aefSSimon Glass bool device_is_compatible(struct udevice *dev, const char *compat)
81273443b9eSMugunthan V N {
81373443b9eSMugunthan V N 	const void *fdt = gd->fdt_blob;
81418aa8da9SMario Six 	ofnode node = dev_ofnode(dev);
81573443b9eSMugunthan V N 
81618aa8da9SMario Six 	if (ofnode_is_np(node))
81718aa8da9SMario Six 		return of_device_is_compatible(ofnode_to_np(node), compat, NULL, NULL);
81818aa8da9SMario Six 	else
81918aa8da9SMario Six 		return !fdt_node_check_compatible(fdt, ofnode_to_offset(node), compat);
82073443b9eSMugunthan V N }
82173443b9eSMugunthan V N 
82273443b9eSMugunthan V N bool of_machine_is_compatible(const char *compat)
82373443b9eSMugunthan V N {
82473443b9eSMugunthan V N 	const void *fdt = gd->fdt_blob;
82573443b9eSMugunthan V N 
82673443b9eSMugunthan V N 	return !fdt_node_check_compatible(fdt, 0, compat);
82773443b9eSMugunthan V N }
828