xref: /rk3399_rockchip-uboot/drivers/core/device.c (revision d00cf31c0f89c7aef53557b214f8ff9e6cd81d6a)
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 
device_bind_common(struct udevice * parent,const struct driver * drv,const char * name,void * platdata,ulong driver_data,ofnode node,uint of_platdata_size,struct udevice ** devp)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;
40d9da4b44SJoseph 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 
54d9da4b44SJoseph 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 
198d9da4b44SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB
199d9da4b44SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB_V2
200d9da4b44SJoseph Chen 	/*
201d9da4b44SJoseph Chen 	 * Put these U-Boot devices in the head of uclass device list for
202d9da4b44SJoseph Chen 	 * the primary get by uclass_get_device_xxx().
203d9da4b44SJoseph Chen 	 *
204d9da4b44SJoseph Chen 	 * device-list: U0, U1, U2, ... K0, K1, K2, ... (prior u-boot dev)
205d9da4b44SJoseph Chen 	 * device-list: K0, K1, K2, ... U0, U1, U2, ... (normal)
206d9da4b44SJoseph Chen 	 *
207d9da4b44SJoseph Chen 	 * U: u-boot dev
208d9da4b44SJoseph Chen 	 * K: kernel dev
209d9da4b44SJoseph Chen 	 */
210d9da4b44SJoseph Chen 	u32 i, prior_u_boot_uclass_id[] = {
211d9da4b44SJoseph Chen 		UCLASS_AHCI,		/* boot device */
212d9da4b44SJoseph Chen 		UCLASS_BLK,
213d9da4b44SJoseph Chen 		UCLASS_MMC,
214d9da4b44SJoseph Chen 		UCLASS_MTD,
215d9da4b44SJoseph Chen 		UCLASS_PCI,
216d9da4b44SJoseph Chen 		UCLASS_RKNAND,
217d9da4b44SJoseph Chen 		UCLASS_SPI_FLASH,
218d9da4b44SJoseph Chen 
219d9da4b44SJoseph Chen 		UCLASS_CRYPTO,		/* RSA security */
220d9da4b44SJoseph Chen 		UCLASS_FIRMWARE,	/* psci sysreset */
221d9da4b44SJoseph Chen 		UCLASS_RNG,		/* ramdom number */
222d9da4b44SJoseph Chen 		UCLASS_SYSCON,		/* grf, pmugrf */
223d9da4b44SJoseph Chen 		UCLASS_SYSRESET,	/* psci sysreset */
224d9da4b44SJoseph Chen 		UCLASS_WDT,		/* reliable sysreset */
225d9da4b44SJoseph Chen 	};
226d9da4b44SJoseph Chen 
227d9da4b44SJoseph Chen 	if (gd->flags & GD_FLG_KDTB_READY) {
228d9da4b44SJoseph Chen 		after_u_boot_dev = false;
229d9da4b44SJoseph Chen 		dev->flags |= DM_FLAG_KNRL_DTB;
230d9da4b44SJoseph Chen 
231d9da4b44SJoseph Chen 		for (i = 0; i < ARRAY_SIZE(prior_u_boot_uclass_id); i++) {
232d9da4b44SJoseph Chen 			if (drv->id == prior_u_boot_uclass_id[i]) {
233d9da4b44SJoseph Chen 				after_u_boot_dev = true;
234d9da4b44SJoseph Chen 				break;
235d9da4b44SJoseph Chen 			}
236d9da4b44SJoseph Chen 		}
237d9da4b44SJoseph Chen 
238d9da4b44SJoseph Chen 		/* no u-boot dev ? */
239d9da4b44SJoseph Chen 		if (!dev->uclass->u_boot_dev_head)
240d9da4b44SJoseph Chen 			dev->uclass->u_boot_dev_head = &uc->dev_head;
241d9da4b44SJoseph Chen 	} else {
242d9da4b44SJoseph Chen 		if (!dev->uclass->u_boot_dev_head)
243d9da4b44SJoseph Chen 			dev->uclass->u_boot_dev_head = &dev->uclass_node;
244d9da4b44SJoseph Chen 	}
245d9da4b44SJoseph Chen #else
246d9da4b44SJoseph Chen 	if (gd->flags & GD_FLG_KDTB_READY)
247d9da4b44SJoseph Chen 		dev->flags |= DM_FLAG_KNRL_DTB;
248d9da4b44SJoseph Chen #endif
249d9da4b44SJoseph Chen #endif
250d9da4b44SJoseph 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 
device_bind_with_driver_data(struct udevice * parent,const struct driver * drv,const char * name,ulong driver_data,ofnode node,struct udevice ** devp)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 
device_bind(struct udevice * parent,const struct driver * drv,const char * name,void * platdata,int of_offset,struct udevice ** devp)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 
device_bind_by_name(struct udevice * parent,bool pre_reloc_only,const struct driver_info * info,struct udevice ** devp)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 
alloc_priv(int size,uint flags)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 
device_probe(struct udevice * dev)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 
513*d00cf31cSCody Xie 	if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL) {
514*d00cf31cSCody Xie 		pinctrl_select_state(dev, "init");
515c3ab9853SPeng Fan 		pinctrl_select_state(dev, "default");
516*d00cf31cSCody Xie 	}
517c3ab9853SPeng Fan 
5186494d708SSimon Glass 	return 0;
5196494d708SSimon Glass fail_uclass:
520706865afSStefan Roese 	if (device_remove(dev, DM_REMOVE_NORMAL)) {
5216494d708SSimon Glass 		dm_warn("%s: Device '%s' failed to remove on error path\n",
5226494d708SSimon Glass 			__func__, dev->name);
5236494d708SSimon Glass 	}
5246494d708SSimon Glass fail:
525206d4d2bSSimon Glass 	dev->flags &= ~DM_FLAG_ACTIVATED;
526206d4d2bSSimon Glass 
5275a66a8ffSSimon Glass 	dev->seq = -1;
5286494d708SSimon Glass 	device_free(dev);
5296494d708SSimon Glass 
5306494d708SSimon Glass 	return ret;
5316494d708SSimon Glass }
5326494d708SSimon Glass 
dev_get_platdata(struct udevice * dev)53354c5d08aSHeiko Schocher void *dev_get_platdata(struct udevice *dev)
5346494d708SSimon Glass {
5356494d708SSimon Glass 	if (!dev) {
536964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
5376494d708SSimon Glass 		return NULL;
5386494d708SSimon Glass 	}
5396494d708SSimon Glass 
5406494d708SSimon Glass 	return dev->platdata;
5416494d708SSimon Glass }
5426494d708SSimon Glass 
dev_get_parent_platdata(struct udevice * dev)543cdc133bdSSimon Glass void *dev_get_parent_platdata(struct udevice *dev)
544cdc133bdSSimon Glass {
545cdc133bdSSimon Glass 	if (!dev) {
54636d7cc17SSimon Glass 		dm_warn("%s: null device\n", __func__);
547cdc133bdSSimon Glass 		return NULL;
548cdc133bdSSimon Glass 	}
549cdc133bdSSimon Glass 
550cdc133bdSSimon Glass 	return dev->parent_platdata;
551cdc133bdSSimon Glass }
552cdc133bdSSimon Glass 
dev_get_uclass_platdata(struct udevice * dev)5535eaed880SPrzemyslaw Marczak void *dev_get_uclass_platdata(struct udevice *dev)
5545eaed880SPrzemyslaw Marczak {
5555eaed880SPrzemyslaw Marczak 	if (!dev) {
55636d7cc17SSimon Glass 		dm_warn("%s: null device\n", __func__);
5575eaed880SPrzemyslaw Marczak 		return NULL;
5585eaed880SPrzemyslaw Marczak 	}
5595eaed880SPrzemyslaw Marczak 
5605eaed880SPrzemyslaw Marczak 	return dev->uclass_platdata;
5615eaed880SPrzemyslaw Marczak }
5625eaed880SPrzemyslaw Marczak 
dev_get_priv(struct udevice * dev)56354c5d08aSHeiko Schocher void *dev_get_priv(struct udevice *dev)
5646494d708SSimon Glass {
5656494d708SSimon Glass 	if (!dev) {
566964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
5676494d708SSimon Glass 		return NULL;
5686494d708SSimon Glass 	}
5696494d708SSimon Glass 
5706494d708SSimon Glass 	return dev->priv;
5716494d708SSimon Glass }
572997c87bbSSimon Glass 
dev_get_uclass_priv(struct udevice * dev)573e564f054SSimon Glass void *dev_get_uclass_priv(struct udevice *dev)
574e564f054SSimon Glass {
575e564f054SSimon Glass 	if (!dev) {
576e564f054SSimon Glass 		dm_warn("%s: null device\n", __func__);
577e564f054SSimon Glass 		return NULL;
578e564f054SSimon Glass 	}
579e564f054SSimon Glass 
580e564f054SSimon Glass 	return dev->uclass_priv;
581e564f054SSimon Glass }
582e564f054SSimon Glass 
dev_get_parent_priv(struct udevice * dev)583bcbe3d15SSimon Glass void *dev_get_parent_priv(struct udevice *dev)
584e59f458dSSimon Glass {
585e59f458dSSimon Glass 	if (!dev) {
586964d153cSSimon Glass 		dm_warn("%s: null device\n", __func__);
587e59f458dSSimon Glass 		return NULL;
588e59f458dSSimon Glass 	}
589e59f458dSSimon Glass 
590e59f458dSSimon Glass 	return dev->parent_priv;
591e59f458dSSimon Glass }
592e59f458dSSimon Glass 
device_get_device_tail(struct udevice * dev,int ret,struct udevice ** devp)593997c87bbSSimon Glass static int device_get_device_tail(struct udevice *dev, int ret,
594997c87bbSSimon Glass 				  struct udevice **devp)
595997c87bbSSimon Glass {
596997c87bbSSimon Glass 	if (ret)
597997c87bbSSimon Glass 		return ret;
598997c87bbSSimon Glass 
599997c87bbSSimon Glass 	ret = device_probe(dev);
600997c87bbSSimon Glass 	if (ret)
601997c87bbSSimon Glass 		return ret;
602997c87bbSSimon Glass 
603997c87bbSSimon Glass 	*devp = dev;
604997c87bbSSimon Glass 
605997c87bbSSimon Glass 	return 0;
606997c87bbSSimon Glass }
607997c87bbSSimon Glass 
device_get_child(struct udevice * parent,int index,struct udevice ** devp)608997c87bbSSimon Glass int device_get_child(struct udevice *parent, int index, struct udevice **devp)
609997c87bbSSimon Glass {
610997c87bbSSimon Glass 	struct udevice *dev;
611997c87bbSSimon Glass 
612997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
613997c87bbSSimon Glass 		if (!index--)
614997c87bbSSimon Glass 			return device_get_device_tail(dev, 0, devp);
615997c87bbSSimon Glass 	}
616997c87bbSSimon Glass 
617997c87bbSSimon Glass 	return -ENODEV;
618997c87bbSSimon Glass }
619997c87bbSSimon Glass 
device_find_child_by_seq(struct udevice * parent,int seq_or_req_seq,bool find_req_seq,struct udevice ** devp)620997c87bbSSimon Glass int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
621997c87bbSSimon Glass 			     bool find_req_seq, struct udevice **devp)
622997c87bbSSimon Glass {
623997c87bbSSimon Glass 	struct udevice *dev;
624997c87bbSSimon Glass 
625997c87bbSSimon Glass 	*devp = NULL;
626997c87bbSSimon Glass 	if (seq_or_req_seq == -1)
627997c87bbSSimon Glass 		return -ENODEV;
628997c87bbSSimon Glass 
629997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
630997c87bbSSimon Glass 		if ((find_req_seq ? dev->req_seq : dev->seq) ==
631997c87bbSSimon Glass 				seq_or_req_seq) {
632997c87bbSSimon Glass 			*devp = dev;
633997c87bbSSimon Glass 			return 0;
634997c87bbSSimon Glass 		}
635997c87bbSSimon Glass 	}
636997c87bbSSimon Glass 
637997c87bbSSimon Glass 	return -ENODEV;
638997c87bbSSimon Glass }
639997c87bbSSimon Glass 
device_get_child_by_seq(struct udevice * parent,int seq,struct udevice ** devp)640997c87bbSSimon Glass int device_get_child_by_seq(struct udevice *parent, int seq,
641997c87bbSSimon Glass 			    struct udevice **devp)
642997c87bbSSimon Glass {
643997c87bbSSimon Glass 	struct udevice *dev;
644997c87bbSSimon Glass 	int ret;
645997c87bbSSimon Glass 
646997c87bbSSimon Glass 	*devp = NULL;
647997c87bbSSimon Glass 	ret = device_find_child_by_seq(parent, seq, false, &dev);
648997c87bbSSimon Glass 	if (ret == -ENODEV) {
649997c87bbSSimon Glass 		/*
650997c87bbSSimon Glass 		 * We didn't find it in probed devices. See if there is one
651997c87bbSSimon Glass 		 * that will request this seq if probed.
652997c87bbSSimon Glass 		 */
653997c87bbSSimon Glass 		ret = device_find_child_by_seq(parent, seq, true, &dev);
654997c87bbSSimon Glass 	}
655997c87bbSSimon Glass 	return device_get_device_tail(dev, ret, devp);
656997c87bbSSimon Glass }
657997c87bbSSimon Glass 
device_find_child_by_of_offset(struct udevice * parent,int of_offset,struct udevice ** devp)658997c87bbSSimon Glass int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
659997c87bbSSimon Glass 				   struct udevice **devp)
660997c87bbSSimon Glass {
661997c87bbSSimon Glass 	struct udevice *dev;
662997c87bbSSimon Glass 
663997c87bbSSimon Glass 	*devp = NULL;
664997c87bbSSimon Glass 
665997c87bbSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
666e160f7d4SSimon Glass 		if (dev_of_offset(dev) == of_offset) {
667997c87bbSSimon Glass 			*devp = dev;
668997c87bbSSimon Glass 			return 0;
669997c87bbSSimon Glass 		}
670997c87bbSSimon Glass 	}
671997c87bbSSimon Glass 
672997c87bbSSimon Glass 	return -ENODEV;
673997c87bbSSimon Glass }
674997c87bbSSimon Glass 
device_get_child_by_of_offset(struct udevice * parent,int node,struct udevice ** devp)675132f9bfcSSimon Glass int device_get_child_by_of_offset(struct udevice *parent, int node,
676997c87bbSSimon Glass 				  struct udevice **devp)
677997c87bbSSimon Glass {
678997c87bbSSimon Glass 	struct udevice *dev;
679997c87bbSSimon Glass 	int ret;
680997c87bbSSimon Glass 
681997c87bbSSimon Glass 	*devp = NULL;
682132f9bfcSSimon Glass 	ret = device_find_child_by_of_offset(parent, node, &dev);
683997c87bbSSimon Glass 	return device_get_device_tail(dev, ret, devp);
684997c87bbSSimon Glass }
685a8981d4fSSimon Glass 
_device_find_global_by_of_offset(struct udevice * parent,int of_offset)6862693047aSSimon Glass static struct udevice *_device_find_global_by_of_offset(struct udevice *parent,
6872693047aSSimon Glass 							int of_offset)
6882693047aSSimon Glass {
6892693047aSSimon Glass 	struct udevice *dev, *found;
6902693047aSSimon Glass 
691e160f7d4SSimon Glass 	if (dev_of_offset(parent) == of_offset)
6922693047aSSimon Glass 		return parent;
6932693047aSSimon Glass 
6942693047aSSimon Glass 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
6952693047aSSimon Glass 		found = _device_find_global_by_of_offset(dev, of_offset);
6962693047aSSimon Glass 		if (found)
6972693047aSSimon Glass 			return found;
6982693047aSSimon Glass 	}
6992693047aSSimon Glass 
7002693047aSSimon Glass 	return NULL;
7012693047aSSimon Glass }
7022693047aSSimon Glass 
device_get_global_by_of_offset(int of_offset,struct udevice ** devp)7032693047aSSimon Glass int device_get_global_by_of_offset(int of_offset, struct udevice **devp)
7042693047aSSimon Glass {
7052693047aSSimon Glass 	struct udevice *dev;
7062693047aSSimon Glass 
7072693047aSSimon Glass 	dev = _device_find_global_by_of_offset(gd->dm_root, of_offset);
7082693047aSSimon Glass 	return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
7092693047aSSimon Glass }
7102693047aSSimon Glass 
device_find_first_child(struct udevice * parent,struct udevice ** devp)711a8981d4fSSimon Glass int device_find_first_child(struct udevice *parent, struct udevice **devp)
712a8981d4fSSimon Glass {
713a8981d4fSSimon Glass 	if (list_empty(&parent->child_head)) {
714a8981d4fSSimon Glass 		*devp = NULL;
715a8981d4fSSimon Glass 	} else {
716a8981d4fSSimon Glass 		*devp = list_first_entry(&parent->child_head, struct udevice,
717a8981d4fSSimon Glass 					 sibling_node);
718a8981d4fSSimon Glass 	}
719a8981d4fSSimon Glass 
720a8981d4fSSimon Glass 	return 0;
721a8981d4fSSimon Glass }
722a8981d4fSSimon Glass 
device_find_next_child(struct udevice ** devp)723a8981d4fSSimon Glass int device_find_next_child(struct udevice **devp)
724a8981d4fSSimon Glass {
725a8981d4fSSimon Glass 	struct udevice *dev = *devp;
726a8981d4fSSimon Glass 	struct udevice *parent = dev->parent;
727a8981d4fSSimon Glass 
728a8981d4fSSimon Glass 	if (list_is_last(&dev->sibling_node, &parent->child_head)) {
729a8981d4fSSimon Glass 		*devp = NULL;
730a8981d4fSSimon Glass 	} else {
731a8981d4fSSimon Glass 		*devp = list_entry(dev->sibling_node.next, struct udevice,
732a8981d4fSSimon Glass 				   sibling_node);
733a8981d4fSSimon Glass 	}
734a8981d4fSSimon Glass 
735a8981d4fSSimon Glass 	return 0;
736a8981d4fSSimon Glass }
7372ef249b4SSimon Glass 
dev_get_parent(struct udevice * child)738479728cbSSimon Glass struct udevice *dev_get_parent(struct udevice *child)
739479728cbSSimon Glass {
740479728cbSSimon Glass 	return child->parent;
741479728cbSSimon Glass }
742479728cbSSimon Glass 
dev_get_driver_data(struct udevice * dev)74339de8433SSimon Glass ulong dev_get_driver_data(struct udevice *dev)
7442ef249b4SSimon Glass {
74539de8433SSimon Glass 	return dev->driver_data;
7462ef249b4SSimon Glass }
747b3670531SSimon Glass 
dev_get_driver_ops(struct udevice * dev)748cc73d37bSPrzemyslaw Marczak const void *dev_get_driver_ops(struct udevice *dev)
749cc73d37bSPrzemyslaw Marczak {
750cc73d37bSPrzemyslaw Marczak 	if (!dev || !dev->driver->ops)
751cc73d37bSPrzemyslaw Marczak 		return NULL;
752cc73d37bSPrzemyslaw Marczak 
753cc73d37bSPrzemyslaw Marczak 	return dev->driver->ops;
754cc73d37bSPrzemyslaw Marczak }
755cc73d37bSPrzemyslaw Marczak 
device_get_uclass_id(struct udevice * dev)756b3670531SSimon Glass enum uclass_id device_get_uclass_id(struct udevice *dev)
757b3670531SSimon Glass {
758b3670531SSimon Glass 	return dev->uclass->uc_drv->id;
759b3670531SSimon Glass }
760c9cac3f8SPeng Fan 
dev_get_uclass_name(struct udevice * dev)761f9c370dcSPrzemyslaw Marczak const char *dev_get_uclass_name(struct udevice *dev)
762f9c370dcSPrzemyslaw Marczak {
763f9c370dcSPrzemyslaw Marczak 	if (!dev)
764f9c370dcSPrzemyslaw Marczak 		return NULL;
765f9c370dcSPrzemyslaw Marczak 
766f9c370dcSPrzemyslaw Marczak 	return dev->uclass->uc_drv->name;
767f9c370dcSPrzemyslaw Marczak }
768f9c370dcSPrzemyslaw Marczak 
device_has_children(struct udevice * dev)769c5785673SSimon Glass bool device_has_children(struct udevice *dev)
770c5785673SSimon Glass {
771c5785673SSimon Glass 	return !list_empty(&dev->child_head);
772c5785673SSimon Glass }
773c5785673SSimon Glass 
device_has_active_children(struct udevice * dev)774c5785673SSimon Glass bool device_has_active_children(struct udevice *dev)
775c5785673SSimon Glass {
776c5785673SSimon Glass 	struct udevice *child;
777c5785673SSimon Glass 
778c5785673SSimon Glass 	for (device_find_first_child(dev, &child);
779c5785673SSimon Glass 	     child;
780c5785673SSimon Glass 	     device_find_next_child(&child)) {
781c5785673SSimon Glass 		if (device_active(child))
782c5785673SSimon Glass 			return true;
783c5785673SSimon Glass 	}
784c5785673SSimon Glass 
785c5785673SSimon Glass 	return false;
786c5785673SSimon Glass }
787c5785673SSimon Glass 
device_is_last_sibling(struct udevice * dev)788c5785673SSimon Glass bool device_is_last_sibling(struct udevice *dev)
789c5785673SSimon Glass {
790c5785673SSimon Glass 	struct udevice *parent = dev->parent;
791c5785673SSimon Glass 
792c5785673SSimon Glass 	if (!parent)
793c5785673SSimon Glass 		return false;
794c5785673SSimon Glass 	return list_is_last(&dev->sibling_node, &parent->child_head);
795c5785673SSimon Glass }
796f5c67ea0SSimon Glass 
device_set_name_alloced(struct udevice * dev)797a2040facSSimon Glass void device_set_name_alloced(struct udevice *dev)
798a2040facSSimon Glass {
799fd1c2d9bSSimon Glass 	dev->flags |= DM_FLAG_NAME_ALLOCED;
800a2040facSSimon Glass }
801a2040facSSimon Glass 
device_set_name(struct udevice * dev,const char * name)802f5c67ea0SSimon Glass int device_set_name(struct udevice *dev, const char *name)
803f5c67ea0SSimon Glass {
804f5c67ea0SSimon Glass 	name = strdup(name);
805f5c67ea0SSimon Glass 	if (!name)
806f5c67ea0SSimon Glass 		return -ENOMEM;
807f5c67ea0SSimon Glass 	dev->name = name;
808a2040facSSimon Glass 	device_set_name_alloced(dev);
809f5c67ea0SSimon Glass 
810f5c67ea0SSimon Glass 	return 0;
811f5c67ea0SSimon Glass }
81273443b9eSMugunthan V N 
device_is_compatible(struct udevice * dev,const char * compat)813911f3aefSSimon Glass bool device_is_compatible(struct udevice *dev, const char *compat)
81473443b9eSMugunthan V N {
81573443b9eSMugunthan V N 	const void *fdt = gd->fdt_blob;
81618aa8da9SMario Six 	ofnode node = dev_ofnode(dev);
81773443b9eSMugunthan V N 
81818aa8da9SMario Six 	if (ofnode_is_np(node))
81918aa8da9SMario Six 		return of_device_is_compatible(ofnode_to_np(node), compat, NULL, NULL);
82018aa8da9SMario Six 	else
82118aa8da9SMario Six 		return !fdt_node_check_compatible(fdt, ofnode_to_offset(node), compat);
82273443b9eSMugunthan V N }
82373443b9eSMugunthan V N 
of_machine_is_compatible(const char * compat)82473443b9eSMugunthan V N bool of_machine_is_compatible(const char *compat)
82573443b9eSMugunthan V N {
82673443b9eSMugunthan V N 	const void *fdt = gd->fdt_blob;
82773443b9eSMugunthan V N 
82873443b9eSMugunthan V N 	return !fdt_node_check_compatible(fdt, 0, compat);
82973443b9eSMugunthan V N }
830